122.买卖股票的最佳时机||
55.跳跃游戏
思路二:遍历数组,不断更新最大覆盖范围,从覆盖范围内寻找可以到达终点的值(不同的是需要加条件,当cover==i,也就是到了覆盖范围尽头时,如果nums[i]==0,就无法前进,直接break;
注意:思路一相当于思路二的简化版本,从思路二可以看出直接遍历覆盖范围可以达到明显优化。
class Solution {
public:
bool canJump(vector<int>& nums) {
int cover=0;
if(nums.size()==1) return true;
for(int i=0;i<nums.size()-1;i++){//遍历的是数组,所以需要终止条件
cover=max(cover,nums[i]+i);
if(cover>=nums.size()-1) return true;
if(cover==i && nums[i]==0) break;//终止条件
}
return false;
}
};
45.跳跃游戏||
思路一:
从起点开始记录第一个最大覆盖范围lastcover,然后lastcover中不断更新第二个最大覆盖范围cover;
当第一个最大覆盖范围走到尽头时,对尽头作出终点判断;
未到达则把第一个最大覆盖范围lastcover更新成第二个最大覆盖范围cover
此时再进行终点判断
class Solution {
public:
int jump(vector<int>& nums) {
int cover=0,precover=0;
int res=0;
for(int i=0;i<=precover;i++){
cover=max(cover,nums[i]+i);
if(i==precover){//上一个最大覆盖范围走到尽头
if(precover==nums.size()-1) break;//判断是否走到终点
else{
res++;//还需要跳跃
precover=cover;//更新最大覆盖范围
if(precover>=nums.size()-1) return res;//判断此时终点是否在最大覆盖范围内
}
}
}
return res;
}
};
1005.K次取反后最大化的数组和
思路:先把取反后大的数先取反
形式一:记录正负数的个数,然后判断K和负数的大小
-
当K<=负数个数,把所有负数取反为正
-
当K>负数个数,
-
首先判断是否存在0,存在0就可以对0操作,不改变数组和大小
-
其次判断K与负数个数的差值的奇偶性,奇数时只需要改变最小的数值,偶数值不需要改变(因为可以在同一个数上多次取反)
-
class Solution {
public:
int largestSumAfterKNegations(vector<int>& A, int K) {
//排序之后,然后判断负数的个数是否小于等于k
sort(A.begin(),A.end());
int F=0,Z=0;
for(int a:A){
if(a>0) Z++;
else if(a<0) F++;
}
//1.k<=F
//2.K>F (1)K-F为奇数 (2)K-F为偶数
int start=0,midF=F;
if(K<=F){//K<=F时,只需要对负数取反
while(K--) A[start++]*=-1;
}
else if(K>F){//K>F时,先对负数取反,判断是否存在0,再判断奇偶
while(midF--) A[start++]*=-1;
if(A[0]!=0){
if((K-F)%2!=0){
sort(A.begin(),A.end());
A[0]*=-1;
}
}
}
int res=0;
for(auto it:A) res+=it;//最后求数组和
return res;
}
};
形式二:优化版
class Solution {
static bool cmp(int a, int b) {
return abs(a) > abs(b);
}
public:
int largestSumAfterKNegations(vector<int>& A, int K) {
sort(A.begin(), A.end(), cmp); // 首先对绝对值进行排序(降序)
for (int i = 0; i < A.size(); i++) { // 把负数全部取反
if (A[i] < 0 && K > 0) {
A[i] *= -1;
K--;
}
}
if (K % 2 == 1) A[A.size() - 1] *= -1; // 如果k还有,就直接修改最小值
int result = 0;
for (int a : A) result += a; // 数组求和
return result;
}
};
134.加油站
思路一:遍历每一个加油站,然后记录当前剩余油量
剩余油量小于0时跳出当前开始
当遍历完成后,如果终止位置已经走了一圈,直接返回开始位置
结果:超出时间限制,注意数据量是10的5次方
思路二:贪心思想
首先记录当前油量,只要当前油量大于等于0,就可以继续遍历
当前油量小于0时,把出发位置放到当前遍历位置 i 的下一位(start=i+1),因为从 i 和 i 之前的位置出发一定无法走完全程;(注意,此时需要更新剩余油量为0,因为已经改变了出发位置为下一位,剩余油量是从0计算的)
遍历结束之后,只要剩余油量大于等于0,说明记录的start是可以走完全程的(因为存在唯一解)
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int n=cost.size();
int totalGas=0;
int curGas=0;
int start=0;
for(int i=0;i<n;i++){
totalGas+=gas[i]-cost[i];//计算总剩余油量
curGas+=gas[i]-cost[i];//计算从start开始的剩余油量
if(curGas<0){//从start走到i无法继续走了,说明0-i都无法走通
start=i+1;//从下一个位置开始
curGas=0;//重新开始为0
}
}
if(totalGas>=0) return start;//说明总油量够走完全程
return -1;
}
};
135.分发糖果
思路:考虑两边孩子和当前位置孩子的评分对比情况
class Solution {
public:
int candy(vector<int>& ratings) {
int n=ratings.size();
vector<int>candys(n,1);
for(int i=1;i<n;i++){//考虑右边孩子比左边孩子评分高
if(ratings[i]>ratings[i-1])
candys[i]=candys[i-1]+1;
}
for(int i=n-2;i>=0;i--){//考虑左边孩子比右边孩子评分高
if(ratings[i]>ratings[i+1])
candys[i]=max(candys[i],candys[i+1]+1);
}
int res=0;
for(auto it:candys)//总和
res+=it;
return res;
}
};
860.柠檬水找零
分析:已知顾客的金额已经固定,所以找的零钱也固定
思路一:面向题目编程
class Solution {
public:
bool lemonadeChange(vector<int>& bills) {
unordered_map<int,int>bils;
int n=bills.size();
for(int i=0;i<n;i++){
cout<<i<<endl;
if(bills[i]==5)//5元直接收
bils[5]++;
else{
if(bills[i]==20){//找15元
if(bils[10]>0 && bils[5]>0){//直接找10 和 5
bils[20]++;
bils[10]--;
bils[5]--;
}else if(bils[5]>=3){//找3 张5
bils[5]-=3;
bils[20]++;
}
else return false;
}else{//找5 元
if(bils[5]>0){
bils[10]++;
bils[5]--;
}
else return false;
}
}
}
return true;
}
};
406.根据身高重建队列
思路一:考虑多个维度,数组插入,自定义比较函数
维度一:身高
维度二:前面多少个比自己高或和自己一样高
在根据维度一排序后,然后根据维度二进行插入排序
class Solution {
public:
static bool cmp(const vector<int>&a,const vector<int>&b){
if(a[0]==b[0]) return a[1]<b[1];//身高相等的情况下,根据前面多少个比自己高或一样高的来排序
return a[0]>b[0];//按身高排序
}
vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
sort(people.begin(),people.end(),cmp);//先根据身高排序
vector<vector<int>>que;
for(int i=0;i<people.size();i++){
int position=people[i][1];//再根据前面多少个比自己高的来排序
que.insert(que.begin()+position,people[i]);
}
return que;
}
};