简体   繁体   English

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

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

I am trying to solve a problem in O(n) without taking space (like map of object).I want to shift all zeros in beginning, one's in last and two's in middle.我试图在不taking space的情况下解决O(n)中的问题(例如对象的 map)。我想在开头移动所有零,在最后移动一个,在中间移动两个。

input : [0, 1, 0, 2, 1] Expected output : [0,0,2,1,1] here is my code输入:[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))

I am trying to find 1 index from left and zero index from right and swap them still not able to solve this question我试图从左边找到1索引,从right找到zero个索引并交换它们仍然无法解决这个问题

Count the 0,1,2 and than fill the array with the 3 values and their counts from the beginnig..计算 0、1、2,然后用 3 个值和它们从 beginnig 开始的计数填充数组。
You don't need any aditional var-space and just use the original array.您不需要任何额外的变量空间,只需使用原始数组即可。

 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);

You could use the algorithm of the Dutch national flag problem您可以使用荷兰国旗问题的算法

The Dutch national flag problem 1 is a computer science programming problem proposed by Edsger Dijkstra (In a chapter of his book A Discipline of Programming Prentice-Hall, 1976).荷兰国旗问题1Edsger Dijkstra提出的计算机科学编程问题(在他的书A Discipline of Programming Prentice-Hall,1976 年的一章中)。 The flag of the Netherlands consists of three colors: red, white and blue.荷兰国旗由三个 colors 组成:红色、白色和蓝色。 Given balls of these three colors arranged randomly in a line (the actual number of balls does not matter), the task is to arrange them such that all balls of the same color are together and their collective color groups are in the correct order.给定这三个 colors 随机排成一行的球(实际球数无关紧要),任务是排列它们,使所有相同颜色的球在一起,并且它们的集体颜色组顺序正确。

with a wrapper for the values.带有值的包装器。

 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);

The easiest way is to scan the array from left to right and count both 0s and 1s.最简单的方法是从左到右扫描数组并计算 0 和 1。 Then, assign 0 to the first zero_count number, 1 to the last one_count number and 2 to the others.然后,将 0 分配给第一个zero_count数字,将 1 分配给最后一个one_count数字,将 2 分配给其他数字。

Perhaps not as elegant as Dijkstra's solution but I did come up with it myself.也许不如 Dijkstra 的解决方案优雅,但我确实自己想出了它。 The idea is to keep one pointer, r , to the leftmost non-1 in the 1s section (on the right), and one pointer, l , to the rightmost 0 in the 0s section (on the left).这个想法是保留一个指针r指向 1s 部分(右侧)中最左边的非 1,以及一个指针l指向 0s 部分(左侧)中最右边的 0。

Now scan up:现在向上扫描:

If the value is 1, switch it with the value at the right pointer and lower that pointer;如果值为1,则将其与右指针处的值切换并降低该指针; additionally, if we now have a 0 in hand, switch it with the value to the right of the left pointer and advance that pointer.此外,如果我们现在手头有一个 0,则将其与左指针右侧的值切换,并使该指针前进。

Otherwise, if the value is 0, switch it with the value to the right of the left pointer and advance that pointer.否则,如果该值为 0,则将其与左指针右侧的值切换,并使该指针前进。

(We have an additional check on each iteration to also increment or decrement the left or right pointers, respectively, if their section has increased.) (我们对每次迭代进行额外检查,以分别增加或减少左指针或右指针,如果它们的部分增加了。)

Clearly, it is O(n) since at every iteration we either increase i or decrease r , or we have sections that have made the iteration moot.显然,它是O(n) ,因为在每次迭代中我们要么增加i要么减少r ,或者我们有一些部分使迭代没有意义。

Seems to pass the control testing at the end.似乎最后通过了控制测试。

 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; } }

Not so good at time complexity, but short:在时间复杂度方面不太好,但很短:

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