本篇文章题目均取自LeetCode
文章目录
一、283.移动零
1.题目描述
2.思路
创建两个指针(注:双指针里的指针不一定是以前学的指针,本题指的就是数组下标)cur,dest分别为0,-1
通过cur指针遍历数组,而dest则表示已经处理的区间内,非0元素的最后一个位置,cur遇到0,就与下标为dest的数组内容交换
3.代码实现
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int cur = 0,dest = -1;
while(cur < nums.size())
{
if(nums[cur]!=0)
{
dest++;
swap(nums[cur],nums[dest]);
}
cur++;
}
}
};
二、1089.复写零
1.题目描述
2.思路
首先,研究一下样例1,发现得到的结果最后一个是4,也就是说,经过复写0后,数组最后一个位置为4,所以我们实现时要先找到这个4
这里用cur表示复写后最后一个数,这样前面才能给够空间给复写后的数组,cur从下标0位置开始遍历数组
找到cur所应该指向的数组最后一个值后,从后往前赋值,若cur指向的值不为0,则直接插入数组,若为0,则连续插入两个0
找最后一个元素
再通过复写0得到下面数组
这里有特例情况,比如数组[1,0,4,0,3],它通过找变换应该是[1,0,0,4,0,0],这样就造成了数组越界,所以我们这里要对这种类型进行特殊处理:将数组最后一个内容赋0,dest指向倒数第二个数据即可
3.代码实现
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[arr.size()-1] = 0;
cur--;
dest -= 2;
}
while(cur >= 0)
{
if(arr[cur])
arr[dest--] = arr[cur--];
else{
arr[dest--] = 0;
arr[dest--] = 0;
cur--;
}
}
}
};
三、202.快乐水
1.题目描述
2.思路
这题我们使用快慢指针解题,什么是快慢指针呢,就是两个指针它们运动一个相比于另一个要快
通过题目,可以发现我们需要取到每个数字的每一位数字,并将它们平方相加,如果最后得到1,则为快乐数,但要是无限循环了,则不是快乐数,下面我们依旧画图解决此题
我们这里假设int范围可以取到9999999999,此时它的各位数平方和也就810,所以也就是说,快慢指针一定会在810次内相遇,所以我们取相遇时指针指向的值,若为1,则为true,否则为false
3.代码实现
class Solution {
public:
int fastnum(int n)
{
int sum = 0;
while(n)
{
sum += pow(n % 10,2);
n /= 10;
}
return sum;
}
bool isHappy(int n) {
int slow = n;
int fast = fastnum(n);
while(slow != fast)
{
slow = fastnum(slow);
fast = fastnum(fastnum(fast));
}
return slow == 1 ? true : false;
}
};
四、11.盛最多水的容器
1.题目描述
2.思路
通过观察题目,不难发现以下条件:容器的底长为(right - left),而它的高取决于两个高中最短的那一个,所以我们不难得到容量等于(right - left) * min(height[left] , height[right]),如果左边高于右边,则right往左移动,否则left往右移动,直到相遇为止,容积取最大即可
3.代码实现
class Solution {
public:
int maxArea(vector<int>& height) {
int n = height.size();
int left = 0,right = n - 1;
int v = 0,v1;
while(left<right)
{
v1 = (right-left) * min(height[left],height[right]);
if(height[left] <= height[right])
left++;
else
right--;
v = max(v,v1);
}
return v;
}
};
五、611.有效三角形个数
1.题目描述
2.思路
这里我们要从数组中取到三条边,构成三角形,那么我们完全可以排序后再次进行查找,取最大边,用left与right指针进行遍历,但如果这么搜索,那也有接近n方的复杂度了,所以这里有一种更快的方法:
若left与right指向的值大于i指向的值,因为数组排好了顺序,所以left一直++,直到right和right指向的值都是大于i指向值的,所以这里数量直接加(right - left),right–
同样的,如果left与right指向的值小于i指向的值,那么left++
3.代码实现
class Solution {
public:
int triangleNumber(vector<int>& nums) {
int n = nums.size();
sort(nums.begin(),nums.end());
int ans = 0;
for(int i = n-1;i>=2;i--)
{
int left = 0,right = i - 1;
while(left < right)
{
if(nums[left]+nums[right] > nums[i])
{
ans += right - left;
right--;
}
else
left++;
}
}
return ans;
}
};
六、15.三数之和
1.题目描述
2.思路
本题和上一题多少有点相似,本题需要取三个数使得结果为0,我们同样用i来表示第一个数,left为第二个数,right为最后一个数
3.代码实现
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> ans;
sort(nums.begin(),nums.end());
int n = nums.size();
for(int i = 0;i < n;)
{
if(nums[i] > 0)
break;
int left = i + 1,right = n-1;
while(left < right)
{
if(nums[i] + nums[left] + nums[right] > 0)
right--;
else if(nums[i] + nums[left] + nums[right] < 0)
left++;
else{
ans.push_back({nums[i],nums[left],nums[right]});
left++;
right--;
while(left < right && nums[left]==nums[left-1]) left++;
while(left < right && nums[right]==nums[right+1]) right--;
}
}
i++;
while(i < n && nums[i] == nums[i-1]) i++;
}
return ans;
}
};
八、18.四数之和
1.题目描述
2.思路
四数之和与三数之和其实基本一致,只是多了道循环,i=0,j = i+1,left = j+1,right = nums.size( ) - 1
但是有一个坑点,那就是int范围此题可能不够,所以sum要用long long类型
3.代码实现
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> ans;
sort(nums.begin(),nums.end());
int n = nums.size();
for(int i = 0;i<n;)
{
for(int j = i+1;j<n;)
{
long long sum = (long long)target - nums[i] - nums[j];
int left = j+1,right = n-1;
while(left < right)
{
if(nums[left] + nums[right] > sum)
right--;
else if(nums[left] + nums[right] < sum)
left++;
else{
ans.push_back({nums[i],nums[j],nums[left],nums[right]});
left++;
right--;
while(left < right && nums[left]==nums[left-1]) left++;
while(left < right && nums[right]==nums[right+1]) right--;
}
}
j++;
while(j < n && nums[j] == nums[j-1]) j++;
}
i++;
while(i < n && nums[i] == nums[i-1]) i++;
}
return ans;
}
};