目录
双指针
引子(简单):给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int j=0;
for(int i=0;i<nums.size();i++){
if(nums[i]!=0){
swap(nums[i],nums[j++]);
}
}
}
};
举一反三:给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。(中等)
示例 1:
给定 nums = [1,1,1,2,2,3],
函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3 。
你不需要考虑数组中超出新长度后面的元素。
示例 2:
给定 nums = [0,0,1,1,1,1,2,3,3],
函数应返回新长度 length = 7, 并且原数组的前五个元素被修改为 0, 0, 1, 1, 2, 3, 3 。
你不需要考虑数组中超出新长度后面的元素。
解法1:双指针
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if(nums.size()<3){
return nums.size();
}
int j=2;
for(int i=2;i<nums.size();i++){
if(nums[i]!=nums[j-2]){
nums[j]=nums[i];
j++;
}
}
return j;
}
};
执行用时 :8 ms, 在所有 C++ 提交中击败了90.90%的用户
内存消耗 :6.3 MB, 在所有 C++ 提交中击败了100.00%的用户
解法二:主要是运用了vector中的erase()方法,
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if(nums.size()<3)return nums.size();
for(auto i = nums.begin()+2;i != nums.end();i++){
if(*i == *(i-2)){
nums.erase(i);
i--;
}
}
return nums.size();
}
};
执行用时 :8 ms, 在所有 C++ 提交中击败了90.90%的用户
内存消耗 :6.5 MB, 在所有 C++ 提交中击败了100.00%的用户
位运算
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。(简单)
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1]
输出: 1
示例 2:
输入: [4,1,2,1,2]
输出: 4
第一种方法是使用哈希表
时间复杂度为O(n),空间复杂度: O(n) 。哈希表 需要的空间与nums 中元素个数相等。
这也是我觉得最好的方法,但看了官方题解之后直呼NB。
lass Solution {
public:
int singleNumber(vector<int>& nums) {
unordered_map<int,int> sHash;
for(int i=0;i<nums.size();i++){
sHash[nums[i]]++;
}
int res;
for(int i=0;i<nums.size();i++){
if(sHash[nums[i]]==1)
{
res=nums[i];
break;
}
}
return res;
}
};
执行用时 :40 ms, 在所有 C++ 提交中击败了17.18%的用户
内存消耗 :13.6 MB, 在所有 C++ 提交中击败了5.88%的用户
使用异或。
class Solution {
public:
int singleNumber(vector<int>& nums) {
int len = nums.size();
int result=0;
for(int i=0;i<len;i++){
result ^=nums[i];
}
return result;
}
};
执行用时 :24 ms, 在所有 C++ 提交中击败了42.63%的用户
内存消耗 :11.7 MB, 在所有 C++ 提交中击败了5.88%的用户
给定一个整数数组 nums
,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。
示例 :
输入:[1,2,1,3,2,5]
输出:[3,5]
注意:
- 结果输出的顺序并不重要,对于上面的例子,
[5, 3]
也是正确答案。 - 你的算法应该具有线性时间复杂度。你能否仅使用常数空间复杂度来实现
class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
int len = nums.size();
vector<int> res;
int result=0;
for(int i=0;i<len;i++){
result ^=nums[i];
}
int DiffNum = result & (~result + 1);//取最低为为 1 的值
int num1=0;
for(int i=0;i<len;i++){
if(nums[i]&DiffNum)
num1 ^=nums[i];
}
return {num1,num1^result};
}
};