力扣135分糖果,贪心,力扣316,去除重复字符,贪心,单调栈

class Solution {
   public int candy(int[] ratings) {
       int n = ratings.length;
       int ret = 1;    //用于记录答案
       //pre用于记录前一个同学分得的糖果数量
       int inc = 1, dec = 0, pre = 1;
       for (int i = 1; i < n; i++) {
           if(ratings[i] >= ratings[i-1]){
               //处于递增序列中
               dec = 0;    //递减序列长度在递增序列中始终为0
               pre = ratings[i] == ratings[i- 1] ? 1 : pre+1;  //当前同学和上一个同学分数相等时,直接分配1个就行,这样满足最小
               ret += pre;
               inc = pre;      //inc用于记录上一个递增序列的长度

           }else {
               //处于递减序列中
               dec++;
               if(dec == inc){
                   //当递减序列长度和递增序列长度相等时,把递增序列的最后一个同学分配到递减序列中
                   dec++;
               }
               ret += dec; //这里加的dec相当于把递减序列翻转后加的每个同学的糖果数量
               pre = 1;    //pre在递减序列中没有意义,因为我肯定比前一个同学少;

           }
       }
       return ret;

   }
}

这里记录这些递增和递减序列是为了更好的加糖果,这里加糖果,相当于所有的递增序列的人都加一个糖果,递减就也是如此。

时间复杂度为O(n),遍历一遍,

char* removeDuplicateLetters(char* s) {
    int nums[26], len = strlen(s), vis[26];
    memset(nums, 0, sizeof(nums));
    memset(vis, 0, sizeof(vis));
    char* p = (char*)malloc(sizeof(char) * 27);
    for (int i = 0; i < len; i++) {
        nums[s[i] - 'a']++;
    }
    int Top = 0;
    for (int i = 0; i < len; i++) 
    {
        if (!vis[s[i] - 'a']) 
        {
            while (Top > 0 && p[Top - 1] > s[i]) 
            {
                if (nums[p[Top - 1] - 'a'] > 0) 
                {
                    vis[p[--Top] - 'a'] = 0;
                } else
                    break;
            }
            vis[s[i] - 'a'] = 1;
            p[Top++] = s[i];
        }
        nums[s[i] - 'a'] -= 1;
    }
    p[Top] = '\0';
    return p;
}

在考虑字符 s[i] 时,如果它已经存在于栈中,则不能加入字符 s[i]。为此,需要记录每个字符是否出现在栈中。

在弹出栈顶字符时,如果字符串在后面的位置上再也没有这一字符,则不能弹出栈顶字符。为此,需要记录每个字符的剩余数量,当这个值为 0 时,就不能弹出栈顶字符了。

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值