860. 柠檬水找零
method 1
贪心的思想在于收到20时先使用10元找零
bool lemonadeChange(vector<int>& bills) {
vector<int> change;
for(int i=0; i<2; i++) change.push_back(0); // 0:5, 1:10, 2:20
for(int i=0; i<bills.size(); i++) {
if(bills[i]==5) change[0]+=1;
else if(bills[i]==10) {
if(change[0]>0) {
change[0]--;
change[1]++;
} else return false;
} else {
if(change[1]>0 && change[0]>0) {
change[0]--;
change[1]--;
} else if(change[0]>2) {
change[0]-=3;
} else return false;
}
}
return true;
}
392. 判断子序列
method 1
bool isSubsequence(string s, string t) {
if(!s.size()) return true;
for(int i=0; i<t.size(); i++) {
int loc = i;
for(int j=0; j<s.size(); j++) {
while(loc<t.size() && t[loc]!=s[j]) {loc++;}
if(loc == t.size()) return false;
if(j == s.size()-1) return true;
loc++;
}
}
return false;
}
method 2
如果s是t的一个子序列,那么一定在t中以相同的顺序出现过
bool isSubsequence(string s, string t) {
int sP=0;
for(int i=0; i<t.size(); i++) {
if(s[sP]==t[i]) sP++;
}
if(sP==s.size()) return true;
return false;
}
455. 分发饼干
method 1
双指针+贪心,如果满足不了这个孩子,就把饼干的指针后移;如果可以满足就跳出while,判断一下是不是满足的情况,然后孩子和饼干的指针都后移(根据进程的需求,找内存块的大小)
int findContentChildren(vector<int>& g, vector<int>& s) {
int ret=0, i=0, j=0;
sort(g.begin(), g.end());
sort(s.begin(), s.end());
while(i<g.size() && j<s.size()) {
while(j<s.size() && g[i]>s[j]) {
j++;
}
if(j<s.size()) ret++;
i++;
j++;
}
return ret;
}
55. 跳跃游戏
method1
每一步都看一下是否更新最远距离(如果能跳到一个位置,那么一定可以跳到之前的位置),并且第i个格子必须是我能跳到的位置
bool canJump(vector<int>& nums) {
int ret = 0;
for(int i = 0; i < nums.size() && i <= ret; i++) ret = max(ret, i + nums[i]);
return ret >= (nums.size() - 1) ? true : false;
}
45. 跳跃游戏 II
method 1
使用j标记最小代价到达的地方
int jump(vector<int>& nums) {
int v[10005] = {0};
for(int i = 0, j = 1; i < nums.size(); i++) {
while(j < nums.size() && j <= i + nums[i]) {
v[j] = v[j] == 0 ? v[i] + 1 : min(v[i] + 1, v[j]);
j++;
}
if(j == nums.size()) break;
}
return v[nums.size() - 1];
}
method 2
由于跳跃数组必定是分段递增的,所以使用l和r控制一个区间的左右端点,在循环中得到下个区间的最右侧,因为能到达最右侧一定可以到达途径的所有点,然后进行更新区间。
int jump(vector<int>& nums) {
if(nums.size() == 1) return 0;
int l = 0, r = 0, step = 0;
while(l <= r) {
int max_r = 0;
for(int i = l; i <= r; i++)
max_r = max(max_r, nums[i] + i);
l = r + 1, r = max_r;
step ++;
if(r >= (int)nums.size() - 1) break;
}
return step;
}
376. 摆动序列
method 1
我是用乘法来判断是否有拐点
int getDiraction(int l, int r) {
if(r > l) return -1;
else return 1;
}
bool judgeSameDiraction(int x, int y) {
if((x > 0 && y > 0) || (x < 0 && y < 0)) return true;
return false;
}
int wiggleMaxLength(vector<int>& nums) {
nums.erase(unique(nums.begin(), nums.end()), nums.end());
int n = nums.size();
if(n == 1 || (n == 2 && nums[0] != nums[1])) {
return n;
}
int r, dyn, ret = 2, d;
stack<int> visitedD;
for(int i = 0; i < n; i++) {
while(!visitedD.empty()) visitedD.pop();
d = getDiraction(nums[i], nums[i + 1]);
if(d == 0) continue;
visitedD.push(1);
visitedD.push(d*2);
dyn = i + 1, r = i + 2;
while(r < n) {
d = getDiraction(nums[dyn], nums[r]);
if(judgeSameDiraction(d, visitedD.top())) visitedD.push(visitedD.top());
else if(d > 0) visitedD.push(visitedD.top() * (-1) + 1);
else visitedD.push(visitedD.top() * (-1) - 1);
dyn ++;
r ++;
}
ret = max(abs(visitedD.top()), ret);
}
return ret;
}
method 2
实际上只使用局部极小值和局部极大值判断就行了,有局部极值一定是再最后的子序列中的
int wiggleMaxLength(vector<int>& nums) {
nums.erase(unique(nums.begin(), nums.end()), nums.end());
int n = nums.size();
if(n <= 2) return n;
int ret = 2;
for(int i = 1; i + 1 < n; i++) {
if((nums[i - 1] > nums[i]) && (nums[i + 1] > nums[i]) || (nums[i - 1] < nums[i]) && (nums[i + 1] < nums[i])) ret ++;
}
return ret;
}