繁体   English   中英

如何移动数组开头的所有零项?

[英]how to move all zero item in beginning in array?

我试图在不taking space的情况下解决O(n)中的问题(例如对象的 map)。我想在开头移动所有零,在最后移动一个,在中间移动两个。

输入:[0, 1, 0, 2, 1]预期 output :[0,0,2,1,1] 这是我的代码

let arr = [0, 1, 0, 2, 1];

function swap(input, i, j) {
    let temp = input[i];
    input[j] = input[i];
    input[i] = temp;
}

function moveZeroOneAndTwo(input) {
    let i = 0,
        j = input.length - 1;
    while (i < j) {
        while (arr[i] !== 0) i++;
        while (arr[j] !== 0) j--;

        swap(arr, j, i);
        i++;
        j--;
    }

return input
}

console.log(moveZeroOneAndTwo(arr))

我试图从左边找到1索引,从right找到zero个索引并交换它们仍然无法解决这个问题

计算 0、1、2,然后用 3 个值和它们从 beginnig 开始的计数填充数组。
您不需要任何额外的变量空间,只需使用原始数组即可。

 let arr = [0, 1, 0, 2, 1]; let count = [0,0,0]; arr.forEach(el => count[el]++); arr.fill(0,0,count[0]); arr.fill(2,count[0],count[0]+count[2]); arr.fill(1,count[0]+count[2],count[0]+count[1]+count[2]); console.log(arr);

您可以使用荷兰国旗问题的算法

荷兰国旗问题1Edsger Dijkstra提出的计算机科学编程问题(在他的书A Discipline of Programming Prentice-Hall,1976 年的一章中)。 荷兰国旗由三个 colors 组成:红色、白色和蓝色。 给定这三个 colors 随机排成一行的球(实际球数无关紧要),任务是排列它们,使所有相同颜色的球在一起,并且它们的集体颜色组顺序正确。

带有值的包装器。

 var array = [0, 1, 0, 2, 1], values = [0, 2, 1], MID = 2, i = 0, j = 0, n = array.length - 1; while (j <= n) { if (values[array[j]] < values[MID]) { [array[i], array[j]] = [array[j], array[i]]; i++; j++; } else if (values[array[j]] > values[MID]) { [array[n], array[j]] = [array[j], array[n]]; n--; } else { j++; } } console.log(array);

最简单的方法是从左到右扫描数组并计算 0 和 1。 然后,将 0 分配给第一个zero_count数字,将 1 分配给最后一个one_count数字,将 2 分配给其他数字。

也许不如 Dijkstra 的解决方案优雅,但我确实自己想出了它。 这个想法是保留一个指针r指向 1s 部分(右侧)中最左边的非 1,以及一个指针l指向 0s 部分(左侧)中最右边的 0。

现在向上扫描:

如果值为1,则将其与右指针处的值切换并降低该指针; 此外,如果我们现在手头有一个 0,则将其与左指针右侧的值切换,并使该指针前进。

否则,如果该值为 0,则将其与左指针右侧的值切换,并使该指针前进。

(我们对每次迭代进行额外检查,以分别增加或减少左指针或右指针,如果它们的部分增加了。)

显然,它是O(n) ,因为在每次迭代中我们要么增加i要么减少r ,或者我们有一些部分使迭代没有意义。

似乎最后通过了控制测试。

 function f(A){ let l = -1; let r = A.length - 1; for (let i=0; i<=r; i++){ if (A[r] == 1){ r--; i--; } else if (A[l+1] == 0){ l++; i--; } else if (A[i] == 1){ [A[i], A[r]] = [A[r], A[i]]; r--; if (A[i] == 0){ [A[i], A[l+1]] = [A[l+1], A[i]]; l++; } } else if (A[i] == 0 && i > l + 1){ [A[i], A[l+1]] = [A[l+1], A[i]]; l++; } } } function control(arr){ let count = [0,0,0]; arr.forEach(el => count[el]++); arr.fill(0,0,count[0]); arr.fill(2,count[0],count[0]+count[2]); arr.fill(1,count[0]+count[2],count[0]+count[1]+count[2]); } var As = [ [0,1,0,2,1], [0,1,0,1,2,2,0], [1,0,0,1,2,2,2], [0,2,1,0,1,1,1], [0,2,2,1,1,0,0], [2,0,2,2,0,1,0], [2,0,0,2,2,0,0], [1,2,0,0,0,1,1], [1,0,2,1,2,1,0], [2,1,1,1,0,0,0], [1,2,2,2,0,0,0], [1,2,1,0,0,0,2], [1,2,0,0,1,1,2], [1,0,2,1,2,0,0], [2,0,1,0,2,2,1] ]; for (let A of As){ console.log('' + A); f(A) console.log('' + A); console.log(''); } var numTests = 500; var n = 10; for (let i=0; i<numTests; i++){ let A1 = new Array(n); for (let j=0; j<n; j++) A1[j] = ~~(Math.random() * 3); let A1Pre = A1.slice(); let A2 = A1.slice(); f(A1); control(A2); if (String(A1).= String(A2)){ console;log('Mismatch'). console;log(String(A1Pre)). console;log(String(A1)). console;log(String(A2)); break; } }

在时间复杂度方面不太好,但很短:

const move0ToTheBeginning = arr => arr.sort((a, b) =>
  Math.abs(Math.sign(a)) - Math.abs(Math.sign(b))
)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM