引言
代码
第一题
这是一道简单的贪心题目,目的是找最长的摆动序列,我们的想法就是记录上一个差值和本次差值,只要差值相反,那么我们就对结果+1
cpp
class Solution {
public:
int wiggleMaxLength(vector<int>& nums) {
if (nums.size() <= 1) {
return nums.size();
}
int preDiff = 0;
int curDiff = 0;
int res = 1;
for (int i = 0; i < nums.size() - 1; i++) {
curDiff = nums[i + 1] - nums[i];
if ((curDiff > 0 && preDiff <= 0) || (curDiff < 0 && preDiff >= 0)) {
res++;
preDiff = curDiff;
}
}
return res;
}
};
第二题
这一题思路不是很难,但是实现起来却比较困难,就是要实现一个最大的覆盖面积在已经遍历过了的点里面,而且还要做到循环的处理,这里就是改变了停止的条件,cover每一次都是要保证是最大的,而只要遍历的点超过了这个最大的覆盖区,说明根本到达不了这个地方。
cpp
class Solution {
public:
bool canJump(vector<int>& nums) {
int cover = 0;
if (nums.size() == 1) {
return true;
}
for (int i = 0; i <= cover; i++) {
cover = max(cover, i + nums[i]);
if (cover >= nums.size() - 1) {
return true;
}
}
return false;
}
};
第三题
这一题相比于上一题有一个不同的地方就是判断走到终点要几步,那么我们可以延续上一题的思路,我们每当走到一个范围的终点的时候就会更新我们的范围,不过在更新之前我们会判断这个范围与终点之间的关系。不过这一题和上一题有一个不同的地方就是这一题的范围不是在一边循环一边变化的,是走完一个范围之后才会更新的,这个也是因为我们题目里面已经保证了可以到达终点。
cpp
class Solution {
public:
int jump(vector<int>& nums) {
if (nums.size() == 1) {
return 0;
}
int ans = 0;
int nextDistance = 0;
int curDistance = 0;
for (int i = 0; i < nums.size(); i++) {
nextDistance = max(nums[i] + i, nextDistance);
if (i == curDistance) {
ans++;
curDistance = nextDistance;
if (nextDistance >= nums.size() - 1) {
break;
}
}
}
return ans;
}
};
第四题
我们创建一个数组来记录一下两个数组的差,这样子就可以转化问题为:从哪一个地方开始相加可以让和一直是正数。首先我们一定要先判断一下整个和相加一定要是正数,否则无论从哪里开始都不可能保证是正数。然后我们按照顺序开始相加,但是只要遇到了负数我们就从下一个开始重新计数。首先我们一开始都会对这个方法有疑问,因为如果满足之后的和是正数,但是一定可以保证再次加上之前的数也能是正数嘛~~~ 但是注意:我们之前已经单独判断所有和加上去一定是正数了,所以我们现在的所有操作是找到起点,因为是这个起点是一定存在的,既然之前的点已经测试过了不可以,那么就往后面继续测呗~~~
cpp
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
vector<int> nums(gas.size(), 0);
for (int i = 0; i < gas.size(); i++) {
nums[i] = gas[i] - cost[i];
}
int index = gas.size();
int sum = 0;
for (int i = 0; i < index; i++) {
sum += nums[i];
}
if (sum < 0) {
return -1;
}
sum = 0;
int startPos = 0;
bool flag = true;
for (int i = 0; i < index; i++) {
sum += nums[i];
if (sum < 0) {
sum = 0;
startPos = i + 1;
continue;
}
}
return startPos;
}
};
第五题
这一题很难,因为我们需要顾及左边又要顾及右边,这种题目我们千万不要一下子兼顾两边,我们要遍历两边,先左边再右边。我们先把所有的数组都设置为1,然后从左到右遍历,只要右边比左边大,那么右边的值就比左边的值大1。然后我们再从右边到左边遍历,也就是如果右边大于左边,那么就比左边的糖果大1,但是因为也要满足上一次遍历的结果,也就是右边比左边大的这个,所以我们要利用上一次已经得到的结果+1。不过一定要注意的是,这两个数组是两个结果,所以很可能对于一个点有两个结果,我们为了要满足两次遍历的结果,所以要取最大值。比如有可能1 2 3 4 5 1,那么对于5这个数我们最后的结果应该是5个糖果。
cpp
class Solution {
public:
int candy(vector<int>& ratings) {
int sum = 0;
vector<int> res(ratings.size(), 1);
int index = ratings.size();
for (int i = 1; i < index; i++) {
if (ratings[i] > ratings[i - 1]) {
res[i] = res[i - 1] + 1;
}
}
for (int i = index - 1; i > 0; i--) {
if (ratings[i - 1] > ratings[i]) {
res[i - 1] = max(res[i - 1], res[i] + 1);
}
}
for (int result : res) {
sum += result;
}
return sum;
}
};