class Solution {
public:
int findContentChildren(vector<int>& g, vector<int>& s) {
//先排序
sort(g.begin(),g.end());
sort(s.begin(),s.end());
//遍历s的index,饼干数组的下标
int index=s.size()-1;
//喂饱的小孩数
int result=0;
//大饼干喂给胃口大的-->局部最优
for(int i=g.size()-1;i>=0;i--){
//先判断index, 否则若index==0,则 s[index]越界报错
if(index >= 0 && s[index] >= g[i]){
result++;
index--;
}
}
return result;
}
};
//贪心算法
class Solution {
public:
int wiggleMaxLength(vector<int>& nums) {
int n=nums.size();
if(n<=1){
return n;
}
//记录前一差值
int preDiff=0;
//记录当前差值
int curDiff=0;
// 记录峰值个数,序列默认序列最右边有一个峰值
int result=1;
for(int i=0;i<n-1;i++){
curDiff=nums[i+1]-nums[i];
//出现峰值
if(( preDiff>=0 && curDiff<0 ) ||( preDiff<=0 && curDiff>0 ) ){
result++;
preDiff=curDiff;
}
}
return result;
}
};
//动态规划
class Solution {
public:
int wiggleMaxLength(vector<int>& nums) {
int n=nums.size();
//status and define dp[][0]代表山峰,dp[][1]为山谷。
vector<vector<int>> dp(n,vector<int>(2));
if(n<2){
return n;
}
//base case
dp[0][0]=1;
dp[0][1]=1;
//transform
for(int i=1;i<n;i++){
dp[i][0]=1;
dp[i][1]=1;
//找山峰
for(int j=0;j<i;j++){
if(nums[i]>nums[j]){
dp[i][0]=max(dp[j][1]+1,dp[i][0]);
}
}
//找山谷
for(int j=0;j<i;j++){
if(nums[i]<nums[j]){
dp[i][1]=max(dp[j][0]+1,dp[i][1]);
}
}
}
return max(dp[n-1][0],dp[n-1][1]);
}
};
//另一种动态规划
class Solution {
public:
int wiggleMaxLength(vector<int>& nums) {
int n=nums.size();
//status and define dp_up[]代表最后一个为上升的最长序列长度,dp_down[]为最后一个为下降的最长序列长度。
vector<int> dp_up(n),dp_down(n);
if(n<2){
return n;
}
//base case
dp_up[0]=1;
dp_down[0]=1;
//transform
for(int i=1;i<n;i++){
if(nums[i]>nums[i-1]){
dp_up[i]=dp_up[i-1];
dp_down[i]=max(dp_down[i-1],dp_up[i-1]+1);
}else if(nums[i]<nums[i-1]){
dp_up[i]=max(dp_up[i-1],dp_down[i-1]+1);
dp_down[i]=dp_down[i-1];
}else{
dp_up[i]=dp_up[i-1];
dp_down[i]=dp_down[i-1];
}
}
return max(dp_up[n-1],dp_down[n-1]);
}
};
//另一种动态规划的优化
class Solution {
public:
int wiggleMaxLength(vector<int>& nums) {
int n=nums.size();
//status and define dp_up[]代表最后一个为上升的最长序列长度,dp_down[]为最后一个为下降的最长序列长度。
if(n<2){
return n;
}
//base case
int dp_up=1;
int dp_down=1;
//transform
for(int i=1;i<n;i++){
if(nums[i]>nums[i-1]){
// dp_up[i]=dp_up[i-1];
// dp_up=dp_up;
// dp_down[i]=max(dp_down[i-1],dp_up[i-1]+1);
dp_down=max(dp_down,dp_up+1);
}else if(nums[i]<nums[i-1]){
// dp_up[i]=max(dp_up[i-1],dp_down[i-1]+1);
dp_up=max(dp_up,dp_down+1);
// dp_down=dp_down;
// dp_down[i]=dp_down[i-1];
}else{
// dp_up[i]=dp_up[i-1];
// dp_down[i]=dp_down[i-1];
}
}
return max(dp_up,dp_down);
}
};
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int n=nums.size();
int result=0; //记录累计结果
int m_max=INT_MIN; //最大和
for(int i=0;i<n;i++){
result+=nums[i];
if(m_max<result){
m_max=result;
}
if(result<=0){ //结果为负数 重新计数
result=0;
}
}
return m_max;
}
};
class Solution {
public:
int maxProfit(vector<int>& prices) {
int result=0;
//局部最优,每天的利润最大化
for(int i=1;i<prices.size();i++){
result+=max(prices[i]-prices[i-1],0);
}
return result;
}
};
class Solution {
public:
bool canJump(vector<int>& nums) {
//跳跃可覆盖的最大距离到终点时为整体最优,每个位置跳跃最大距离为局部最优
int cover=0; //当前下标
//只有1个元素时,肯定可达
if(nums.size()==1){
return true;
}
for(int i=0;i<=cover;i++){
//max(此位置上可覆盖的最大距离,之前的cover)
cover=max(nums[i]+i,cover);
//可以覆盖
if(cover>=nums.size()-1){
return true;
}
}
return false;
}
};
class Solution {
public:
int jump(vector<int>& nums) {
//局部最优:每次走最远
if(nums.size()==1){
return 0;
}
int step=0;
for(int i=0;i<nums.size();i++){
//在此位置最大覆盖距离可以到达最后一个位置
if(i+nums[i]>=nums.size()-1){
step++;
return step;
}
//不能到达时
//记录每个元素跳跃后可再次可跳跃的最大位置
int pos_max=0;
//记录此次跳跃步数下标
int pos=i+1;
for(int j=i+1;j<i+1+nums[i];j++){
//找跳跃到下一个格子的最大距离
if(j+nums[j]>=pos_max){
pos_max=j+nums[j];
//下标减1
pos=j-1;
}
}
i=pos;
step++;
}
return step;
}
};
class Solution {
public:
static bool cmp(int a,int b){
return abs(a)>abs(b);
}
int largestSumAfterKNegations(vector<int>& nums, int k) {
//按绝对值从大到小排列
sort(nums.begin(),nums.end(),cmp);
//遇到负数,转为正数
for(int i=0;i<nums.size();i++){
if(k>0&&nums[i]<0){
nums[i]=-nums[i];
k--;
}
}
//K还没用完,反复转换最后一个负数
if(k%2==1) nums[nums.size()-1]*=-1;
return accumulate(nums.begin(),nums.end(),0);
}
};
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
//先看总油量和总耗量
int sum=0;
//油箱剩余的油最小值
int min_rest=INT_MAX;
for(int i=0;i<gas.size();i++){
sum+=gas[i]-cost[i];
min_rest=min(sum,min_rest);
}
//总油量<总耗量,不可能跑完
if(sum<0){
return -1;
}
//油箱剩余的油每次都够,从0出发就可以
if(min_rest>=0){
return 0;
}
//都不行,那就先找油,找最先让油箱有min_rest的油,要从后往前找
for(int i=gas.size()-1;i>=0;i--){
min_rest+=gas[i]-cost[i];
if(min_rest>=0){
return i;
}
}
return -1;
}
};
//第二种贪心
//局部最优:当前累加rest[j]的和curSum一旦小于0,起始位置至少要是j+1,因为从j开始一定不行。
//全局最优:找到可以跑一圈的起始位置。
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int start=0;
int today_sum=0;
int sum=0;
for(int i=0;i<gas.size();i++){
today_sum+=gas[i]-cost[i];
sum+=gas[i]-cost[i];
//第i天出现负油量,重新开始计算,从i+1开始
if(today_sum<0){
start=i+1;
today_sum=0;
}
}
if(sum<0){
return -1;
}
return start;
}
};
class Solution {
public:
int monotoneIncreasingDigits(int n) {
string strNum=to_string(n);
int flag=strNum.size();
for(int i=strNum.size()-1;i>0;i--){
if(strNum[i]<strNum[i-1]){
strNum[i-1]--;
flag=i;
}
}
for(int i=flag;i<strNum.size();i++){
strNum[i]='9';
}
return stoi(strNum);
}
};