给你一个以字符串表示的非负整数 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 。
为保证剩下数字最小,采用贪心算法。
- 局部最优情况:尽量保证小的数字在前 ->全局最优
- 遍历数组,当前数字大于栈顶数字(前一个数字)则一直出栈到k次数用完或者到小于等于当前数字为止。然后将当前数字入栈
- 若k次数没用完,则从队列尾端删除k个数字(因为后面进的比前面大,所有从后删除)
- 最后使用拼接字符串保存结构,并删除所有前置0
public static String removeKdigits(String num, int k) {
int len = num.length();
if (len <= k)
return "0";
char[] chars = num.toCharArray();
Deque<Character> deque = new LinkedList<Character>();
//优先队列,此处代替栈使用,可以简化掉字符串反转这一操作。
StringBuilder builder = new StringBuilder();
int i = 0;
while (i != len){
while (!deque.isEmpty() && chars[i] < deque.peekLast() && k != 0){
deque.pollLast();
k--;
}
deque.offerLast(chars[i++]);
}
for (int j = 0; j < k; ++j) {
deque.pollLast();
}
while (!deque.isEmpty()){
builder.append(deque.pollFirst());
}
while (builder.charAt(0) == '0' && builder.length() > 1)
builder.deleteCharAt(0);
return builder.toString();
}