K桁を移動
問題の説明:
文字列で表される負でない整数numを指定して、この数値のk桁の数値を削除して、残りの数値を最小にします。
注:
numの長さは10002未満でk以上です。
numには先行ゼロは含まれません。
例1:
入力:num = "1432219"、k = 3
出力: "1219"
説明:3つの数値4、3 、および2を削除して、新しい最小数1219を形成します。
例2:
入力:num = "10200"、k = 1
出力: "200"
説明:最初の1を削除し、残りの数は200です。出力に先行ゼロを付けることはできません。
例3:
入力:num = "10"、k = 2
出力: "0"
説明:元の数字からすべての数字を削除し、残りを空白のままにしてゼロにします。
問題解決のアイデア1:
1.貪欲な戦略。
2.質問ではk個の数値を削除する必要があります。私の方法は、適切な範囲のnum.size()-k個の数値を抽出することです。貪欲では実行できないため、最大値または最小値を毎回削除できます。正解はありません。
1432219最大のものを削除:1221;最小のものを削除:4329(もっと間違っています)。
3.適切な範囲はどれくらいですか?例:num = "1432219"、k = 3; 7-3、4の数値を検索することです。1432年から初めてそれを探す必要があるとき、219の次の3つは移動できません。1つを見つけたので、3つあることと、4つあることを確認する必要があります。
4.重要なのは、それを見つけた後の対処方法です。以下に示すように、1432、1を見つけた後、1を保存し、1:432219の後の数をインターセプトします。
![](https://img-blog.csdnimg.cn/20200416094303293.png)
![](https://img-blog.csdnimg.cn/20200416094149382.png)
![](https://img-blog.csdnimg.cn/2020041609450972.png)
![](https://img-blog.csdnimg.cn/20200416094644866.png)
5.適切な範囲で検索およびインターセプトすると、最終的に正しい答えを得ることができますが、時間の複雑さとスペースの複雑さが高すぎます。
コードは次のとおりです1。
string removeKdigits(string num, int k) {
if(num.size()<=k){//长度小于等于k则直接返回“0”
return "0";
}
string s;
k=num.size()-k;
while(k--){//选取num.size()-k个
char ch='9';
int n=0;//位置,方便截取
for(int i=0;i<num.size()-k;i++){//合适的范围
if(num[i]<ch){//寻找最小
ch=num[i];
n=i;
}
}
num=num.substr(n+1);//截取
s+=ch;//加上
}
int i=0;
while(s[i]=='0'){//开头的清零
i++;
}
s=s.substr(i);
if(s.size()==0){//清完0可能位空,所以这里要返回0
return "0";
}
return s;
}
![](https://img-blog.csdnimg.cn/20200415214146113.png)
解決策2:
1.上記の方法では、適切な範囲で最小のものを選択してから抽出し、スタックを使用して効率を向上させることができます。
2. numの各文字を循環的に判断し、スタックの一番上の要素が文字よりも大きいかどうかを判断します。大きい場合は、スタックから飛び出し、そうでない場合はスタックに飛び出し、文字列を小さいものから大きいものに並べ替える感覚があります。
3.問題ではスタックが削除され、スタックは一度k–であるため、kが十分に大きいかどうかに応じて、文字列が小さいものから大きいものに並べ替えられないことに注意してください。kの数を使い切ると、次の文字が考慮されますスタックの一番上の文字が小さい場合、スタックから抜け出す方法はありません。
4.スタックを使用する特殊なケースがあります。つまり、文字列は並べ替えられています。例:num = "123456789"、k = 3;次に、スタックをポップする方法がなく、取得する文字列が長すぎるため、文字列の長さが長すぎるかどうかを判断するには、長すぎる場合、次のk文字「123456789」を削除し、最後の3文字を削除して、最小の「123456」のままにします。
5.スタックを使用するには、文字列を取り出して順序を逆にする必要があります。もちろん、最初に出てくるので、最上位ビットが0かどうか、およびすべて0かどうかも判断する必要があります。
コードは次のとおりです2:
string removeKdigits(string num, int k) {
if(num.size()<=k){//长度小于等于k则直接返回“0”
return "0";
}
stack<char>s;
s.push(num[0]);
for(int i=1;i<num.size();i++){
while(!s.empty()&&k!=0&&s.top()>num[i]){
//栈空或者k的次数用完了或者栈顶最小则不用进入while
s.pop();//出栈
k--;//次数减一
}
s.push(num[i]);
}
string ss;
while(!s.empty()){//提取字符
ss+=s.top();
s.pop();
}
reverse(ss.begin(),ss.end());//逆序
int i=0;
while(ss[i]=='0'){//跳过最高位为0
i++;
}
ss=ss.substr(i);
if(ss.size()==0){//全为0
return "0";
}
if(ss.size()>n){//长度过长
return ss.substr(0,n);
}
return ss;
}
![](https://img-blog.csdnimg.cn/20200415214318111.png)