一 删除排序数组中的重复项
题目链接:力扣
重点在审题:
1 排序数组
2 原地“删除”重复元素,“删除”不一定指删除,可以是替换
3 不需要考虑数组中超出新长度后面的元素。(返回的是一个数组长度,后台根据长度自动截取)
自力更生:
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if(nums.size()<=1) return nums.size();
auto first = nums.begin();
auto second = first+1;
while(second!=nums.end()){
if(*first==*second) {
nums.erase(second);
}
else {
first = second;
second+=1;
}
}
return nums.size();
}
};
借鉴他人:双指针法(快慢指针法,i是慢指针,j是快指针)
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if(nums.size()<=1)
return nums.size();
int i=0;
for(int j=1;j<nums.size();j++)
{
if(nums[j]!=nums[i])
{
i++;
nums[i]=nums[j];
}
}
return (i+1);
}
};
当nums[i]与nums[j]相等时,就把j自增,否则,我们就找到了不同于nums[i]的第一个数字,为了保留一个重复数字,就把i增1,然后被nums[j]覆盖掉即可。直到j越界。
二 移除元素
题目链接:力扣
其实跟第一题满相似的,但是还是不会迁移。。。
法一 双指针法
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
if(nums.size()==0)
return 0;
int i=0;
for(int j=0;j<nums.size();j++)
{
if(nums[j]!=val)
{
nums[i]=nums[j];
i++;
}
}
return i;
}
};
j是快指针,i是慢指针。当nums[j]不是要删除的值时,把该值赋给Num[i],即覆盖,i++,当Num[j]是要删除的值,快指针继续走,直到碰到不是就开始覆盖。
法二 替换法
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
if(nums.size()==0)
return 0;
int j=nums.size();
int i;
for(i=0;i<j;)
{
if(nums[i]==val)
{
nums[i]=nums[j-1];
j--;
}
else
i++;
}
return i;
}
};
遍历数组,如果是val,就把val与后面的元素调换位置,为了防止后面的元素也是val,就先不把i增1。这适合val值得个数比较少的情况。
三 两数之和
题目链接:力扣
自力更生
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> res;
if(nums.size()<2)
return res;
vector<int> num_copy(nums);
sort(num_copy.begin(),num_copy.end());
int i=0;
int j=nums.size()-1;
int left,right;
for(left=num_copy[i],right=num_copy[j];left+right!=target&&i<j;)
{
if(left+right>target)
{
j-=1;
right=num_copy[j];
}
else
{
i+=1;
left=num_copy[i];
}
}
if(left+right==target&&i<j)
{
int index_left=-1,index_right=-1;
for(int i=0;i<nums.size();i++)
{
if(nums[i]==left&&index_left==-1)
index_left=i;
//参考【3,3】,因为一个数如果被left遍历到,一定不可以被right再遍历了
else if(nums[i]==right&&index_right==-1)
index_right=i;
}
res.push_back(index_left);
res.push_back(index_right);
return res;
}
else
return res;
}
};
思路:复制一个数组,并排序,然后双指针法一个从前往后,一个从后往前。找到left和right之后,再去原数组中获取下标即可(注意因为同一个数字不可以使用2次,因此如果一个下标是left的,就不可能是right了,反之亦然)
借鉴不同想法
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> res(2,-1);
if(nums.size()<2)
return res;
map<int,int> a;
for(int i=0;i<nums.size();i++)
{
//键是数组元素,值是下标
a.insert(map<int,int>::value_type(nums[i],i));
}
for(int i=0;i<nums.size();i++)
{
//第二个条件是判断2个数字是不是同一个数字
if(a.count(target-nums[i])>0&&a[target-nums[i]]!=i)
{
res[0]=i;
res[1]=a[target-nums[i]];
break;
}
}
return res;
}
};
关于map的详解:戳这里