LeetCode算法题 (Move Zores(移动零))Day5!!!C/C++

https://leetcode.cn/problems/move-zeroes/description/

一、题目描述

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

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

         今天的题目解题方法还是非常多的,我刚看到题目的时候本来想说用开辟一个新数组的方式来做这道题,但是题目要求必须在不复制数组的情况下原地对数组进行操作。不过不重要,条条大路通罗马嘛。(这里我就选择两种比较容易理解的方法分享给大家)

二、示例分析

示例 1:

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

示例 2:

输入: nums = [0]
输出: [0]

通过示例,简单来说就是把为0的元素统统放到数组的右边,不为0的元素统统放到数组的左边。

注意:本题有坑,但不大。再不为0的元素移动时记得要保持原本位置不变哦!

假设本题的数组元素为[0,1,0,3,2],那么最终的答案应该为[1,3,2,0,0];并非是从大到小排序!

三、解题思路&代码实现

题解一:

通过实例分析,我的初步想法是先判断数组前后的元素是否为0,如果第一个元素为0,后一个元素不为0,那么我们需要把这两个元素进行交换。

// 循环遍历数组nums,i从0开始,只要i + 1小于数组大小numsSize就继续循环
for (int i = 0; i + 1 < numsSize; i++) {
    // 检查当前元素nums[i]是否为0,且下一个元素nums[i + 1]不为0
    if (nums[i] == 0 && nums[i + 1]!= 0) {
          //一下三行为交换i和i+1的位置
          int t = nums[i];
          nums[i]=nums[i+1];
          nums[i+1]=t;
    }
}

那么解决了这一步,我们才刚刚解决了整理一次之后的结果,现在我们需要在for循环的外面再加上一个外层循环。

while(true)
{
    // 循环遍历数组nums,i从0开始,只要i + 1小于数组大小numsSize就继续循环
    for (int i = 0; i + 1 < numsSize; i++) {
        // 检查当前元素nums[i]是否为0,且下一个元素nums[i + 1]不为0
        if (nums[i] == 0 && nums[i + 1]!= 0) {
          //一下三行为交换i和i+1的位置
          int t = nums[i];
          nums[i]=nums[i+1];
          nums[i+1]=t;
        }
    }
}

嗯......循环是加上了,但是这里很多小伙伴应该一眼就能看出来,这不是死循环了吗?对,这就是死循环,完成题目我们还需要加上一个标志位,用来判断是否已经将数组里的所有为0的元素移动完毕。

// 无限循环,直到满足内部的退出条件才会跳出
while (true) {
    // 初始化一个标志变量flag为0,用于记录是否进行了交换操作
    int flag = 0;
    // 循环遍历数组nums,i从0开始,只要i + 1小于数组大小numsSize就继续循环
    for (int i = 0; i + 1 < numsSize; i++) {
        // 检查当前元素nums[i]是否为0,且下一个元素nums[i + 1]不为0
        if (nums[i] == 0 && nums[i + 1]!= 0) {
            // 如果满足条件,将flag加1,表示进行了一次交换操作
            flag++;
            int t = nums[i];
            nums[i]=nums[i+1];
            nums[i+1]=t;
        }
    }
    // 如果在一次完整的数组遍历中没有进行任何交换操作(flag为0),则跳出外部的while循环
    if (flag == 0)
        break;
}

这样题解1就顺利跑通了。

题解二:

题解二相对题解一来说,我个人是要感觉简单很多的,可以理解为直接写答案了。

整体的思路类似我发布的LeetCode算法题day1https://blog.youkuaiyun.com/m0_75144071/article/details/143021601?spm=1001.2014.3001.5502

这里链接给到大家,就不细讲了,感兴趣的小伙伴可以点击链接,查看一下!

整体代码如下:

// 函数功能:将数组中的零元素移动到数组末尾,保持非零元素的相对顺序不变
// 参数:
//   nums:指向整数数组的指针
//   numsSize:数组的大小
void moveZeroes(int* nums, int numsSize) {
    // j用于记录非零元素应放置的位置
    int j = 0;
    // 遍历整个数组
    for(int i = 0; i < numsSize; i++) {
        // 如果当前元素不为零
        if(nums[i]!= 0) {
            // 将非零元素放置到索引为j的位置,并将j向后移动一位
            nums[j++] = nums[i];
        }
    }
    // 将剩余位置(从j开始到数组末尾)填充为零
    for(; j < numsSize; j++) {
        nums[j] = 0;
    }
}

这个方法在时间复杂度上要比第一个好很多,这个算法可以达到O(N)

四、优化代码

        题解一中的while(true),我在这里其实是非常不建议大家使用的,除非大家是物联网相关专业的同学(这里懂得都懂😁😁😁)。在实际开发过程中,如果有可以代替while(true)的方法,大家一定不要选择while(true)。

我们可以把外层循环的while(true)修改成这样:

 // 外层循环从索引1开始,遍历数组
    for (int j = 1; j < numsSize; j++) {
        // 定义一个标志变量flag,初始值为true,表示尚未进行交换操作
        bool flag = true;
        // 内层循环用于检查数组中的相邻元素
        for (int i = 0; i + 1 < numsSize; i++) {
            // 如果当前元素为0且下一个元素不为0,则进行交换操作
            if (nums[i] == 0 && nums[i + 1]!= 0) {
                // 将标志变量flag设为false,表示进行了交换操作
                flag = false;
                // 将下一个非零元素赋值给当前位置
                nums[i] = nums[i + 1];
                // 将当前位置的下一个元素设为0
                nums[i + 1] = 0;
            }
        }
        // 如果在一次内层循环中没有进行交换操作(即flag为true),则跳出外层循环
        if (flag)
            break;
    }

        今天关于“Move Zeros(移动零)”算法问题的探讨就到这里啦。通过对这两个问题的深入分析,我们不仅掌握了具体的代码实现,还理解了背后的算法思路。希望这些内容能够帮助大家在算法学习的道路上更进一步,无论是应对面试中的算法题,还是提升自己的编程能力,都能有所裨益。算法的世界广阔而深邃,让我们一起保持探索的热情,不断挖掘其中的奥秘,期待下一次与大家分享更多精彩的算法知识!感谢大家的收看!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值