LeetCode双指针专题-一个原数组,一个新数组
相关题目
LeetCode27.移除元素
题目
给你一个数组 nums
和一个值 val
,你需要原地移除所有数值等于 val
的元素。元素的顺序可能发生改变。然后返回 nums
中与 val
不同的元素的数量。
假设 nums
中不等于 val
的元素数量为k
,要通过此题,您需要执行以下操作:
- 更改
nums
数组,使nums
的前k
个元素包含不等于val
的元素。nums
的其余元素和nums
的大小并不重要。 - 返回
k
。
示例:
输入: nums = [3,2,2,3], val = 3 |
提示:
0 <= nums.length <= 100
0 <= nums[i] <= 50
0 <= val <= 100
解法
- 双指针法:
fast
:遍历数组,负责查找有效数字;slow
:标记新数组的位置,覆盖无效元素。
- 如果
nums[fast] != val
,则将nums[fast]
移动到nums[slow]
,然后slow++
。 - 遍历完成后,
slow
的值就是新数组的长度。
时间复杂度: O(n)
空间复杂度:O(1)
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slow = 0;
for (int fast = 0; fast < nums.size(); fast++) {
if (nums[fast] != val) {
nums[slow++] = nums[fast];
}
}
return slow;
}
};
LeetCode26.删除有序数组中的重复项
题目
给你一个 非严格递增排列 的数组 nums
,请你原地删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums
中唯一元素的个数。
考虑 nums
的唯一元素的数量为 k
,你需要做以下事情确保你的题解可以被通过:
- 更改数组
nums
,使nums
的前k
个元素包含唯一元素,并按照它们最初在nums
中出现的顺序排列。nums
的其余元素与nums
的大小不重要。 - 返回
k
。
示例 1:输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
解释:函数应该返回新的长度 2,并且原数组 nums 的前两个元素被修改为 1 和 2。无需考虑数组中超出新长度后面的元素。
示例 2:输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4,_,_,_,_,_]
提示:
1 <= nums.length <= 3 * 104
-104 <= nums[i] <= 104
nums
已按 非严格递增 排列
解法
考虑到题目中提及是有序数组,所有可以使用下述方法
- 双指针法:
fast
:遍历数组,查找新数组的元素;slow
:指向新数组的结尾元素。
- 如果
nums[fast] != nums[slow]
,就说明找到了新的元素,slow++
,然后将将nums[fast]
移动到nums[slow]
- 遍历完成后,
slow + 1
的值就是新数组的长度。
时间复杂度: O(n)
空间复杂度:O(1)
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int slow = 0;//新数组的末尾
for (int fast = 1; fast < nums.size(); fast++) {
if (nums[fast] != nums[slow]) {//找到新元素
slow++;
nums[slow] = nums[fast];
}
}
return slow + 1;
}
};
LeetCode80.删除有序数组中的重复项
题目
给你一个有序数组 nums
,请你原地删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组** 并在使用 O(1) 额外空间的条件下完成。
示例 1:输入:nums = [1,1,1,2,2,3]
输出:5, nums = [1,1,2,2,3]
解释:函数应返回新的长度 5,并且前五个元素为:1, 1, 2, 2, 3。
函数返回的值和 nums 中元素的前五个值都正确即可,后面剩下的元素可以忽略。
示例 2:输入:nums = [0,0,1,1,1,1,2,3,3]
输出:7, nums = [0,0,1,1,2,3,3]
提示:
1 <= nums.length <= 3 * 104
-104 <= nums[i] <= 104
nums
已按升序排列
解法
考虑到题目中提及是有序数组,所有可以使用下述方法
- 双指针法:
fast
:遍历数组,查找新数组的元素;slow
:指向新数组的结尾元素。
- 找到新元素的两种情况
nums[slow] != nums[fast]
,此时不等于新数组的结尾元素,符合nums[slow] == nums[fast]&& nums[slow] != nums[slow - 1]
,此时等于新数组的结尾元素,那这个元素只能数新数组中出现两次的最后一次
时间复杂度: O(n)
空间复杂度:O(1)
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if (nums.size() < 2)return nums.size();
int slow = 1;
for (int fast = 2; fast < nums.size(); fast++) {
if ((nums[slow] != nums[fast]) ||
(nums[slow] == nums[fast] && nums[slow] != nums[slow - 1])) {
nums[++slow] = nums[fast];
}
}
return slow + 1;
}
};
经验总结
- 当想要用额外空间解决问题的时候,想一想可不可以用双指针。
- 一个指针指向原数组位置
- 一个指针指向新数组位置