昨天共做以下几道题目:股票问题、跳跃游戏、跳跃游戏2、加油站、K次取反、分发糖果、柠檬水找零、根据身高重建队列。其中独立思考做出来的时股票问题、K次取反、柠檬水找零。 有点儿难度的题目:跳跃游戏、跳跃游戏2、加油站。前两个属于区间类型的题目。 中等题目:两个维度权衡的问题:分发糖果、根据身高重建队列。
- 区间问题
- 跳跃游戏
一开始想的是每一步都跳最远,在遇到0的情况下,如何解决,思考的是回退。关键思路是:记录最大的cover的值,然后再在0-cover区间内进行遍历,找到再大的cover值。
给定一个非负整数数组,你最初位于数组的第一个位置。数组中的每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达最后一个位置。 假如为[2, 5, 0, 0]
- 跳跃游戏2
给你一个非负整数数组 nums ,你最初位于数组的第一个位置。数组中的每个元素代表你在该位置可以跳跃的最大长度。你的目标是使用最少的跳跃次数到达数组的最后一个位置。假设你总是可以到达数组的最后一个位置。
要统计次数,就需要考虑什么时候必须加一次。
class Solution {
public:
int jump(vector<int>& nums) {
if (nums.size() == 1) return 0;
int curDistance = 0;
int ans = 0;
int nextDistance = 0;
for (int i = 0; i < nums.size(); i++) {
nextDistance = max(nums[i] + i, nextDistance);
if (i == curDistance) {
if (curDistance != nums.size() - 1) {
ans++;
curDistance = nextDistance;
} else break;
}
}
return ans;
}
};
依次遍历数组的数据,若走到当前最大距离(curDistance)还没有走到终点,那么就必须走下一步,把在当前这段(curDistance)中记录的下一步nextDistance更新为curDistance。并且步数加1。
-
加油站
加油站一开始的思路是模拟每一站的消耗与补充,没有整体的思考其中的规律。首先是记录每一次经过加油站的rest,并且将其累加,如果累加起来是负数,那么绝无可能绕一圈,消耗的油比补充的油少。并且在这个过程可以维护累积透支的油cur_sum。如果cur_sum是>=0的,那么说明,每一次都刚好能到下一个加油站,并且接受补给。开始的地点为0。 假如cur_sum是负数呢?从最后一个加油站往前看是否能有攒下来的油弥补cur_sum,即透支的油。假如能将其弥补,意味着能够从这个加油站出发,攒油,并且供后面的加油站消耗。返回这个位置i。
class Solution { public: int canCompleteCircuit(vector<int>& gas, vector<int>& cost) { int curSum = 0; int min = INT_MAX; for (int i = 0; i < gas.size(); i++) { int rest = gas[i] - cost[i]; curSum += rest; if (curSum < min) { min = curSum; } } if (curSum < 0) return -1; if (min >= 0) return 0; std::cout << min << std::endl; for (int i = gas.size() - 1; i >= 0; i--) { int rest = gas[i] - cost[i]; min += rest; if (min >= 0) { return i; } } return -1; } };
- 两个维度权衡问题
- 分发糖果问题
n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。 你需要按照以下要求,给这些孩子分发糖果: 每个孩子至少分配到 1 个糖果。 相邻两个孩子评分更高的孩子会获得更多的糖果。 请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。
问题的难点在于没法重新为孩子的评分排序,因为涉及到规则:相邻两个孩子评分更高的孩子会获得更多的糖果。那就要考虑左右孩子的评分。能不能逐一的去判断确定给每个孩子多少糖果呢? 应该要思考的是什么情况下需要考虑两种情况。左右两边的情况。先从第二个节点开始遍历,判断ratings[i] 比ratings[i - 1] 多的话,ratings[i]加1。但是当ratings是不断减小的,即右边的孩子比左边的孩子分数低,那么怎么确保左边的孩子得到的糖果比右边的孩子得到的糖果多呢?从右往左遍历,假如遇到左边的孩子得分比右边的孩子分数高,那么取max(candyVec[i], candyVec[i + 1] + 1)。最后统计结果。
- 根据身高重建队列
假设有打乱顺序的一群人站成一个队列,数组 people 表示队列中一些人的属性(不一定按顺序)。每个 people[i] = [hi, ki] 表示第 i 个人的身高为 hi ,前面 正好 有 ki 个身高大于或等于 hi 的人。 请你重新构造并返回输入数组 people 所表示的队列。返回的队列应该格式化为数组 queue ,其中 queue[j] = [hj, kj] 是队列中第 j 个人的属性(queue[0] 是排在队列前面的人)。
因为[h,k]中的k是代表了前面比自己高的人有几个。因此先将身高从高到低排序,然后再依次根据k来安排他们的位置。
总的来说,难题还挺多的,套路不唯一,要想清楚怎么做,在什么情况应该怎么做。