leetCode 402:移掉k位数字

目录

一、题目描述

二、解题思路

三、代码实现


一、题目描述

给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小。

注意:

  • num 的长度小于 10002 且 ≥ k。
  • num 不会包含任何前导零。

示例 1 :

输入: num = "1432219", k = 3
输出: "1219"
解释: 移除掉三个数字 4, 3, 和 2 形成一个新的最小的数字 1219。
 

示例 2 :

输入: num = "10200", k = 1
输出: "200"
解释: 移掉首位的 1 剩下的数字为 200. 注意输出不能有任何前导零。
 

示例 3 :

输入: num = "10", k = 2
输出: "0"
解释: 从原数字移除所有的数字,剩余为空就是0。

二、解题思路

本题的难点在于怎么找数,要使找到的数尽可能的小且不能改变相对的顺序,就意味着从左往右的遍历,对于当前正在遍历的数而言,如果前面的数比它大,那就要将其移除,这样新得到的数会更小,举例来说,1432219,如果现在遍历到的数是3,那么前面的4就要移除,因为14开头的数会比13开头的数大,同样当遍历到2时,前面的3就要移除,因为13开头的数要比12开头的数大;对每一个数字都进行这样的操作,最终得到结果。

如果想到了上述的操作流程,那么数据结构也就好选了,满足后进先出的结构那就是栈了。

还有一些细节需要注意的是,此题在遍历过程中并不一定能把所有要移除的数都找出来;还要注意结果中的前导0的处理。

到这里,这道题基本上就没有什么问题了。

三、代码实现

#include<bits/stdc++.h>  
using namespace std;

string removeKdigits(string num, int k) {
	int n = num.size();
	if (k == n) return "0";
	if (k == 0) return num;
	string res;
	//如果不想后面在逆置的话,可以用vector(只要前后都可以出入数据的数据结构就行)代替
	stack<char> chSta;
	chSta.push(num[0]);
	for (int i = 1; i < n; ++i) {
		//这里要注意,必须是栈顶元素大于当前值才弹出,等于不弹出,否则特殊情况的答案不正确
		while (!chSta.empty() && chSta.top() > num[i] && k) {
			chSta.pop();
			k--;
		}
		chSta.push(num[i]);
	}
	//如果弹出的数量没有K个,说明数据中间是维持升序的(比如一个升序的序列:112345)
	//那么要删除的数据处在末尾,弹出末尾对应的数量的数字即可
	while (k){
		chSta.pop();
		k--;
	}
	//拿出栈中的数据放到string中
	while (!chSta.empty()) {
		res += chSta.top();
		chSta.pop();
	}
	//逆置string
	reverse(res.begin(), res.end());
	//处理开头的‘0'
	if (res[0] == '0') {
		for (string::iterator it = res.begin(); it != res.end(); ) {
			if (*it == '0') {
				it = res.erase(it);
			} else
				break;
		}
	}
	if (res == "") return "0";
	return res;
}
int main() {
	string num = "113";
	num = removeKdigits(num, 2);
	cout << num;
	return 0;
}

强调一下:单调栈的使用一定是栈顶元素大于当前数才弹出,否则在特殊情况时的结果是不对的,要注意这个坑,调了一上午……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值