题目描述:
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
示例:
输入: [0,1,0,3,12]
输出: [1,3,12,0,0]
要求:
必须在原数组上操作,不能拷贝额外的数组。
尽量减少操作次数。
解题核心思想
移动零是一个很有用的技巧。接下来,讲下这个技巧的实现原理。
这里参考了快速排序的思想,快速排序首先要确定一个待分割的元素做中间点 x,然后把所有小于等于 x 的元素放到 x 的左边,大于 x 的元素放到其右边。
这里我们可以用0当做这个中间点,把不等于0(注意题目没说不能有负数)的放到中间点的左边,等于0的放到其右边。这的中间点就是0本身,所以实现起来比快速排序简单很多,我们使用两个指针 i
和 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
}
}
}
详细的讲解:
为了更加清楚的表达这道题的解题过程,我结合解题思想和代码,带大家一起来详细的将步骤表达出来。
首先,代码中的 j
对应 gif 图中的 b
,nums[i]
对应 gif 图中 a
;我们以 nums = [0,1,0,3,12]
为例,下面是详细的步骤:
-
i = 0,nums[i] = 0
, for循环继续 -
i = 1,nums[i] = 1
,此时j = 0
,nums[i]和nums[j]交换
,nums变成了 [1,0,0,3,12]
,j += 1
,继续for循环 -
i = 2,nums[i] = 0
,for循环继续 -
i = 3,nums[i] = 3
,此时j = 1
,nums[i]和nums[j]交换
,nums变成了 [1,3,0,0,12]
,j += 1
,继续for循环 -
i = 4,nums[i] = 12
,此时j = 2
,nums[i]和nums[j]交换
,nums变成了 [1,3,12,0,0]
,j += 1
,继续for循环 -
结束
通过这个例子的详细步骤,我们就可以很快的理解移动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自动化测试等,微信搜索公众号:“无量测试之道”,或扫描下方二维码:
添加关注,让我们一起共同成长!