1 Array.prototype.findMaxAndMin = function () { 2 3 if (this.length == 0) return {min: null, max: null}; 4 5 var min, max, index = 0; //两个数之间的最大值,最小值 还有下标; 6 var temp_max, temp_min = 0; 7 8 //偶数 9 if (this.length % 2 == 0) { 10 if (this[0] > this[1]) { 11 max = this[0]; 12 min = this[1]; 13 } else { 14 min = this[0]; 15 max = this[1]; 16 } 17 index = 2; 18 } else { //奇数 19 min = this[0]; 20 max = this[0]; 21 index = 1; 22 } 23 24 //采用迭代 25 while (index < this.length - 1) { 26 if (this[index] < this[index + 1]) { 27 temp_max = this[index + 1]; 28 temp_min = this[index]; 29 } else { 30 temp_max = this[index]; 31 temp_min = this[index + 1]; 32 } 33 max = temp_max > max ? temp_max : max; 34 min = temp_min < min ? temp_min : min; 35 index += 2; 36 } 37 38 return {min: min, max: max}; 39 }; 40 41 var A = [16, 22, 2, 323320, 13, 3, 2321, 45546, 5766, 7, 23]; 42 console.log(A.findMaxAndMin());
1 Array.prototype.swap = function (i, j) { 2 var temp = this[i]; 3 this[i] = this[j]; 4 this[j] = temp; 5 }; 6 7 Array.prototype.RANDOM_PARTITION = function (p, r) { 8 console.log("p", p, "r", r); 9 var random = Math.round(p + Math.random() * (r -p)); 10 11 this.swap(random, r); 12 return this.PARTITION(p, r); 13 }; 14 15 Array.prototype.PARTITION = function (p, r) { 16 var x = this[r]; 17 var i = p - 1; 18 19 for (var j = p; j < r; j++) { 20 if (this[j] < x) { 21 this.swap(++i, j); 22 } 23 } 24 this.swap(r, ++i); 25 return i; 26 }; 27 28 Array.prototype.RONDOMIZED_SORT = function (p, r, i) { 29 if (p == r) return this[p]; 30 31 var q = this.RANDOM_PARTITION(p, r); 32 33 var k = q - p + 1; //计算A[p..q]一共有多少元素 34 35 if (i == k) return this[q]; 36 37 if (i < k) { 38 return arguments.callee.call(this, p, q - 1, i); //记住这里一定要加return 才会逐级往上返回。 39 } else { 40 return arguments.callee.call(this, q + 1, r, i - k); //因为所求在大端,我们已经知道k前面个数字是不符合的,所以要减去 41 } 42 }; 43 44 45 var A = [1, 2, 3, 4, 5, 3, 2, 1, 0, -1]; 46 47 console.log(A.RONDOMIZED_SORT(0, A.length - 1, 9));
RANDOMIZED-SELECT 算法采用快速排序算法的思想。区别是,快速排序会递归地处理划分的两边,而 RANDOMIZED-SELECT 则只处理一边。所以快速排序的期望运行时间是 Θ(n lg n),而 RANDOMIZED-SELECT 的期望运行时间为 Θ(n)。
RANDOMIZED-SELECT 的最坏运行时间为 Θ(n2),即使是要选择最小元素也是如此。因为它是随机化的,该算法的平均情况性能较好。
9.2-1 证明:在RANDOMIZED-SELECT中,对长度为0的数组,不会进行递归调用。
看上面的代码,从RANDOMIZED-SELECT函数知,长度为0的数组 p=r,那么直接返回A[p].不做下面的随机划分和递归调用。
9.2-3 给出RANDOMIZED-SELECT的一个基于迭代的版本。
1 Array.prototype.swap = function (i, j) { 2 var temp = this[i]; 3 this[i] = this[j]; 4 this[j] = temp; 5 }; 6 7 Array.prototype.RANDOM_PARTITION = function (p, r) { 8 9 var random = Math.round(p + Math.random() * (r - 1 - p)); 10 this.swap(random, r); 11 return this.PARTITION(p, r); 12 }; 13 14 Array.prototype.PARTITION = function (p, r) { 15 var x = this[r]; 16 var i = p - 1; 17 18 for (var j = p; j < r; j++) { 19 if (this[j] < x) { 20 this.swap(++i, j); 21 } 22 } 23 this.swap(r, ++i); 24 return i; 25 }; 26 27 Array.prototype.RANDOM_SELECT = function (p, r, i) { 28 var type = 0; 29 var q; //q左边的都比q小,反之都大于等于 30 var k; //A[p...r]子数组的元素个数 31 32 while (true) { 33 if (p == r) break; 34 q = this.RANDOM_PARTITION(p, r); 35 36 k = q - p + 1; 37 38 if (k == i) { 39 type = 1; 40 break; 41 } 42 43 if (i < k) { 44 r = q - 1; 45 } else { 46 p = q + 1; 47 } 48 49 } 50 return type ? this[q] : this[p]; 51 }; 52 53 54 var A = [1, 2, 3, 4, 5, 3, 2, 1, 0, -1]; 55 56 console.log(A.RANDOM_SELECT(0, A.length - 1, 2));
下面给出一个更简介的代码:
var A = [100, 122, 223, 334, 445, 556, 556, 666, 777]; var B = [9, 9, 9, 10, 11, 12, 13, 14, 15]; function getMedian(A, B) { while (true) { var n = A.length; if (n > 1) { if (A[Math.floor(n / 2)] > B[Math.floor(n / 2)]) { A = A.slice(0, Math.floor(n / 2) + 1); B = B.slice(Math.floor(n / 2), n + 1); } else { B = B.slice(0, Math.floor(n / 2) + 1); A = A.slice(Math.floor(n / 2), n + 1); } } else { return A[0] < B[0] ? A[0] : B[0]; } } } console.log(getMedian(A, B));