Leetcode 402.移掉k位数字
移调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。
题解:
从高位开始走,如果下一个数字比当前数字小,且要删除的数字次数每用完,则删除当前位置的数字,且继续向前比较,这样总能得到一个较小的序列。
具体来讲:
利用桟维持一个递增的序列,也就是说将字符串中字符依次入栈,如果当前字符比栈顶元素小,并且还可以继续删除元素,那么就将栈顶元素移掉,且继续向下一个栈顶元素比较,尽量维持序列递增,也可以算是一个贪心思想。最后移除字符串首部的所有 0 ,如果此时发现剩余的字符全为0,则输入 0 ,否则取非0 开始的前 num.length() - k 个元素构成一个序列即可。
由于最后要移除前面的 0 元素,可以用双端队列实现;
考虑到字符可以直接比较大小,所有用char[] 数组来模拟桟较为方便,最后从头往后查找定位第一个非0 元素即可。
1 class Solution { 2 public String removeKdigits(String num, int k) { 3 if (k <= 0) { 4 return num; 5 } 6 if (num.length() == 0 || k >= num.length()) { 7 return "0"; 8 } 9 int digits = num.length() - k;// 输出字符串的长度 10 char[] stk = new char[num.length()];// 模拟桟 11 int top = 0;// 记录栈顶元素的下一个位置 12 for (int i = 0; i < num.length(); i++) {// 遍历所有元素 13 char c = num.charAt(i); 14 while (top > 0 && stk[top - 1] > c && k > 0) {// 如果当前元素比栈顶元素小,则出栈 15 top--; 16 k--; 17 } 18 stk[top++] = c; // 将当前元素压桟 19 } 20 // 从头开始查找头个不为0的元素位置 21 int idx = 0; 22 while (idx < digits && stk[idx] == '0') { 23 idx++; 24 } 25 return idx == digits ? "0" : new String(stk, idx, digits - idx); //如果0的长度=所需长度(即剩下的都是0)则输出0,否则输出前digits长度的字符串 26 } 27 }