LeetCode 402 - Remove K Digits


https://leetcode.com/problems/remove-k-digits/
Given a non-negative integer num represented as a string, remove k digits from the number so that the new number is the smallest possible.
Note:
  • The length of num is less than 10002 and will be ≥ k.
  • The given num does not contain any leading zero.
Example 1:
Input: num = "1432219", k = 3
Output: "1219"
Explanation: Remove the three digits 4, 3, and 2 to form the new number 1219 which is the smallest.
Example 2:
Input: num = "10200", k = 1
Output: "200"
Explanation: Remove the leading 1 and the number is 200. Note that the output must not contain leading zeroes.
Example 3:
Input: num = "10", k = 2
Output: "0"
Explanation: Remove all the digits from the number and it is left with nothing which is 0.
X. Ordered Stack
https://blog.csdn.net/fuxuemingzhu/article/details/81034522
使用一个栈作为辅助,遍历数字字符串,当当前的字符比栈最后的字符小的时候,说明要把栈的最后的这个字符删除掉。为什么呢?你想,把栈最后的字符删除掉,然后用现在的字符进行替换,是不是数字比以前的那种情况更小了?所以同样的道理,做一个while循环!这个很重要,可是我没有想到。在每一个数字处理的时候,都要做一个循环,使得栈里面最后的数字比当前数字大的都弹出去。

最后,如果K还没用完,那要删除哪里的字符呢?毋庸置疑肯定是最后的字符,因为前面的字符都是小字符。
https://leetcode.com/problems/remove-k-digits/discuss/88675/Clear-Java-Solution-Using-Deque


 // the goal is to create an ascending sequence
public String removeKdigits(String num, int k) {
    if (num == null || num.length() == 0) return "0";
    Deque<Character> nums = new LinkedList<>();
    char[] digits = num.toCharArray();
    for (int i = 0; i < digits.length; i++) {
        while (!nums.isEmpty() && k > 0 && digits[i] < nums.peekLast()) {
            nums.pollLast();
            k--;
        }
        nums.offer(digits[i]);
    }
    
    while (k > 0) {
        nums.pollLast();
        k--;
    }
    
    while (!nums.isEmpty() && nums.peek() == '0') {
        nums.poll();
    }
    
    StringBuilder sb = new StringBuilder();
    while (!nums.isEmpty()) {
        sb.append(nums.poll());
    }
    
    return sb.length() == 0 ? "0" : sb.toString();
}
http://www.cnblogs.com/grandyang/p/5883736.html
http://blog.csdn.net/qq508618087/article/details/52584133
思路:其基本思想是利用栈尽量维持一个递增的序列,也就是说将字符串中字符依次入栈,如果当前字符串比栈顶元素小,并且还可以继续删除元素,那么就将栈顶元素删掉,这样可以保证将当前元素加进去一定可以得到一个较小的序列.也可以算是一个贪心思想.最后我们只取前len-k个元素构成一个序列即可,如果这样得到的是一个空串那就手动返回0.还有一个需要注意的是字符串首字符不为0
使得栈中的数字尽可能保持递增顺序。
首先分析一下什么样的数是最小的数。数总是有0~9的数字组成,高位的数字越小,这个数就越小。

所以,在对一个数做删除数字处理的时候,首先要从高位上把大的数字干掉,尽可能保留小的。

举个例子 num = "143219", k = 4

这个数字可以按照递增和递减分成三段 “1”, “4321”, “9”。递减子段上除了最后一个数字,其他的都可以被删除。

如果递减子段都处理完了,还没有删满k个,那就从最右边删(因为剩下的都是递增区间段了。)



1:    string removeKdigits(string num, int k) {  
2:      string res = "";  
3:        
4:      for(int i =0; i<num.size(); i++) {  
5:        while(res.size()>0 && res.back() > num[i]&& k>0) {  
6:          res.pop_back();  
7:          k--;  
8:        }  
9:        res.push_back(num[i]);  
10:      }  
11:        
12:      // if k != 0, remove the digit from right  
13:      res.erase(res.size() - k, k);  
14:        
15:      // trim the zero  
16:      int i =0;  
17:      while(res[i] == '0' && i<res.size()-1) i++;  
18:        
19:      res.erase(0, i);  
20:        
21:      return res.size() == 0? "0": res;  
22:    }  
https://segmentfault.com/a/1190000017514605
    public String removeKdigits(String num, int k) {
        Deque<Character> stack = new ArrayDeque<>();
        int n = num.length();
        if (k >= n) return "0";
        for (int i = 0; i < n; i++) {
            while (k > 0 && !stack.isEmpty() && stack.peek() > num.charAt(i)) {
                stack.pop();
                k--;
            }
            stack.push(num.charAt(i));
        }
        while (k > 0) {
            stack.pop();
            k--;
        }
        StringBuilder sb = new StringBuilder();
        while (!stack.isEmpty()) sb.append(stack.pop());
        sb.reverse();
        while (sb.length() > 1 && sb.charAt(0) == '0') sb.deleteCharAt(0);//bad
        return sb.toString();
    }
Use StringBuilder as stack
https://discuss.leetcode.com/topic/59580/short-10-lines-o-n-java-code
    public static String removeKdigits(String num, int k) {
        StringBuilder sb = new StringBuilder();
        for(char c : num.toCharArray()) {
            while(k > 0 && sb.length() != 0 && sb.charAt(sb.length() - 1) > c) {
                sb.setLength(sb.length() - 1);
                k--;
            }
            if(sb.length() != 0 || c != '0') sb.append(c);  // Only append when it is not leading zero
        }
        if(k >= sb.length()) return "0";
        sb.setLength(sb.length() - k);  // use all remaining k
        return sb.toString();  
    }
setLength(len -1) O(1)
public void setLength(int newLength) {
    if (newLength < 0)
        throw new StringIndexOutOfBoundsException(newLength);    ensureCapacityInternal(newLength);
    if (count < newLength) {
        Arrays.fill(value, count, newLength, '\0');    }

    count = newLength;}
Use array as stack
https://discuss.leetcode.com/topic/59412/a-greedy-method-using-stack-o-n-time-and-o-n-space
https://discuss.leetcode.com/topic/59501/6ms-java-solution-with-detailed-comment
    public String removeKdigits(String num, int k) {
        int digits = num.length() - k;
        char[] stk = new char[num.length()];
        int top = 0;
        // k keeps track of how many characters we can remove
        // if the previous character in stk is larger than the current one
        // then removing it will get a smaller number
        // but we can only do so when k is larger than 0
        for (int i = 0; i < num.length(); ++i) {
            char c = num.charAt(i);
            while (top > 0 && stk[top-1] > c && k > 0) {
                top -= 1;
                k -= 1;
            }
            stk[top++] = c;
        }
        // find the index of first non-zero digit
        int idx = 0;
        while (idx < digits && stk[idx] == '0') idx++;
        return idx == digits? "0": new String(stk, idx, digits - idx);
    }
http://www.voidcn.com/blog/yeqiuzs/article/p-6204756.html
    public String removeKdigits(String num, int k) {
        int len = num.length();
        //corner case
        if(k==len)        
            return "0";
            
        Stack<Character> stack = new Stack<>();
        int i =0;
        while(i<num.length()){
            //whenever meet a digit which is less than the previous digit, discard the previous one
            while(k>0 && !stack.isEmpty() && stack.peek()>num.charAt(i)){
                stack.pop();
                k--;
            }
            stack.push(num.charAt(i));
            i++;
        }
        
        // corner case like "1111"
        while(k>0){
            stack.pop();
            k--;            
        }
        
        //construct the number from the stack
        StringBuilder sb = new StringBuilder();
        while(!stack.isEmpty())
            sb.append(stack.pop());
        sb.reverse();
        
        //remove all the 0 at the head
        while(sb.length()>1 && sb.charAt(0)=='0')
            sb.deleteCharAt(0);
        return sb.toString();
    }
https://discuss.leetcode.com/topic/59646/straightforward-java-solution-using-stack
public String removeKdigits(String num, int k) {
        Stack<Integer> stack = new Stack<Integer>();
        if (num.length() == 0 || num.length() <= k)
            return "0";

        for (int i = 0; i < num.length(); i++) {
            int cur = num.charAt(i) - '0';
            while (!stack.isEmpty() && cur < stack.peek()
                    && num.length() - i - 1 >= (num.length() - k) - stack.size()) {
                stack.pop();
            }
            if (stack.size()<num.length()-k)
                stack.push(cur);
        }

        StringBuilder res = new StringBuilder();
        while (!stack.isEmpty())
            res.insert(0, stack.pop());

        while (res.length() > 0 && res.charAt(0) == '0')
            res.deleteCharAt(0);

        if (res.length() == 0)
            return "0";
        return res.toString();
    }
http://www.cnblogs.com/grandyang/p/5883736.html
这道题让我们将给定的数字去掉k位,要使得留下来的数字最小,这题跟LeetCode上之前那道Create Maximum Number有些类似,可以借鉴其中的思路,如果n是num的长度,我们要去除k个,那么需要剩下n-k个,我们开始遍历给定数字num的每一位,对于当前遍历到的数字c,进行如下while循环,如果res不为空,且k大于0,且res的最后一位大于c,那么我们应该将res的最后一位移去,且k自减1。当跳出while循环后,我们将c加入res中,最后我们将res的大小重设为n-k。根据题目中的描述,可能会出现"0200"这样不符合要求的情况,所以我们用一个while循环来去掉前面的所有0,然后返回时判断是否为空,为空则返回“0”
    string removeKdigits(string num, int k) {
        string res = "";
        int n = num.size(), keep = n - k;
        for (char c : num) {
            while (k && res.size() && res.back() > c) {
                res.pop_back();
                --k;
            }
            res.push_back(c);
        }
        res.resize(keep);
        while (!res.empty() && res[0] == '0') res.erase(res.begin());
        return res.empty() ? "0" : res;
    }
http://blog.csdn.net/mebiuw/article/details/52576884
* 这是一个非常简单的问题,贪心解决法 * 即 removeKdigits(num,k) = removeKdigits(removeKdigits(num,1),k-1) * 进行最多K轮的删除,每次从头开始寻找一位删除: * 1、要么第二位是0,这样相当于至少删了两位,很值得,必须这么做 * 2、不然,找到第一个出现下降转折的位置 删除 * */ public String removeKdigits(String num, int k) { int n; while(true){ n = num.length(); if(n <= k || n == 0) return "0"; if(k-- == 0) return num; if(num.charAt(1) == '0'){ int firstNotZero = 1; while(firstNotZero < num.length() && num.charAt(firstNotZero) == '0') firstNotZero ++; num=num.substring(firstNotZero); } else{ int startIndex = 0; while(startIndex < num.length() - 1 && num.charAt(startIndex) <= num.charAt(startIndex + 1)) startIndex ++; num=num.substring(0,startIndex)+num.substring(startIndex+1); } } }

X.
http://bookshadow.com/weblog/2016/09/18/leetcode-remove-k-digits/
解法II 问题可以转化为对偶问题:从字符串num中选取size - k个字符,使得选出的数字最小化。
首先利用字典numd保存数字'0' - '9'在原始字符串num中的出现位置。
然后循环size - k次:
按照'0' - '9'的顺序从numd中选取位置合法的数字
位置合法包含2条原则:1) 候选数字之后剩余的数字要足够多,2) 候选数字要处在已选出的数字之后
def removeKdigits(self, num, k): """ :type num: str :type k: int :rtype: str """ size = len(num) ans = '0' numd = collections.defaultdict(collections.deque) for i, n in enumerate(num): numd[n].append(i) p = 0 for x in range(size - k): for y in '0123456789': while numd[y] and numd[y][0] < p: numd[y].popleft() if numd[y] and numd[y][0] <= k + x: p = numd[y][0] ans += y numd[y].popleft() break return str(int(ans))

X.  https://discuss.leetcode.com/topic/59871/two-algorithms-with-detailed-explaination
The first algorithm is straight-forward. Let's think about the simplest case: how to remove 1 digit from the number so that the new number is the smallest possible? Well, one can simply scan from left to right, and remove the first "peak" digit; the peak digit is larger than its right neighbor. One can repeat this procedure k times, and obtain the first algorithm:
string removeKdigits(string num, int k) {
        while (k > 0) {
            int n = num.size();
            int i = 0;
            while (i+1<n && num[i]<=num[i+1])  i++;
            num.erase(i, 1);
            k--;
        }
        // trim leading zeros
        int s = 0;
        while (s<(int)num.size()-1 && num[s]=='0')  s++;
        num.erase(0, s);
        
        return num=="" ? "0" : num;
    }

http://www.1point3acres.com/bbs/thread-202732-1-1.html
给一个string, 找出lexical order 最小的, size==k的, subsequence, (note, not substring)
String findMin(String s, k){} 
e.g.
input
s=pineapple, k==3, 

output: ale
ale is the lexical order smallest subsequnce of length 3. 
我是暴力求解的: 
1. find the first occur position of distinct char. 
2. then start from that position. 
3. dfs to find lenght==3, subsequence(dfs, combination way); . visit 1point3acres.com for more.
4. find the one with smallest lexical order. 

我就是说了个大概.
pop的时候需要看后面还剩几个元素了
元素不够的时候就含泪不pop了,直接push进去
比如你说的例子,其实是
f->e->d->c->cb->cba
  1. public class Solution {
  2.         鏉ユ簮涓€浜�.涓夊垎鍦拌鍧�. 
  3.         public String removeKdigits(String num, int k) {. 1point3acres.com/bbs
  4.         if(num == null || num.length() == 0) return num;
  5.         int len = num.length();. 1point3acres.com/bbs
  6.         if(len == k) return "";
  7.         Stack<Character> stack = new Stack<Character>();
  8.         char []ch = num.toCharArray();
  9.         int i = 0, n = num.length();
  10.         while(i < len){

  11.             while(!stack.isEmpty() && stack.size() + n-i > k &&  stack.peek() > ch[i]){
  12.                 stack.pop();
  13.             }.鐣欏璁哄潧-涓€浜�-涓夊垎鍦�
  14.             stack.push(ch[i++]);
  15.         }. more info on 1point3acres.com
  16.         
  17.         // handle corner case 1111 or 1234, when k = 2. 涓€浜�-涓夊垎-鍦帮紝鐙鍙戝竷
  18.         while(stack.size() > k){-google 1point3acres
  19.             stack.pop();
  20.         }
  21.         
  22.         StringBuilder sb = new StringBuilder();
  23.         while(!stack.isEmpty()). Waral 鍗氬鏈夋洿澶氭枃绔�,
  24.           sb.insert(0, stack.pop());
  25.         
  26.         return sb.toString();
  27.         
  28.     }

  29.         public static void main(String[] args) {.鏈枃鍘熷垱鑷�1point3acres璁哄潧
  30.                 Solution s = new Solution();
  31.                 String str="xyzabc";
  32.                 int k=3;
  33.                 System.out.println(s.removeKdigits(str, k));
  34.         }. 鐗涗汉浜戦泦,涓€浜╀笁鍒嗗湴
  35. }

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts