LintCode 539. 移动零


http://www.lintcode.com/zh-cn/problem/move-zeroes/


1.问题描述


给一个数组 nums写一个函数将0移动到数组的最后面,非零元素保持原数组的顺序

注意事项
1.必须在原数组上操作
2.最小化操作数


2.样例


给出 nums = [0, 1, 0, 3, 12], 调用函数之后, nums = [1, 3, 12, 0, 0].


3.问题解析


思路一:从头开始遍历数组,遇到数字0,将区间i + 1 ~ nums.length - count - 2的元素左移一位,统计数字0的个数:count。


public static void moveZeroes(int[] nums) {
    if(nums == null || nums.length <= 1) return;
    int count = 0;// 0的个数
    for(int i = 0;i < nums.length - count - 1;i++){
        if(nums[i] == 0){
            for(int j = i;j < nums.length - count - 1;j++){
                nums[j] = nums[j + 1];// 左移一位
            }
            nums[nums.length - count - 1] = 0;
            count++;
            i--;
        }
    }
}

这种解决方案,仅耗费一个整数的内存空间,测试在10万级别数据量以上,涉及到大量的数组元素左移,非常耗时间,测试10万的数据 : 900ms。


思路二:循环数组nums,用一个新的数组arr存储数字不为0的整数,最后用原生的数组拷贝将arr内存数据拷贝到nums。


public static void moveZeroes(int[] nums){
    if(nums == null || nums.length <= 1) return;
    int index = 0;
    int[] arr = new int[nums.length];
    for(int num : nums){
        if(num != 0) arr[index++] = num;
    }
    System.arraycopy(arr, 0, nums, 0, nums.length);
}

这种解决方案,需要耗费和数组nums同大小的内存空间:数组arr,仅一次遍历,时间复杂度O(n),测试10万的数据:2ms,1000万的数据 : 40ms。


思路三:循环数组nums,用一个新的数组zeroIndexs存储数字为0的整数的索引,数字0后的元素整体均只移动一次。


public static void moveZeroes(int[] nums){
        if(nums == null || nums.length <= 1) return;
        int count = 0;
        int[] zeroIndexs = new int[nums.length];
        for(int i = 0;i < nums.length;i++){
            if(nums[i] == 0){
                zeroIndexs[count++] = i;
            }
        }
        if(count == 0 || zeroIndexs[0] == nums.length - count) return;
        int step = 1;//元素左移的位数
        for(int i = 0;i < count - 1;i++){
            for(int j = zeroIndexs[i] + 1;j < zeroIndexs[i + 1];j++){
                nums[j - step] = nums[j];// 左移
            }
            step++;
        }
        // 最有一个区间,如果是右开放的区间,移动元素
        if(zeroIndexs[count - 1] != nums.length - 1){
            for(int i = zeroIndexs[count - 1] + 1;i < nums.length;i++){
                nums[i - step] = nums[i];
            }
        }
        // 元素移动完成,需要将右侧的元素设为0
        for(int i = nums.length - count;i < nums.length;i++){
            nums[i] = 0;
        }
    }

这种解决方案,需要耗费和数组nums同大小的内存空间:数组arr。时间复杂度O(n),测试10万的数据:4ms,1000万的数据 : 80ms。


4.测试数据


int[] nums = new int[10000000];
for(int i = 1;i <= 10000000;i++){
    nums[i - 1] = i % 2 == 0 ? 0 : i;       
}
long start = System.currentTimeMillis();
moveZeroes(nums);
System.out.println(System.currentTimeMillis() - start);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值