• 图解算法——数组移动零


    1、题目描述

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

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/move-zeroes
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    2、示例

    示例1:

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

    说明:

    1. 必须在原数组上操作,不能拷贝额外的数组;
    2. 尽量减少操作次数。

    3、解题思路

    看到这道题,由于题目限制了不能有额外空间消耗,所以暴力法求解思路是:从前往后遍历(或从后往前遍历),遇到一个0,就进行类似 “冒泡” 排序的操作,将0 移动到数组最后。

    代码如下:

    class Solution {
        public void moveZeroes(int[] nums) {
            int l = 0;
            int r = nums.length-1;
            for(int i = r; i>=l; i--){
                if(nums[i] == 0){
                    for(int j = i; j<r; j++){
                        nums[j] = nums[j+1];
                    }
                    nums[r] = 0;
                    r--;
                }
            }
        }
    }

    问题似乎解决了,我们提交一下看看结果如何:

     果然,耗时是比较严重的,拖了后腿。

    因为在这里你的算法复杂度是O(N^2);

    那么有没有复杂度为O(n)的办法呢?

    当我们看到这里,不知道有没有思路想到“双指针”?

    是的,一般情况下,双指针就是解决数组元素交换问题的。但是有人说了,上面的思路不就是双指针嘛?

    是的,上面的思路也是双指针,不过不同的是,上面的思路是一左一右指针。左指针是固定的,不会变,只有右指针在变化。

    而下面这个思路是,左右指针都在变化。我们设定一左一右指针left 和 right,且初始值都是0。

    我们以right 为驱动,当right 下标所在位置不为0 时,我们交换left 和 right两个位置的数据,然后left++ 且 right ++;当right 下标处不为0 时,right ++。这里left 代表数组左侧第一次以0 开头元素下标(如:数组 [5,6,8,7,0,0,3],left就是下标为4的0元素),right 表示右侧遍历的下标。

    故,代码如下:

    class Solution {
        public void moveZeroes(int[] nums) {
            int n = nums.length, left = 0, right = 0;
            while (right < n) {
                if (nums[right] != 0) {
                    swap(nums, left, right);
                    left++;
                }
                right++;
            }
        }
    
        public void swap(int[] nums, int left, int right) {
            int temp = nums[left];
            nums[left] = nums[right];
            nums[right] = temp;
        }
    }

    提交看看:

     果然,由于时间复杂度的降低,耗时果然减少了许多。

    小结:

    注意在数组中双指针的使用。

    Over......

  • 相关阅读:
    instanceof方法
    Java 实现接口计算圆柱的体积和面积并添加颜色
    Java代码执行顺序
    Java饿汉单例模式
    斐波那契数(动态规划和递归)
    Java 接口实现计算器加减乘除(字符交互界面)
    局部内部类详解_转载
    Java引用类型
    递归打印字符串
    时间复杂度
  • 原文地址:https://www.cnblogs.com/gjmhome/p/15183053.html
Copyright © 2020-2023  润新知