• LeetCode 283.移动零:一个非常有用的技巧


    题目描述:

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

    示例:

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

    要求:

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

    解题核心思想

      移动零是一个很有用的技巧。接下来,讲下这个技巧的实现原理。
      这里参考了快速排序的思想,快速排序首先要确定一个待分割的元素做中间点 x,然后把所有小于等于 x 的元素放到 x 的左边,大于 x 的元素放到其右边。
      这里我们可以用0当做这个中间点,把不等于0(注意题目没说不能有负数)的放到中间点的左边,等于0的放到其右边。这的中间点就是0本身,所以实现起来比快速排序简单很多,我们使用两个指针 和 j,只要 nums[i]!=0,我们就交换 nums[i] 和 nums[j]
    可以看下下面的gif图:

    代码:

     func moveZeroes(_ nums: inout [Int]) {
            if nums.count == 0 { return }
            var j = 0
            for i in 0..<nums.count {
                if nums[i] != 0 {
                    let temp = nums[i]
                    nums[i] = nums[j]
                    nums[j] = temp
                    j += 1
                }
            }
        }

    详细的讲解:

      为了更加清楚的表达这道题的解题过程,我结合解题思想和代码,带大家一起来详细的将步骤表达出来。
      首先,代码中的 对应 gif 图中的 bnums[i] 对应 gif 图中 ;我们以 nums = [0,1,0,3,12]为例,下面是详细的步骤:

    1. i = 0,nums[i] = 0, for循环继续

    2. i = 1,nums[i] = 1,此时j = 0,nums[i]和nums[j]交换nums变成了 [1,0,0,3,12],j += 1,继续for循环

    3. i = 2,nums[i] = 0,for循环继续

    4. i = 3,nums[i] = 3,此时j = 1,nums[i]和nums[j]交换nums变成了 [1,3,0,0,12],j += 1,继续for循环

    5. i = 4,nums[i] = 12,此时j = 2,nums[i]和nums[j]交换nums变成了 [1,3,12,0,0],j += 1,继续for循环

    6. 结束

      通过这个例子的详细步骤,我们就可以很快的理解移动0这个算法思想是什么了。为什么说这个移动0的思想很有用了,你们看下面这个题,

    给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

    示例:

    输入:nums = [2,0,2,1,1,0]
    输出:[0,0,1,1,2,2]

       这个题,看起来很麻烦,但是其本质就是【移动0】。解题代码如下:
      思想:移动2、和移动1,就是把全是2的移动到最后,再把全是1的移动到最后,得到就是结果啦。

    func sortColors(_ nums: inout [Int]) {
            if nums.count == 0 { return }
            var blue = 0
            var white = 0
            for i in 0..<nums.count {
                if nums[i] != 2 {
                    let temp = nums[blue]
                    nums[blue] = nums[i]
                    blue += 1
                    nums[i] = temp
                }
            }
    
            for i in 0..<blue {
                if nums[i] != 1 {
                    let temp = nums[white]
                    nums[white] = nums[i]
                    white += 1
                    nums[i] = temp
                }
            }
        }

    总结:

    今天主要讲解了移动0这道题的解法,讲这道题的原因是,因为这道题不仅是一道题目,更是一种解题技巧和思想。大家一定要掌握哦。希望帮助到大家。

    欢迎关注【无量测试之道】公众号,回复【领取资源】
    Python编程学习资源干货、
    Python+Appium框架APP的UI自动化、
    Python+Selenium框架Web的UI自动化、
    Python+Unittest框架API自动化、
    资源和代码 免费送啦~
    文章下方有公众号二维码,可直接微信扫一扫关注即可。

    备注:我的个人公众号已正式开通,致力于测试技术的分享,包含:大数据测试、功能测试,测试开发,API接口自动化、测试运维、UI自动化测试等,微信搜索公众号:“无量测试之道”,或扫描下方二维码:

    添加关注,让我们一起共同成长!

  • 相关阅读:
    让Controller支持对平铺参数执行@Valid数据校验
    @Validated和@Valid的区别?校验级联属性(内部类)
    Apache和Spring提供的StopWatch执行时间监视器
    Spring方法级别数据校验:@Validated + MethodValidationPostProcessor
    疑问
    第20章 链接详解(笔记)
    nm命令介绍
    使用Euclid算法求最大公约数
    Linux Man手册的使用示例
    VMware12 + Ubuntu16.04 虚拟磁盘扩容
  • 原文地址:https://www.cnblogs.com/Wu13241454771/p/15157612.html
Copyright © 2020-2023  润新知