目录
283.移动零
一、题目描述
二、思路解析
三、代码
1089.复写零
一、题目描述
二、思路解析
三、代码
202.快乐数
一、题目描述
二、思路解析
三、代码
11.盛水最多的容器
一、题目描述
二、思路解析
三、代码
283.移动零
一、题目描述
OJ题目链接:力扣(LeetCode)
二、思路解析
这是将数组分成两部分的题目,当我们遇到把数组分成若干部分的题目时,首先要想到的是双指针,在之前的学习中,我对对撞指针的题目做的比较多,但是这题如果我们使用对撞指针就无法满足“保持非零元素的相对顺序”这一条件,所以我们就考虑到了快慢指针。
我们想定义两个指针 cur 和 dest ,让 cur 遍历整个数组, dest 则指向已处理数组的最后一个元素,根据题目要求,我们可以画出如下原理图:
当我们的cur遍历完整个数组,最后一部分就没有数了,也就已经解决问题了。
但是我们要注意,因为 dest 指向已处理部分的最后一个元素,所以 dest 是非零的,交换时使用的是 dest++
三、代码
class Solution {
public:void moveZeroes(vector<int>& nums) {int cur = 0;int dest = -1;for(; cur < nums.size(); cur++){if(nums[cur] != 0) //可以简写为if(nums[cur]){dest++;swap(nums[dest], nums[cur]);}}}
};
1089.复写零
一、题目描述
OJ题目链接:力扣(LeetCode)
二、思路解析
首先我考虑的还是快慢指针,从前向后遍历数组元素,可是我们要移动元素,就必然会产生元素的覆盖:
我还企图用三个指针来记录要被覆盖的值,可是当上手后会发现,这好像一个巨大的递归,当我记录了当前要被覆盖的值,我们的下一个值又被覆盖了:
看来从前向后是行不通的,那我们只能从后向前再继续尝试,但是又有一个难题,因为数组长度一直是不变的,所以我们要得知结果数组的最后一个数是谁:
这就又要用到快慢指针了,我们设置 cur 和 dest 两个指针,当 nums[cur] == 0 时, dest 走两格,其它时候, dest 和 cur 都走一格,当 dest 走完整个数组, cur 所指的就是最后数组的结尾元素:
现在知道了结果数组的最后一个元素,那么我们再让 cur 和 dest 往回走,
1.1.如果 cur 的值不是0,dest 的值直接被覆盖,
1.2.dest 和 cur 都向前走一步;
2.1.如果 cur 的值是0,那么 dest 的值被覆盖,2.2.dest 向前走一步,dest 的值继续被覆盖,
2.3.dest 和 cur 都向前走一步。
三、代码
class Solution {
public:void duplicateZeros(vector<int>& arr) {int len = arr.size();int cur = 0;int dest = -1;//一开始不知道dest的位置while(cur < len)//cur要遍历整个数组{if(arr[cur]) dest++;else dest += 2;if(dest >= len - 1) break;//如果dest已经到数组结尾,终止cur++;}if(dest == len)//dest有可能越界{//单独处理末尾元素arr[len - 1] = 0;dest -= 2;cur--;}while(cur >= 0){if(arr[cur]) arr[dest--] = arr[cur--];else{arr[dest--] = 0;arr[dest--] = 0;cur--;}}}
};
202.快乐数
一、题目描述
OJ题目链接:力扣(LeetCode)
二、思路解析
我们要特别关注题目描述中的第二句话,这是一个始终都会循环的结构,对比之前的知识,我们很快能想到环形链表。
定义 fast 和 slow 两个指针, fast 的速度是 slow 的二倍,那么他们一定会在环内相遇,我们通过观察相遇位置是否是1就可以得出该数是不是快乐数。
接下来的任务就是算这个数每个位置上的数字的平方和了,这有多种写法,我提供我的写法,如下
三、代码
class Solution {
public:int Calculate(int n){//计算某个数每个位置上的数字的平方和int sum = 0;while(n / 10 >= 10){sum += pow(n % 10, 2);n /= 10;}sum += pow(n % 10, 2);sum += pow(n / 10, 2);return sum;} bool isHappy(int n){int fast = Calculate(n);int slow = n;while (fast != slow){slow = Calculate(slow);fast = Calculate(Calculate(fast));}return slow == 1;}
};
11.盛水最多的容器
一、题目描述
OJ题目链接:力扣(LeetCode)
二、思路解析
首先我们先要理解下面的话,如果不理解可以自己举例子算一下,所以就得出只有一种情况是不确定的,我们只需要罗列出该情况并找到最大值,即可完成本题。
根据以上情况,我们设置左右指针,并不断选中最小值然后计算其容积,并让非最小值向内移动,不断重复,并不断更新容积的最大值即可。
三、代码
class Solution {
public:int maxArea(vector<int>& height) { int min_Val = 0;//最小值int V = 0;//容积int tmp = 0;int left = 0;int right = height.size() - 1;while(left < right){min_Val = min(height[left], height[right]);tmp = (right - left) * min_Val;if(height[left] > height[right])right--;elseleft++;V = max(V, tmp);}return V;}
};