目录
[0. 双指针](#0. 双指针)
[1. 移动零](#1. 移动零)
[1.1 题目链接](#1.1 题目链接)
[1.2 题目描述](#1.2 题目描述)
[1.3 算法思路](#1.3 算法思路)
[1.4 C++算法代码](#1.4 C++算法代码)
[2. 复写零](#2. 复写零)
[2.1 题目链接](#2.1 题目链接)
[2.2 题目描述](#2.2 题目描述)
[2.3 算法思路](#2.3 算法思路)
[2.4 C++算法代码](#2.4 C++算法代码)
[3. 快乐数](#3. 快乐数)
[3.1 题目链接](#3.1 题目链接)
[3.2 题目描述](#3.2 题目描述)
[3.3 算法思路](#3.3 算法思路)
[3.4 C++算法代码](#3.4 C++算法代码)
[4. 盛最多水的容器](#4. 盛最多水的容器)
[4.1 题目链接](#4.1 题目链接)
[4.2 题目描述](#4.2 题目描述)
[4.3 算法思路](#4.3 算法思路)
[4.4 C++算法代码](#4.4 C++算法代码)
[5. 有效三角形的个数](#5. 有效三角形的个数)
[5.1 题目链接](#5.1 题目链接)
[5.2 题目描述](#5.2 题目描述)
[5.3 算法思路](#5.3 算法思路)
[5.4 C++算法代码](#5.4 C++算法代码)
[6.1 题目链接](#6.1 题目链接)
[6.2 题目描述](#6.2 题目描述)
[6.3 算法思路](#6.3 算法思路)
[6.4 C++算法代码](#6.4 C++算法代码)
[7. 三数之和](#7. 三数之和)
[7.1 题目链接](#7.1 题目链接)
[7.2 题目描述](#7.2 题目描述)
[7.3 算法思路](#7.3 算法思路)
[7.4 C++算法代码](#7.4 C++算法代码)
0. 双指针
常见的双指针有两种形式,一种是对撞指针,一种是左右指针。
**对撞指针:**一般用于顺序结构中,也称左右指针。
- 对撞指针从两端向中间移动。一个指针从左端开始,另一个从右端开始,然后逐渐往近。
- 对撞指针的终止条件一般是两个指针相遇或者错开(也可能在循环内部找到结果直接跳出环),也就是:
left == right (两个指针指向同一个位置)
left > right(两个指针错开)
**快慢指针:**又称为龟兔赛跑算法,其基本思想就是使用两个移动速度不同的指针在数组或链表等序列结构上的移动。
这种方法对于处理环形链表或数组非常有用。
其实不单单是环形链表或者数组,如果我们要研究的问题出现循环往复的情况时,均可考虑使用快慢指针的思想。
快慢指针的实现方式有很多种,最常用的一种就是:
- 在一次循环中,每次让慢的指针向后移动一位,而快的指针往后移动两位,实现一快一慢。
代码链接:
1. 移动零
1.1 题目链接
283. 移动零 - 力扣(LeetCode)https://leetcode.cn/problems/move-zeroes/description/
1.2 题目描述
1.3 算法思路
1.4 C++算法代码
cpp
class Solution {
public:
void moveZeroes(vector<int>& nums) {
for(int cur = 0,dest = -1; cur < nums.size();cur++)
if(nums[cur])
swap(nums[++dest],nums[cur]);
}
};
2. 复写零
2.1 题目链接
1089. 复写零 - 力扣(LeetCode)https://leetcode.cn/problems/duplicate-zeros/description/
2.2 题目描述
2.3 算法思路
2.4 C++算法代码
cpp
class Solution {
public:
void duplicateZeros(vector<int>& arr)
{
int cur = 0,dest = -1;
//找最后一个复写的数
while(cur < arr.size())
{
if(arr[cur] != 0)
dest++;
else
dest +=2;
if(dest >= arr.size()-1) break;
cur++;
}
//处理一下边界情况
if(dest == arr.size())
{
arr[dest-1] = 0;
cur--;
dest-=2;
}
//复写操作
while(cur >= 0)
{
if(arr[cur] != 0)
{
arr[dest--] = arr[cur--];
}
else
{
arr[dest--] = arr[cur];
arr[dest--] = arr[cur--];
}
}
}
};
3. 快乐数
3.1 题目链接
3.2 题目描述
3.3 算法思路
3.4 C++算法代码
cpp
class Solution {
public:
int bitsum(int n)
{
int sum = 0;
while(n)
{
int t = n % 10;
sum += t * t;
n /= 10;
}
return sum;
}
bool isHappy(int n) {
int slow = n,fast = bitsum(n);
while(slow != fast)
{
slow = bitsum(slow);
fast = bitsum(bitsum(fast));
}
return slow == 1;
}
};
4. 盛最多水的容器
4.1 题目链接
11. 盛最多水的容器 - 力扣(LeetCode)https://leetcode.cn/problems/container-with-most-water/description/
4.2 题目描述
4.3 算法思路
4.4 C++算法代码
cpp
class Solution {
public:
int maxArea(vector<int>& height) {
int left = 0,right = height.size()-1,max = 0,v = 0;
while(left < right)
{
v = (height[left] > height[right] ? height[right] : height[left]) * (right - left);
if(v > max) max = v;
height[left] > height[right] ? right-- : left++;
}
return max;
}
};
5. 有效三角形的个数
5.1 题目链接
611. 有效三角形的个数 - 力扣(LeetCode)https://leetcode.cn/problems/valid-triangle-number/description/
5.2 题目描述
5.3 算法思路
5.4 C++算法代码
cpp
class Solution {
public:
int triangleNumber(vector<int>& nums) {
//排序优化
sort(nums.begin(),nums.end());
//利用双指针解决问题
int value = 0;
for(int i = nums.size()-1;i >= 2;i--)
{
int left = 0,right = i -1;
while(left < right)
{
if(nums[left] + nums[right] > nums[i])
{
value += right - left;
right--;
}
else
{
left++;
}
}
}
return value;
}
};
6.和为s的两个数
6.1 题目链接
6.2 题目描述
6.3 算法思路
6.4 C++算法代码
cpp
class Solution {
public:
vector<int> twoSum(vector<int>& price, int target) {
int left = 0,right = price.size()-1;
while(left < right)
{
int sum = price[left] + price[right];
if(sum < target)
left++;
else if(sum > target)
right--;
else
return {price[left],price[right]};
}
return {-4941, -1};
}
};
7. 三数之和
7.1 题目链接
15. 三数之和 - 力扣(LeetCode)https://leetcode.cn/problems/3sum/description/
7.2 题目描述
7.3 算法思路
7.4 C++算法代码
cpp
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
sort(nums.begin(),nums.end());
vector<vector<int>> ret;
int n = nums.size();
for(int i = 0;i < n;)
{
int x = nums[i];
for(int j = i + 1;j < n;)
{
int begin = j + 1,end = n - 1;
long long z = (long long)target - nums[i] - nums[j];
while(begin < end)
{
int sum = nums[begin] + nums[end];
if(sum < z) begin++;
else if(sum > z) end--;
else
{
ret.push_back({nums[i],nums[j],nums[begin],nums[end]});
begin++;
while(begin < end && nums[begin] == nums[begin-1]) begin++;
end--;
while(begin < end && nums[end] == nums[end+1]) end--;
}
}
j++;
while(j < n && nums[j] == nums[j-1]) j++;
}
i++;
while(i < n && nums[i] == nums[i-1]) i++;
}
return ret;
}
};