难度:⭐
题目描述:
给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
示例1:
1 | 输入: [0,1,0,3,12] |
说明:
- 必须在原数组上操作,不能拷贝额外的数组。
- 尽量减少操作次数。
解题过程:
思路:
遍历数组,删除元素0然后在末尾添加一个元素0,注意删除元素后数组元素的索引。
c++代码:(执行用时24ms,击败10.55%,内存消耗9.1M,击败22.73%)
1 | class Solution { |
官方题解:
方法一:双指针
思路及解法
使用双指针,左指针指向当前已经处理好的序列的尾部,右指针指向待处理序列的头部。
右指针不断向右移动,每次右指针指向非零数,则将左右指针对应的数交换,同时左指针右移。
注意到以下性质:
左指针左边均为非零数;
右指针左边直到左指针处均为零。
因此每次交换,都是将左指针的零与右指针的非零数交换,且非零数的相对顺序并未改变。
c++代码:(执行用时12ms,击败49.15%,内存消耗9.2M,击败10.44%)
1 | class Solution { |
复杂度分析
- 时间复杂度:$O(n)$,其中 $n$ 为序列长度。每个位置至多被遍历两次。
- 空间复杂度:$O(1)$。只需要常数的空间存放若干变量。
总结:
自己的方法效率还是不行,vector容器删除和插入元素比较慢(需要前后元素前移或后移),优势是查找元素比较快(下表索引),所以自己使用的erase()函数和emplace_back()函数效率都不太高。而官方题解使用的是双指针还挺巧妙的,将左指针指向的零与右指针指向的非零数交换。双指针方法还挺常用的,以后多多使用吧。