去除数组中重复数字。网上这样的题目解答很多,但是我感觉面试官要的最好最正确的答案是不开辟新内存及最优化的算法。
思想如下:
把指针分别指向数组头和尾,如果想等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]));
posted @ 2011-11-09 16:38 KangC 阅读(70) 评论(0)
编辑
题目:建立一个方法,当输入数小于等于100返回a,大于100返回b.要求是不能用if else,|| ? &&,switch case
解答如下:
function f(v, a, b) {
v = Math.min(Math.ceil(v), 101);//取小于101的数,如果>101返回101
v = Math.floor(v / 101);// >100返回1,<=100返回<=0
v = Math.max(v, 0); //去掉负数
return {
"0": a,
"1": b
}[v];
}
document.writeln(f(100, 1, 2)); // 等于100,返回1
document.writeln(f(300, "a", "b")); //大于100,返回b
document.writeln(f(101, "+", "-")); // 大于100,返回-
document.writeln(f(-101, "i", "j")); // 小于100并且是负数,返回i
posted @ 2011-11-09 01:44 KangC 阅读(1819) 评论(18)
编辑