LeetCode—— 移动零

2020-01-31  本文已影响0人  Minority

题目描述

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

示例:

输入: [0,1,0,3,12]
输出: [1,3,12,0,0]
说明:

必须在原数组上操作,不能拷贝额外的数组。
尽量减少操作次数。
一、CPP
1. 双指针法:

解题思路:使用两个指针,指针 i 负责遍历数组,指针 j 负责其后的元素均不为0。当指针 i 处的元素不为0时,才与 j 处的元素交换。
时间复杂度:O(n)。
空间复杂度:O(1)。

class Solution {
public:
    void moveZeroes(vector<int>& nums) {

        int j = -1;
        for(int i = 0; i < nums.size(); i++){
            if(nums[i] != 0){    
                j++;
                int temp = nums[i];
                nums[i] = nums[j];
                nums[j] = temp;
            }
        }

        for(int i=0;i<nums.size();i++){
            cout<<nums[i];
        }
        
    }
};
if(nums[i] != 0){
      j++;
      //也可以用if(i!=j)
      if(nums[j] ==0){
            int temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
      }             
}
2. 单指针覆盖法:

解题思路:和双指针思想类似。不同点在于单指针的 i 总是比 j 快,当 i 不为0时总是覆盖 j 位置的数,最后再在末尾补0。
时间复杂度:O(n)。
空间复杂度:O(1)。

class Solution {
public:
    void moveZeroes(vector<int>& nums) {

        int length = nums.size();
        int j = 0;

        for(int i : nums){
            if(i != 0){
                nums[j++] = i;
            }
        }
        //补0
        while(j<length){
            nums[j++] =0;
        }
        
    }
};
3. 辅助数组法:

解题思路:先计算0的个数,然后把不为0的数复制到辅助数组中,最后补上0的个数。然后把辅助数组的值赋值给原数组。
时间复杂度:O(n)。
空间复杂度:O(n)。题目要求在原数组上进行操作,不合题意。

class Solution {
public:

    void moveZeroes(vector<int>& nums) {
            int n = nums.size();

            // Count the zeroes
            int numZeroes = 0;
            for (int i = 0; i < n; i++) {
                numZeroes += (nums[i] == 0);
            }

            // Make all the non-zero elements retain their original order.
            vector<int> ans;
            for (int i = 0; i < n; i++) {
                if (nums[i] != 0) {
                    ans.push_back(nums[i]);
                }
            }

            // Move all zeroes to the end
            while (numZeroes--) {
                ans.push_back(0);
            }

            // Combine the result
            for (int i = 0; i < n; i++) {
                nums[i] = ans[i];
            }
        }

};

!!! 错误的做法:

解题思路:遍历数组,当遇到0时把其向后移动。这种方法的时间复杂度比较高,而且对于[1,2,8,0,0,7,4]的测试用例也行不通。
时间复杂度:O(n2)。
空间复杂度:O(1)

#include <iostream>
#include <vector>
using namespace std;

int main()
{   int nums [] ={1,2,8,0,0,7,4};

    int length = sizeof(nums)/sizeof(nums[0]);
    int right = length;
    int tmp;

    for(int i=0;i<length;i++){
        if(nums[i] == 0){
            for(int j = i;j<right;j++){
                tmp = nums[j];
                nums[j] = nums[j+1];
                nums[j+1] = tmp;
            }
            right--;
            
        }
    }

    for(int i=0;i<length;i++){
        cout<<nums[i];
    }
    return 0;
}

二、Java(双指针法)
class Solution {
    public void moveZeroes(int[] nums) {

        int j = -1;

        for(int i = 0;i<nums.length;i++){
            
            //等于0时直接移动i,j不动
            if(nums[i]!= 0){
                j++;
                //如果i,j指向的不是同一个
                if(i != j){
                    int tmp = nums[j];
                    nums[j] = nums[i];
                    nums[i] = tmp;
                }
            }          
        }    

    
    }
}
三、Python(双指针法)
class Solution(object):
    def moveZeroes(self, nums):
        """
        :type nums: List[int]
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        j = -1

        for i in range(len(nums)):
            if nums[i] != 0:
                # python不可以j++
                j += 1;
                if i!=j:
                    nums[i],nums[j] = nums[j],nums[i]
四、各语言及算法时间复杂度
各语言及算法时间复杂度
上一篇下一篇

猜你喜欢

热点阅读