【LeetCode402】-移除K位数字

解题的前情提要

要理解贪心的思想,每一步都要选取当前最优的
适用范围: 线性的情况下,一般使用贪心和动态规划较多
常使用的数据结构: 贪心策略常结合栈数据结构

实现思想

数值的比较 1)总位数2)对应数字位上的数值

  • 在位数不同的情况下,位数越多的数值越大
  • 在位数相同的情况下,从最高位开始比较,最高位数值越大的数值越大,若相同比较次高位…直到比较出结果

思考过程
现在要考虑明白本怎么获取到正确的结果
从样例开始分析入手:
在这里插入图片描述
第一位为1,第二位为4

  • 删除1得到新的数为432219
  • 删除4得到新的数为132219

很明显后者比前者小,这个规律是在于,后一位的数值比当前数值大,肯定不能让后一位挪到前一位,必然导致数值增大,概括来说就是取二者之间最小的那位

在这个过程删除的操作一定是从前往后进行的,结果在最后才得到,符合栈数据结构的特点,可以考虑配合栈来实现。
特殊情况
之前所讨论的是一般情况,除此之外还要考虑别的特殊情况

情况一:
Q:当后面的元素一直小于当前最后的元素,是否一直舍弃最后的元素?
A:这是实现思想中的核心,在仍可以删除的情况下为取得最优解,一定要选择较小的数值在新的位置上
(这里面我原先有点没想明白,所以采取了从头遍历的方案,导致超时,实际上用while循环来实现即可)
情况二:
Q: 如果序列是单调递增的怎么办,也就没满足普遍情况的删除情况?
A:可以从后往前删除k个元素基克尔
情况三:
Q:怎么删除结果序列中多余的前置0
A:直接从源头上遏制,当栈中元素为空,且要压入是0的情况,不将该0压入里面

而且在实现的过程中,要考虑栈是否为空,k是否为0,结果字符串是否为空

数据结构

经过前面的分析之后,我们可以使用栈这一数据结构,在具体实现的时候可以使用vector,注意时要利用栈的特点,但并不一定要使用栈,使用了vector的好处在于便于将结果存入字符串中,而且栈也支持压入(push_back)和弹出(push_back)

实现代码

代码一
在这里插入图片描述
代码二

class Solution {
    
    
public:
    string removeKdigits(string num, int k) {
    
    
       vector<char> s;
       string re="";
       for(int i=0;i<num.size();i++){
    
    
           while(s.size()!=0&&k&&num[i]<s[s.size()-1]){
    
    
               s.pop_back();
               k--;
           }
           if(s.size()==0&&num[i]=='0'){
    
    
              continue;
           }
           else{
    
    
                s.push_back(num[i]);
           }
       }
       while(s.size()!=0&&k){
    
    
               s.pop_back();
               k--;
        }
       for(int i=0;i<s.size();i++){
    
    
           re.append(1,s[i]);
       }
       if(re==""){
    
    
           return "0";
       }
       return re;
    }
};

代码二主要优化了代码一的数字和字符的转换,这个转换我觉得是不必要的,本身用字符编码的特点也能比较出实际的数值大小

提交结果及分析

在这里插入图片描述

虽然有两层循环,但时间复杂度是O(n)的,只是一个线性的过程

猜你喜欢

转载自blog.csdn.net/weixin_44944046/article/details/113726524