力扣最热一百题——4.移动零

目录

日常吐槽

[题目链接:283. 移动零 - 力扣(LeetCode)](#题目链接:283. 移动零 - 力扣(LeetCode))

题目描述

示例

提示

解法一:交换位置

思路

代码实现

解法二:覆写元素

思路

代码实现

总结



日常吐槽

今天本来是计划玩玩游戏的,结果我直接上头了,输一把赢一把的,唉,最后也没法从完美B+差三分上A,还到欠了四十多分才上A,我真的服了,话不多说直接上今天的题目吧。


题目链接:283. 移动零 - 力扣(LeetCode)

注:下述题目描述和示例均来自力扣

题目描述

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

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例

示例 1:

复制代码
输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]

示例 2:

复制代码
输入: nums = [0]
输出: [0]

提示

  • 1 <= nums.length <= 104
  • -231 <= nums[i] <= 231 - 1

**进阶:**你能尽量减少完成的操作次数吗?

呃不能。。。。。


这里题目有一个很关键的信息就是要在不复制数组的情况下对数组进行操作,也就是我们要在原数组上进行操作,不能新开一个数组,否则就太简单了,直接遍历一遍不要0就行了。并且记住要保持其他元素的相对顺序。

解法一:交换位置

思路

这个解法的思路就是我每次先找到一个0,这个0的位置是最靠前的一个0,然后在这个0的位置上往后找第一个不为零的元素,使用两个指针记录这两个数的位置,交换他们的位置即可,非常简单,思路也是很清晰的,交换完最后一个0之后,所有的0也就在后面了。

代码实现

java 复制代码
class Solution {
    public void moveZeroes(int[] nums) {
        // 0,1,0,3,12
        // l r
        // 1,0,0,3,12
        //  lr 
        // 1,3,12,0,0
        //      l   r
        // 获取数组的长度
        int len = nums.length;
        // 定义出两个指针
        int left = 0;
        int right = 1;
        // 进入寻找非0元素的过程
        // left记录0的位置,right记录第一个遇到的非零的位置
        while(left < len){
            // 结束特判
            if(right == len && nums[right - 1] == 0){
                break;
            }
            if(nums[left] == 0){
                while(right < len){
                    if(nums[right] != 0){
                        swap(nums,left,right);
                        left++;
                        right = left + 1;
                        break;
                    }else{
                        right++;
                    }
                }
            }else{
                left++;
                right++;
            }
        }
    }


    /**
        交换数组位置
    */
    public void swap(int[] arr,int left,int right){
        int temp = arr[left];
        arr[left] = arr[right];
        arr[right] = temp;
    }
}

说实话,虽然说这个方法比较好思考出来,但是利于人脑思考的方法最终的效果都是不尽人意的。


解法二:覆写元素

思路

这个解法的思路是将数组中的所有0移动到数组的末尾,而保持非零元素的相对顺序不变。

首先,定义两个指针 left 和 right,初始时都指向数组的开头。right 指针用于遍历数组,left 指针用于记录下一个非零元素应该存放的位置。

然后,开始遍历数组,当 right 指针指向的元素为0时,right 指针向右移动一位,跳过该次循环。这是因为我们要将所有的0移动到数组的末尾,所以需要忽略所有的0。

当 right 指针指向的元素不为0时,将该元素覆盖到 left 指针指向的位置,并将 left 指针向右移动一位,即 left++。这样,非零元素就被移动到了正确的位置上。

循环结束后,left 指针后面的元素都应该是0,所以我们再次遍历数组,将 left 指针后面的元素都设置为0。

最终的结果就是将所有的0移动到了数组的末尾,而非零元素的相对顺序保持不变。

代码实现

java 复制代码
class Solution {
    public void moveZeroes(int[] nums) {
        int left = 0;
        int right = 0;
        while(right < nums.length){
            if(nums[right] == 0){
                //这里就是right指针遇到0了
                //需要跳过这个数和跳过这次循环
                right++;
                continue;
            }
            //这里进行覆盖操作
            nums[left++] = nums[right++];
        }
        while(left < nums.length){
            nums[left++] = 0;
        }
    }
}

这个方法的执行效率和内存开销直接起飞了bro,遥遥领先。

总结

官方题解我觉得写得非常的难以理解,但是他确实是把交换的思路优化到极致了,以至于执行效率还是很快,所以这个世界上的万千代码和人一样,厉害的,你更难以洞察其内心。

相关推荐
M78佐菲42 分钟前
c语言学习笔记:排序与查找方法整理
linux·c语言·笔记·学习·算法
AI备案指南-满满3 小时前
人工智能拟人化互动服务安全自评估报告的评估要点有哪些?
人工智能·算法·安全·机器人·大模型备案·算法备案
土司大王4 小时前
LeetCode hot100——两两交换链表中的节点
算法·leetcode·职场和发展
大熊背5 小时前
树莓派IspPipeline LSC模块原理详解
算法·lsc·isppipeline·mesh lsc
测试19985 小时前
Selenium 无法定位元素的几种解决方案
自动化测试·软件测试·python·selenium·测试工具·职场和发展·测试用例
zander2586 小时前
LeetCode 300. 最长递增子序列
算法·leetcode·深度优先
欧叶冲冲冲6 小时前
Python常见数据结构的CRUD(LeetCode高频版速查)
数据结构·python·leetcode
祖力556 小时前
Linux应用软件编程:目录IO与framebuffer
linux·运维·算法·framebuffer·目录io
名字还没想好☜7 小时前
Go 用 slices/maps 标准库泛型函数:告别手写 Contains、Sort、去重(Go 1.21)
开发语言·后端·算法·golang·go