题目要求
第一种解题思路:
因为数组是已经排好序的有序数组,所以后面的元素一定是大于等于前面的数字的,所以我们只需要判断后一个数字是否与前一个数字相等,如果相等就让后一个继续向后,直到不等于当前数为止,如果不相等就让前面的下标向后移动一位赋值,最后的长度就是前面下标+1
// 前面的解释有点难以理解,看代码很容易理解
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if(nums.size() == 0)
{
return 0;
}
int index = 0;
for(int i = 1; i < nums.size(); i++)
{
if(nums[index] != nums[i])
{
nums[++index] = nums[i];
}
}
return index + 1;
}
};
第二种解决思路:
利用STL中的distance以及unique接口:
distance有两个参数为迭代器,计算两个迭代器之间的距离;
unique的两个参数也为迭代器,它保证了相邻的数据之间没有重复项,例如:{ 1, 2, 2, 3, 3, 3, 2, 4, 4}的结果就是{1, 2, 3, 2, 4};可以发现其中仍然是存在重复项的,因为unique只保证相邻的两个数据是唯一的,在本题中不会出现这个问题,因为题中的数组为有序的。返回值也是一个迭代器,表示相邻的不重复项的最后一个地址。
// 代码实现简单,但是需要对接口熟悉
// 接口在头文件 #include <algorithm>中
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
return distance(nums.begin(), unique(nums.begin(), nums.end()));
}
};
第三中解决思路:
同样用到了STL中的接口upper_bound
upper_bound需要在排序数组中使用
在从小到大的数组中,upper_bound的作用是利用二分查找,找到第一个大于val的值,直到找到 last位置
// 头文件#include <algorithm>
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
return removeDuplicates(nums.begin(), nums.end(), nums.begin()) - nums.begin();
}
template<class InIt, class OutIt>
OutIt removeDuplicates(InIt first, InIt last, OutIt output)
{
while(first != last)
{
*output++ = *first;
first = upper_bound(first, last, *first);
}
return output;
}
};
扩展:
第一种解题思路:
与第一题的解题方式类似
从第三个元素开始,与第一个元素相比较,相同则第一个元素的出现次数一定是大于3个的,不相同就比较下一个与第二个元素是否相同,以此类推
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if(nums.size() < 2)
{
return nums.size();
}
int index = 2;
for(int i = 2; i < nums.size(); ++i)
{
if(nums[i] != nums[index - 2])
{
nums[index++] = nums[i];
}
}
return index;
}
};
最终返回index的原因是index的位置在有效数据的下一个位置,而下标是从0开始的,所以index就表示长度
第二种思路:
判断一个元素的左右两边是否相同,相同表示当前元素已经超过两个,这时候继续向后走,直到走到左右两边不相同或走到最后一个元素的前一个。
为什么走到最后一个前一个元素就可以直接赋值了?
因为赋值的永远是相同元素中的第一个和最后一个,到了倒数第二个元素时,左右两边还是相同就可以直接将最后一个元素赋值了。
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int index = 0;
for(int i = 0; i < nums.size(); ++i)
{
if(i > 0 && i < nums.size() - 1
&& nums[i - 1] == nums[i]
&& nums[i] == nums[i + 1])
continue;
nums[index++] = nums[i];
}
return index;
}
};
第二种方法相较于第一种方法更为简洁;但是第一种方法的扩展性较好,将出现2的位置改位3即可解答最多出现三次的问题。
如果是无序数组,则需要使用hashmap来记录数字出现次数
解题思路来自《LeetCode题解》