对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。
思路:1. 先将两个数组进行排序
2. 从胃口最大的小孩开始遍历小孩数组
3. 一个循环就可以,通过index控制饼干的位置,每满足一个条件,index--
代码:
class Solution {
public:
int nums;
int findContentChildren(vector& g, vector& s) {
if (s.size() == 0) return 0;
sort(g.begin(),g.end(),less());
sort(s.begin(),s.end(),less());
int imax = min(g.size(), s.size());
int index = s.size() - 1;
for (int i = imax-1; i >= 0; i--) {
if (g[i] <= s[index]) {
nums++;
index--;
}
}
return nums;
}
};
思路:统计局部坡度,即 prediff 和 curdiff 的关系
注意要考虑边界问题 和 平坡 的情况
先排除数组长度为 1 的情况,然后设置最小输出的坡度数量为 1
如果 前一个坡度 prediff <= 0 && curdiff > 0 证明出现了一个最小拐点, 同理 prediff >= 0 && curdiff < 0
记得更新坡度 prediff = curdiff , i = 1开始
代码:
class Solution {
public:
int wiggleMaxLength(vector& nums) {
if (nums.size() == 1) return 1;
int prediff = 0;
int curdiff = 0;
int resul = 1;
for (int i = 1; i < nums.size(); i++) {
curdiff = nums[i] - nums[i - 1];
if ((prediff >= 0 && curdiff < 0) || (prediff <= 0 && curdiff > 0)) {
resul++;
}
prediff = curdiff;
}
return resul;
}
};
给你一个整数数组 nums
,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组 是数组中的一个连续部分。
思路:设置一个最小的值,然后从数组第一个元素开始遍历,当累加的值 > max时,max = count
当累加的值 < 0 时,重置为 0 (因为一个也没有的子序列的和就是 0 )
代码:
class Solution {
public:
int maxSubArray(vector& nums) {
int resul = INT32_MIN;
int count = 0;
for (int i = 0; i < nums.size(); i++) {
count += nums[i];
if (count >= resul) resul = count;
if (count <= 0) count = 0;
}
return resul;
}
};
给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。
在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。 返回 你能获得的 最大 利润 。
思路:
计算当天和前一天的利润,如果 >0 则取, <= 0 则不取
class Solution {
public:
int maxProfit(vector& prices) {
int resul = 0;
int profit = 0;
for (int i = 1; i < prices.size(); i++) {
profit = prices[i] - prices[i - 1];
if (profit < 0) {
profit = 0;
}
else {
resul += profit;
}
}
return resul;
}
};
数组中的每个元素代表你在该位置可以跳跃的最大长度。判断能否到达最后一个下标。
思路:每遍历一个元素,更新总体的覆盖范围,其覆盖范围 cover = i + nums[i]
当 cover >= nums.size() - 1 即代表可以到达最后一个下标
class Solution {
public:
bool canJump(vector& nums) {
if (nums.size() <= 1) return true;
int cover = nums[0];
for (int i = 0; i <= cover; i++) {
cover = max(cover, i + nums[i]);
if (cover >= nums.size() - 1) return true;
}
return false;
}
};
返回到达 nums[n - 1] 的最小跳跃次数。生成的测试用例可以到达 nums[n - 1]。
思路:
1.先排除数组的数目 <= 1 的情况
2.最小步数是由 n 个子覆盖所决定, subcover每更新一次,resul++, 第一个subCover = nums[0]
3.循环的条件是 i <= cover,
循环内部: i < cover 时, 更新 subCover = max(subCover, num[i] + i)
i == cover 时要更新 cover , cover = subCover, 满足条件要及时 break
代码:
class Solution {
public:
int jump(vector& nums) {
if (nums.size() == 1) return 0;
int resul = 1;
int cover = nums[0];
int subCover = cover;
if (cover >= nums.size() - 1) return resul;
for (int i = 0; i <= cover; i++) {
if (i < cover) {
subCover = max(subCover, i + nums[i]);
}
else {
subCover = max(subCover, i + nums[i]);
cover = subCover;
resul++;
if (cover >= nums.size() - 1) break;
}
}
return resul;
}
};
给你一个整数数组 nums
和一个整数 k
,选择某个下标 i 并将 nums[i] 替换为 -nums[i] 。
重复这个过程恰好 k 次。可以多次选择同一个下标 i 。
以这种方式修改数组后,返回数组可能的最大和 。
思路:要点:用绝对值进行从大到小进行排序,然后遍历数组,k > 0 && nums[i] < 0 就取反
代码:
class Solution {
public:
static bool cmp(const int& a, const int& b) {
return abs(a) > abs(b);
}
int largestSumAfterKNegations(vector& nums, int k) {
sort(nums.begin(), nums.end(), cmp);
int resul = 0;
for (int i = 0; i < nums.size(); i++) {
if (nums[i] < 0 && k > 0) {
nums[i] *= -1;
k--;
}
}
if (k % 2 != 0) nums[nums.size() - 1] *= -1;
for (auto a : nums) resul += a;
return resul;
}
};
加油站
思路:
当前的油站的油gas+目前车里的油不够到达cost,则该点不是起点
有一个 当前用油 curSum 和 totalSum, curSum < 0时 需要更新
start = i + 1;
代码:
class Solution {
public:
int canCompleteCircuit(vector& gas, vector& cost) {
int curSum = 0;
int totalSum = 0;
int start = 0;
for (int i = 0; i < gas.size(); i++) {
curSum += gas[i] - cost[i];
totalSum += gas[i] - cost[i];
if (curSum < 0) {
curSum = 0;
start = i + 1;
}
}
if (totalSum < 0) return -1;
return start;
}
};
你需要按照以下要求,给这些孩子分发糖果:
每个孩子至少分配到 1 个糖果。
相邻两个孩子评分更高的孩子会获得更多的糖果。
请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。
注意:
1.从左向右,如果右大于左,则右 = 左 + 1
2.从右向左,如果左大于右,则左 = max(左,右+ 1)
代码:
class Solution {
public:
int candy(vector& ratings) {
vector candy(ratings.size(), 1);
// 先从左向右遍历,左小于右,右就比左大 1
for (int i = 0; i < ratings.size() - 1; i++) {
if (ratings[i + 1] > ratings[i]) {
candy[i + 1] = candy[i] + 1;
}
}
// 从左向右遍历
for (int i = ratings.size() - 2; i >= 0; i--) {
if (ratings[i] > ratings[i + 1]) candy[i] = max(candy[i + 1] + 1,candy[i]);
}
int resul = 0;
for (auto a : candy) resul += a;
return resul;
}
};
class Solution {
public:
bool lemonadeChange(vector& bills) {
// vector wall(21,0);
int wall5 = 0, wall10 = 0;
for (int i = 0; i < bills.size(); i++) {
if (bills[i] == 5) {
wall5++;
}
else if (bills[i] == 10) {
if (wall5 > 0){
wall5--;
wall10++;
}
else return false;
}
else {
if (wall5 > 0 && wall10 > 0) {
wall5--;
wall10--;
}
else if (wall5 >= 3 && wall10 == 0) {
wall5 -= 3;
}
else return false;
}
}
return true;
}
};
先按身高从高到低进行排序,身高相等,前面人少的排前面(也就是people[1])
然后用 insert 去插入,先插入的是升高高的,后插入的人如果 [1] 和前面身高高的人相同,一定会插在他前面
代码:
class Solution {
public:
static bool cmp(const vector& a, const vector& b) {
if (a[0] == b[0]) return a[1] < b[1];
return a[0] > b[0];
}
vector> reconstructQueue(vector>& people) {
sort(people.begin(), people.end(), cmp);
vector> que;
for (int i = 0; i < people.size(); i++) {
int pos = people[i][1];
que.insert(que.begin() + pos, people[i]);
}
return que;
}
};
思路:先从 start 从小到大排序,然后进行判定:
若左气球的 end >= 右气球的 start 说明有一部分重合 右气球的 end 需要重新选择最小的边界
否则,没有重合,箭 + 1
代码:
class Solution {
public:
static bool cmp(const vector& a, const vector& b) {
return a[0] < b[0];
}
int findMinArrowShots(vector>& points) {
if (points.size() == 0) return 0;
sort(points.begin(), points.end(), cmp);
int resul = 1;
for (int i = 1; i < points.size(); i++) {
if (points[i][0] > points[i - 1][1]) resul++;
else points[i][1] = min(points[i - 1][1], points[i][1]);
}
return resul;
}
};
返回 需要移除区间的最小数量,使剩余区间互不重叠 。
思路:返回需要移除的区间,则可以记录 非交叉空间的个数(count)
上一个区间的 end 小于等于 下一个区间的 begin 即 end <= intervals[i][0];
然后更新 end count++
class Solution {
public:
static bool cmp(const vector& a, const vector& b) {
return a[1] < b[1];
}
int eraseOverlapIntervals(vector>& intervals) {
if (intervals.size() <= 1) return 0;
sort(intervals.begin(), intervals.end(), cmp);
int end = intervals[0][1];
int count = 1; // count 代表非重叠的个数
for (int i = 1; i < intervals.size(); i++) {
if (intervals[i][0] >= end) {
end = intervals[i][1];
count++;
}
}
return intervals.size() - count; // 总数 - 非重叠的个数 = 重叠的数
}
};
重点: 哈希表: hash[str[i] - 'a'] = i;
用来确定某一个字母所抵达的最大位置
然后遍历字符串,设定 left 和 right 当 i == right时,也就是当遍历到 i == hash[str[i] - 'a']
条件满足,push_back 到结果中
中间要进行起始位置的记录,Push 完之后起始位置要 +1
代码
class Solution {
public:
vector partitionLabels(string s) {
int hash[26];
for (int i = 0; i < s.size(); i++) {
hash[s[i] - 'a'] = i;
}
vector resul;
int lef = 0;
int rig = hash[s[0] - 'a'];
for (int i = 0; i < s.size(); i++) {
rig = max(rig, hash[s[i] - 'a']);
if (rig == i) {
resul.push_back(rig - lef + 1);
lef = rig + 1;
}
}
return resul;
}
};
其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。
思路:
1.先按左边界从小到大排序
2.建立 resul 容器,如果 interval[i - 1][1] < interval[i][0]
说明不重叠,就把 iterval[i]
push
到 resul
中
否则就进行覆盖,用 resul.back()[1] = 新的右边界就可以
代码:
class Solution {
public:
static bool cmp(const vector& a, const vector& b) {
return a[0] < b[0];
}
vector> merge(vector>& intervals) {
if (intervals.size() <= 1) return intervals;
sort(intervals.begin(), intervals.end(), cmp);
vector> resul;
resul.push_back(intervals[0]);
for (int i = 1; i < intervals.size(); i++) {
if (resul.back()[1] >= intervals[i][0]) {
resul.back()[1] = max(resul.back()[1],intervals[i][1]);
}
else {
resul.push_back(intervals[i]);
}
}
return resul;
}
};
当且仅当每个相邻位数上的数字 x 和 y 满足 x <= y 时,我们称这个整数是单调递增的。
给定一个整数 n ,返回 小于或等于 n 的最大数字,且数字呈 单调递增 。
思路:用到 to_string
和 stoi
进行转换
从后往前遍历,如果 i - 1 的 > i 标记 i 到最后统一由 i 之后的位置全部转换成 ‘9’
代码:
class Solution {
public:
int monotoneIncreasingDigits(int n) {
std::string str = to_string(n);
int flag = 0;
for (int i = str.size() - 1; i > 0; i--) {
if (str[i - 1] > str[i]) {
str[i - 1]--;
flag = i;
}
}
if (flag != 0) {
for (int i = flag; i < str.size(); i++) {
str[i] = '9';
}
}
return stoi(str);
}
};
代码:
class Solution {
public:
int resul;
int traversal(TreeNode* cur) {
if (cur == nullptr) return 2;
int lef = traversal(cur->left);
int rig = traversal(cur->right);
// 先判断 2 (有覆盖的情况)
if (lef == 2 && rig ==2) return 0;
// 再判断 0 的情况,先判断是否有无覆盖的情况,再判断有覆盖的情况
if (lef == 0 || rig == 0) {
resul++; //此时摄像头要 + 1
return 1;
}
// 判断 1 的情况
if (lef ==1 || rig == 1) return 2;
return -1;
}
int minCameraCover(TreeNode* root) {
resul = 0;
if (traversal(root) == 0) resul++;
return resul;
}
};