【优选算法】C++双指针问题
一、移动零
双指针,一个cur,一个dest
两个指针的作用:
cur:从左往右扫描数组,遍历数组
dest:已处理的区间内,非零元素的最后一个位置
三个区间:[ 0, dest ] [ dest + 1, cur - 1 ] [ cur, n - 1 ]
class Solution {
public:void moveZeroes(vector<int>& nums) {int cur = 0, dest = 0;int n = nums.size();while(cur < n){if(nums[cur] != 0)swap(nums[dest++], nums[cur]);cur++;}}
};
2、复写零
思路:
class Solution {
public:void duplicateZeros(vector<int>& arr) {int dest = -1, cur = 0, n = arr.size();// 从左往右while(cur < n){if(arr[cur]) dest++;else dest+=2;if(dest >= n-1) break;cur++;}// 处理边界情况if(dest == n){arr[n-1] = 0;cur--;dest-=2;}// 从右往左while(cur >= 0){if(arr[cur]) {arr[dest--] = arr[cur--];}else{cur--;arr[dest--] = 0;arr[dest--] = 0;}}}
};
3、快乐数
思路:
class Solution {
public:int _isHappy(int n) {int ret = 0;while (n) {int m = n % 10;ret += pow(m, 2);n /= 10;}return ret;}bool isHappy(int n) {int low = n, fast = n;low = _isHappy(low);fast = _isHappy(fast);fast = _isHappy(fast);while (fast != low) {low = _isHappy(low);fast = _isHappy(fast);fast = _isHappy(fast);}if (fast == 1)return true;elsereturn false;}
};
4、盛水最多的容器
思路:
class Solution {
public:int maxArea(vector<int>& height) {int left = 0, right = height.size()-1;int maxA = 0, area = 0;while(left < right){area = (right-left)*(min(height[left], height[right]));if(maxA < area) maxA = area;if(height[left] > height[right]) right--;else left++;}return maxA;}
};
5、有效三角形的个数
思路:
class Solution {
public:int triangleNumber(vector<int>& nums) {// 先排序sort(nums.begin(), nums.end());// 排序完成int n = nums.size(), c = n - 1;int sum = 0;while (c >= 2) {int left = 0, right = c - 1;while (left < right) {if (nums[left] + nums[right] > nums[c]) {sum += (right - left);right--;} elseleft++;}c--;}return sum;}
};
6、和为s的两个数
思路:
class Solution {
public:vector<int> twoSum(vector<int>& price, int target) {int left = 0, right = price.size()-1;vector<int> retv;while(left < right){if(price[left] + price[right] > target) right--;else if(price[left] + price[right] < target) left++;else {retv.push_back(price[left]);retv.push_back(price[right]);break;}}return retv;}
};
7、三数之和
思路:
class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {vector<vector<int>> vv;// 1.先排序sort(nums.begin(), nums.end());// 2.固定一个数int i = 0, n = nums.size();while (i < n-1) {int left = i + 1, right = n - 1;int val = -nums[i];while (left < right) {if (nums[left] + nums[right] > val)right--;else if (nums[left] + nums[right] < val)left++;else {vector<int> v;v.push_back(nums[left]);v.push_back(nums[right]);v.push_back(-val);while (nums[left] == nums[++left] && left < right); // 去重while (nums[right] == nums[--right] && left < right); // 去重vv.push_back(v);}}while(nums[i] == nums[++i] && i < n-1); // 去重,i < n-1,避免越界}return vv;}
};
8、四数之和
思路:
class Solution {
public:vector<vector<int>> fourSum(vector<int>& nums, int target) {vector<vector<int>> vv;// 1.排序sort(nums.begin(), nums.end());// 排序完成,开始操作int n = nums.size();for(int i = 0; i < n; ){// 固定bfor(int j = i+1; j < n;){long long arm = (long long)target - nums[i] - nums[j];int left = j+1, right = n-1;while(left < right){int sum = nums[left] + nums[right];if(sum < arm) left++;else if(sum > arm) right--;else{vv.push_back({nums[i], nums[j], nums[left], nums[right]});// 开始去重 left rightleft++;while(left < right && nums[left] == nums[left-1]) left++;right--;while(left < right && nums[right] == nums[right+1]) right--;}}// 去重 jj++;while(j < n && nums[j] == nums[j-1]) j++;}// 去重 ii++;while(i < n && nums[i] == nums[i-1]) i++;}return vv;}
};// 第二种变形
class Solution {
public:vector<vector<int>> fourSum(vector<int>& nums, int target) {vector<vector<int>> vv;// 1.排序sort(nums.begin(), nums.end());// 排序完成,开始操作// 固定aint a = 0, n = nums.size();while (a < n - 1) {// 固定bint b = a + 1;while (b < n - 1) {int left = b + 1, right = n - 1;long long val = (long long)target - nums[a] - nums[b];while (left < right) {if (nums[left] + nums[right] > val)right--;else if (nums[left] + nums[right] < val)left++;else {vv.push_back({nums[a], nums[b], nums[left], nums[right]});// 去重 left rightwhile (nums[left] == nums[++left] && left < right);while (nums[right] == nums[--right] && left < right);}}// 去重 bwhile (nums[b] == nums[++b] && b < n - 1);}// 去重 awhile (nums[a] == nums[++a] && a < n - 1);}return vv;}
};