刷题使我快乐,满脸开心.jpg

  • 来源:力扣(LeetCode)
  • 链接:https://leetcode.cn/problems/remove-k-digits/
  • 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题目

给你一个以字符串表示的非负整数 num 和一个整数 k ,移除这个数中的 k 位数字,使得剩下的数字最小。请你以字符串形式返回这个最小的数字。

示例 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 。

提示:

  • 1 <= k <= num.length <= 105
  • num 仅由若干位数字(0 - 9)组成
  • 除了 0 本身之外,num 不含任何前导零

思路

我们很容易就能想到,最高位越小,无论后面位数数字如何,整体数值都会越小,所以,我们就从左到右遍历,找最小的最高位、第二位、等等等等。
而至于如何代码实现,那可以考虑*单调栈*的思路:
1、从左至右每次拿一个数字,当比结果前面的数字小时则丢弃前面的数字,至多可以丢弃k个数字,遍历完num或者k0后则退出遍历,
2、当然,也有可能遍历完之后,k还是大于0,那么就需要截取下结果,从num尾部截取即可。

代码

func removeKdigits(num string, k int) string {
	if k >= len(num) {
		return "0"
	}

	numBytes := []byte(num)
	var resBytes []byte
	remain := len(num) - k
	for _, charByte := range numBytes {
		for k > 0 && len(resBytes) > 0 && resBytes[len(resBytes)-1] > charByte {
			resBytes = resBytes[:len(resBytes)-1]
			k--
		}
		resBytes = append(resBytes, charByte)
	}

	res := ""
	if len(resBytes) <= remain {
		res = strings.TrimLeft(string(resBytes), "0")
	} else {
		res = strings.TrimLeft(string(resBytes[:remain]), "0")
	}
	if res == "" {
		return "0"
	}
	return res
}