去除數組中重複數字。網上這樣的題目解答很多,但是我感覺面試官要的最好最正確的答案是不開闢新記憶體及最佳化的演算法。
思想如下:
把指標分別指向數組頭和尾,如果想等j--,i和{i+1,j}之間的資料做比較,如果想等和j位置上的資料做交換,如果j位置上的數字和i想等j--,直到和不想等j位置上的資料做交換,i++繼續迴圈,當 i=j 時結束,見:
第一次:[1,47,89,1,18,1,47,6,90,77,50,88,89,89,0,6,1]
i j
第二次:[1,47,89,6,18,0,47,6,90,77,50,88,89,89,1,1,1]
i j
第三次:[1,47,89,6,18,0,89,6,90,77,50,88,89,47,1,1,1]
i j
第四次:[1,47,89,6,18,0,88,6,90,77,50,89,89,47,1,1,1]
i j
完成: [1,47,89,6,18,0,88,6,90,77,50,89,89,47,1,1,1]
ij
代碼如下:
function f(arr) {
var i = 0, j = arr.length - 1;
while (i != j) {
for (; i < j; i++) {
for (var z = i+1; z <= j; z++) {
if (arr[i] == arr[z]) {
while (arr[z] == arr[j]) { // 去除j位置上和當前比較數想等的數字。
j--;
arr.pop();
}
arr[z] = arr[j] ^ arr[z];
arr[j] = arr[j] ^ arr[z];
arr[z] = arr[j] ^ arr[z];
j--;
arr.pop();
}
}
}
}
return arr; // 不用pop這裡可以用arr.slice(0,i);
}
alert(f([1,47,89,1,18,1,47,6,90,77,50,88,89,89,0,6,1]));
但上述方法比較的次數是 n2-1次 ,顯然演算法不是很最佳化。
演算法最佳化
function f(arr) {
var nArr = new Array();
nArr.push(arr.pop());
while(arr.length)
nArr = t(nArr, arr.pop());
return nArr;
}
function t(arr, v) {
var len = arr.length;
if (len == 1 && arr[0] == v)
return arr;
else if (len == 1 && arr[0] < v) {
arr.push(v);
return arr;
}
else if (len == 1 && arr[0] > v)
return [v].concat(arr);
var i = Math.ceil(len / 2);
if (arr[i] > v) // 大於進入左葉比較
return t(arr.slice(0, i), v).concat(arr.slice(i, arr.length));
if (arr[i] < v)// 小於進入右葉比較
return arr.slice(0, i).concat(t(arr.slice(i, arr.length), v));
return arr;
}
alert(f([3,2,1,2,11,3,3,77,88,99,99,100,3,77]));