双指针法
15.三数之和
解题思路:
- 考虑特殊情况,如全为正数,全为零等
- 题目要求不重复的三元组,则包含了去重的操作
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int size = nums.size();
vector<vector<int>> result;
sort(nums.begin(),nums.end()); //排序
for(int i = 0; i < size; i++){
if(nums[i] > 0){ //全为正数的情况
return result;
}
if(i > 0 && nums[i] == nums[i-1]){
continue; //重复则跳过
}
int left = i + 1;
int right = size -1;
while(right > left){
if(nums[i] + nums[left] + nums[right] > 0){
right--; //和大了,右侧指针--
}
else if(nums[i] + nums[left] + nums[right] < 0){
left++; //和小了,左侧指针++
}
else{
result.push_back(vector<int>{nums[i],nums[left],nums[right]});
while(right > left && nums[right] == nums[right-1]){
right--; //去重
}
while(right > left && nums[left] == nums[left+1]){
left++;
}
right--;
left++;
}
}
}
return result;
}
};
18.四数之和
解题思路:
与三数之和相同,多套一层循环
特别要注意的是第二层循环的时候跳过的判定条件,否则将无法识别{0,0,0,0} 0的情况
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
int size = nums.size();
sort(nums.begin(),nums.end());
vector<vector<int>> result;
for(int i = 0; i < size; i++){
if(i > 0 && nums[i] == nums[i-1]){
continue;
}
for(int j = i + 1; j < size; j++){
if(j > i + 1 && nums[j] == nums[j-1]){
continue;
}
int left = j + 1;
int right = size - 1;
while(right > left){
if(nums[i] + nums[j] + nums[left] + nums[right] > target){
right--;
}
else if(nums[i] + nums[j] + nums[left] + nums[right] < target){
left++;
}
else{
result.push_back(vector<int>{nums[i],nums[j],nums[left],nums[right]});
while(right > left && nums[right] == nums[right-1]){
right--;
}
while(right >left && nums[left] == nums[left+1]){
left++;
}
right--;
left++;
}
}
}
}
return result;
}
};
27.移除元素
解题思路:
题目要求原地移除,此时可以使用双循环来移动数组元素但是时间复杂度为O(n^2)
也可以使用双指针法时间复杂度O(n)
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int size = nums.size();
int last = 0, first = 0;
for(first; first < size; first++){
if(nums[first] != val){
nums[last] = nums[first];
last++;
}
}
return last;
}
};
142.环形链表 II
解题思路:
用一快一慢两个指针做追的运动,通过如下图计算,可知在相遇后首部和相遇点同时进行步长为1的移动
,相遇点即为入环点
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode* p = head;
ListNode* q = head;
while(p!=NULL&&p->next!=NULL){
q = q->next;
p = p->next->next;
if( p == q ){
ListNode* x=head;
ListNode* y=p;
while(x != y){
x = x->next;
y = y->next;
}
return x;
}
}
return NULL;
}
};
206.反转链表
解题思路:
使用双指针逐一反转链表元素
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* p = head;
ListNode* q = nullptr;
ListNode* temp;
while(p){
temp = p->next;
p->next = q;
q = p;
p = temp;
}
return q;
}
};