【Algorithm】Double Pointer Division Thought Wonderful Solution Moving Zero

insert image description here

Problem: 283. Moving zero

train of thought

First of all, let's talk about the idea of ​​this question

  • This question can mainly be classified into the question type of [Array Division/Array Blocking]. We divide all elements in an array into two intervals, with non-zero elements on the left and zero elements on the right

1.jpg

  • The first thing we think of to solve this kind of problem is [Double Pointer Algorithm]. Students who have studied C language should be able to know that pointers are more cumbersome and complicated. If you are interested in learning, you can check out my article link
  • But here we don't need to use int*this kind of pointer, but directly use the array subscript as a pointer

Ok, then let's take a look at what this double pointer is like and how to use it

  • The role of the two pointers
    • [cur]: scan the array from left to right, traverse the array
    • [dest]: the last position of the non-zero element in the processed range
  • It can be seen that curwe are used to traverse the array, from [cur, n - 1]is the element that has not been processed; then from [0, cur]is the element that has been processed, but the requirement of this question is that we have to divide [zero elements] and [non-zero elements], So we can divide the previous interval into [0, dest]and[dest + 1, cur - 1]

3.jpg

To sum up:

[0, dest] [dest + 1, cur - 1] [cur, n - 1]

  • [0, dest]- non-zero elements
  • [dest + 1, cur - 1]- zero element
  • [cur, n - 1]- unprocessed elements

Algorithm Diagram Analysis

Next, we will simulate the process of solving the problem by drawing an algorithm diagram

  • Let's take the first example given in the title as an example to explain, because we haven't processed any non-zero elements at the beginning, so there is no data for [0, cur - 1]this interval, so at the beginning we You can place the [dest] pointer at -1

4.jpg

  • Because we need to move the non-zero elements to the front, so if we encounter a 0 element, cur++just leave it at this position

5.jpg

  • Then when we encounter non-zero elements, we need to exchange them to the front, then our [0, dest]interval is used to store non-zero elements. If there is one more element at this time, destwe need to add 1, which originally points to - 1 this position, then we can use ++destto complete

6.jpg

  • Next, when the data is exchanged, we can compare the above three intervals, and we can find that the leftmost is a non-zero element, the middle is a 0 element, and the right is an element to be processed. Next we encounter 0 elements, socur++

7.jpg

  • curAfter moving back, we encountered a non-zero element again, continue to let it destgo up and exchange the elements at the two positions

8.jpg

  • Now let's look at these three intervals again. The left side is still [non-zero element], the middle is [0 element], and the right side is [pending element]

9.jpg

  • Then after encountering a non-zero element, continue to let ++dest, and then do the exchange

10.jpg

  • Finally, let's take a look at the entire range of elements after processing: the non-zero elements are all in the front, while the 0 elements are in the back, and [cur, n - 1]this section of the range does not exist, indicating that there are no more elements to be processed

11.jpg

the complexity

Next, let's analyze the space-time complexity of this question.

  • time complexity:

The core idea of ​​this algorithm refers to the interval division of [Quick Sort]. Here, in the process of continuously traversing the array, we use the middle 0 as the division, and then the left side is non-zero elements, and the right side is unprocessed elements. In the process of processing, we only traverse the array once, so the complexity is O ( n ) O(n)O ( n )

  • Space complexity:

In this question, we did not open up additional space, so the complexity is O ( 1 ) O(1)O(1)

Code

class Solution {
    
    
public:
    void moveZeroes(vector<int>& nums) {
    
    
        for(int dest = -1, cur = 0; cur < nums.size(); ++cur)
        {
    
    
            if(nums[cur] != 0)
            {
    
    
                swap(nums[++dest], nums[cur]);
            }
        }
    }
};

insert image description here

Guess you like

Origin blog.csdn.net/Fire_Cloud_1/article/details/132360761