860.Lemonade Change
思路:每次判断收到的钱是5,10,还是20;用five和ten记录拥有的5元和10元个数,如果是5,那么直接five++,如果是10,那么ten++,five–(判断有没有5),如果20,判断有没有10,两种情况。
bool lemonadeChange(vector& bills) {
int five = 0,ten = 0;
for (int bill : bills) {
if (bill == 5)
five++;
else if (bill == 10) {
if (five < 1)
return false;
five --;
ten++;
}
else if (bill == 20) {
if (ten) {
if (five < 1)
return false;
ten--;
five--;
}
else {
if (five < 3)
return false;
five = five - 3;
}
}
}
return true;
}
455.Assign Cookies
思路:首先进行排序,让胃口小的和cookie小的在前面。然后从g中遍历,从胃口小的开始满足,如果满足则下一个child,如果不满足,那么下一个cookie,看是否满足。
int findContentChildren(vector& g, vector& s) {
int res = 0;
sort(g.begin(),g.end());
sort(s.begin(),s.end());
int i = 0, j = 0;
while (i < g.size() and j < s.size()) {
if (s[j] >= g[i]) {
res++;
i++;
j++;
}
else {
j++;
}
}
return res;
}
406.Queue Reconstruction by Height
思路:首先,进行排序,排序规则是,按照身高从大到小排序,如果相等,就按照排序从小到大排序(见sort函数),然后新建一个res数组,遍历排序后的数组,根据排序数字插入。
vector> reconstructQueue(vector>& people) {
vector> res;
sort(people.begin(),people.end(),[](pair a,pair b) {
return a.first > b.first || (a.first == b.first && a.second < b.second);
});
for (auto a : people) {
res.insert(res.begin() + a.second,a);
}
return res;
}
621.Task Scheduler
思路:
错误代码:主要是认为空挡部分可以放下剩下的字符,但是可能会出现这种情况,4A3B3C3D,n=2,则使用原来的思路(先放最多类的,再按照类别从前往后填空) 不能获得最小值。所以没有做出来。
int leastInterval(vector& tasks, int n) {
int res = 0;
int len = tasks.size();
vector cnt(26,0);
for (char c : tasks)
cnt[c - 'A']++;
sort(cnt.begin(),cnt.end());
int max_char = cnt[25];
int count = 0;
int i = 25;
while (i >=0 && cnt[i] == max_char){
i--;
count++;
}
if (count >= n+1) {
res = tasks.size();
}
else {//这里默认在空格地方,可以放下所有其他字符
res = (max_char - 1) * (n + 1) + count;
}
// res = max(len,(max_char - 1) * (n + 1) + count);
return res;
}
正确代码:
int leastInterval(vector& tasks, int n) {
int res = 0;
int len = tasks.size();
vector cnt(26,0);
for (char c : tasks)
cnt[c - 'A']++;
sort(cnt.begin(),cnt.end());
int max_char = cnt[25];
int count = 0;
int i = 25;
while (i >=0 && cnt[i] == max_char){
i--;
count++;
}
res = max(len,(max_char - 1) * (n + 1) + count);
return res;
}
738.Monotone Increasing Digits 单调递增数字
思路:首先把数字转化为字符串,然后对字符串进行操作。观察规律可以知道,从后往前比较,当i-1个数比第i个数大的话,也就是说前边一个数字比后边的数大,那么就让i-1个数减1,后边的数变成最大数字9,我们只需要遍历一遍,记录从后向前数,最后一个需要减1的位置,也就是j,那么把j 之后的数都变成9。
int monotoneIncreasingDigits(int N) {
string str_N = to_string(N);
int n = str_N.size();
int j = n;
for (int i = n - 1;i > 0; i--) {
if (str_N[i] >= str_N[i-1])
continue;
str_N[i-1] = str_N[i-1] - 1;
j = i;
}
for (int i = j; i < n; i++) {
str_N[i] = '9';
}
return stoi(str_N);
}
435.Non-overlapping Intervals.非重叠数字
思路:首先对数字对进行排序,然后遍历,如果i个数字对的end大于i+1个数字对的start,说明有重叠,res++,那么就让下一个数字对的end设置为这两个重复数字对中end小的那个,然后继续比对。
int eraseOverlapIntervals(vector& intervals) {
int n = intervals.size();
int res = 0;
int last;
sort(intervals.begin(),intervals.end(),[](Interval& a,Interval& b){
return a.start < b.start;
});
for (int i = 0; i < n-1; i++) {
if (intervals[i].end > intervals[i+1].start) {//说明有重叠
res++;
intervals[i+1].end = min(intervals[i].end,intervals[i+1].end);
}
}
return res;
}
870.Advantage Shuffle
思路:这是个田忌赛马的问题。 B 数组中的每个数字找到与之对应 A 数组中大于它的最小值,如果没有则将其设为 A 数组中没处理数据的最小值。其中用到了C++中map.upper_bound函数(第一次见),所以感觉有点复杂。
vector advantageCount(vector& A, vector& B) {
vector res;
map m;
map::iterator iter;
int curNum;
for (auto a : A)
m[a]++;
for (auto b : B) {
iter = m.upper_bound(b);
if (iter != m.end()) {
curNum = iter->first;
}
else {
curNum = m.begin()->first;
}
res.push_back(curNum);
m[curNum]--;
if (m[curNum] == 0)
m.erase(curNum);
}
return res;
}
881.Boats to Save People
思路:先按照体重进行排序,然后每次选取第一个和最后一个进行组合,如果小于limit,说明可以同时拉两个人,i++,j–,res++,如果大于limit,那么只拉重的那个人,i不变,j–,res++;但是这个方法时间太慢。
int numRescueBoats(vector& people, int limit) {
int res = 0;
sort(people.begin(),people.end());
int n = people.size();
int i = 0,j = n-1;
while (i <= j) {
if (people[i] + people[j] <= limit) {
i++;
j--;
}
else {
j--;
}
res++;
}
return res;
}
767.Reorganize String
思路:这道题的目的是字符串中不能有相同的字符相邻,那么如果最多的那个字符的个数超过了字符串长度的一半,那么一定会相邻,这时候返回“”,反之,一定可以实现这个目标。
统计每个字符的个数,并没有用map,而是用的vector,数量*100,然后+字母序号,最后的vector的值%100,结果就是字符,/100就是字符个数,这里相当秀,用vector同时表示了个数和字符。然后对vector进行排序,从数量最多的字符开始放,而且是隔位放,这样可以保证相同字符一定不相邻。因为原字符串S已经没有用,我们可以在S上进行原址赋值操作。
string reorganizeString(string S) {
int n = S.size();
int j = 0;
vector char_num(26,0);
for (auto c : S) {
char_num[c - 'a'] += 100;
}
for (int i = 0; i < 26; i++) {
char_num[i] += i;
}
sort(char_num.begin(),char_num.end());
for (int i = 25; i >= 0; i--) {
char c = char_num[i] % 100 + 'a';
int num = char_num[i] / 100;
if (num > (n+1)/2)
return "";
for (int k = 0; k < num; k++) {
S[j] = c;
j += 2;
if (j >= n)
j = 1;
}
}
return S;
}
659.Split Array into Consecutive Subsequences
思路:参考思路
bool isPossible(vector& nums) {
unordered_map cnt,tails;
for (int num : nums)
cnt[num]++;
for (int num : nums) {
if (cnt[num] <= 0)
continue;
else if (tails[num-1] > 0) {//说明num可以连接上前面的连续数组
tails[num-1]--;
tails[num]++;
}
else if (cnt[num+1] > 0 && cnt[num+2] > 0) {//重新一个新连续数组
tails[num+2]++;
cnt[num+1]--;
cnt[num+2]--;
}
else {
return false;
}
cnt[num]--;
}
return true;
}
134.Gas Station
思路:last表示上一个剩余的gas,然后从start开始计算一个环的路程,计算此gas[(start + j) % n] + last - cost[(start + j) % n] < 0,说明走不下去,那么从下一个站点开始算。最后结束如果j的值等于n,说明可以走完环。
int canCompleteCircuit(vector& gas, vector& cost) {
int n = gas.size();
for (int i = 0; i < n; i++) {
int last = 0;
int start = i;
int j = 0;
for (j = 0; j < n; j++) {
if (gas[(start + j) % n] + last - cost[(start + j) % n] < 0) {
break;
}
last += gas[(start + j) % n] - cost[(start + j) % n];
}
if (j == n)
return start;
}
return -1;
}
思路2:此方法和上一个思路相同,但是多加了一个处理步骤。也就是i = start + j;当start = i的时候,不可能走完全程,那么说明从start到start+j这一段上的所以点都不可以当做起点,那么我们下一次起始点就不用i+1啦,而是变成start+j+1.所以设置为start+j,加上循环的i++。
int canCompleteCircuit(vector& gas, vector& cost) {
int n = gas.size();
for (int i = 0; i < n; i++) {
int last = 0;
int start = i;
int j = 0;
for (j = 0; j < n; j++) {
if (gas[(start + j) % n] + last - cost[(start + j) % n] < 0) {
i = start + j;
break;
}
last += gas[(start + j) % n] - cost[(start + j) % n];
}
if (j == n)
return start;
}
return -1;
}
55.Jump Game
思路:计算每一个位置可以到达的最远的位置。如果大于等于最后一个位置,退出循环;如果当i大于reach的时候,说明前边的步骤到不了i位置,也退出循环。最后看reach的值是不是大于等于最后位置。
bool canJump(vector& nums) {
int n = nums.size();
int reach = 0;
for (int i = 0; i < n; i++) {
if (reach >= (n-1) || i > reach) break;
reach = max(reach,i + nums[i]);
}
return reach >= (n-1);
}