Lintcode: Delete Digits

Given string A representative a positive integer which has N digits, remove any k digits of the number, the remaining digits are arranged according to the original order to become a new positive integer. Make this new positive integers as small as possible.
N <= 240 and k <=N, 
Example
Given an integer A = 178542, k = 4

return a string "12"

第二遍作法:跟 Remove Duplicate Letters 和 Create Maximum Number很像html

維護一個stack,每次把當前char加進去,直到加到A.length()-k個。加以前看看能不能刪一些棧頂元素,條件:git

1. 棧非空算法

2. 當前元素<棧頂元素this

3. A後面剩的元素數目 >= A.length()-k-stack.size()spa

這樣弄出來棧裏面存着最後的數code

注意可能以0開頭,不要緊,由於題目是刪掉元素剩的最小的數,容許的,只用最後返回結果把開頭0去掉就行htm

 1 public class Solution {
 2     /**
 3      *@param A: A positive integer which has N digits, A is a string.
 4      *@param k: Remove k digits.
 5      *@return: A string
 6      */
 7     public String DeleteDigits(String A, int k) {
 8         // write your code here
 9         if (k == 0) return A;
10         if (A == null || A.length()==0 || A.length()==k) return "";
11         Stack<Character> stack = new Stack<Character>();
12         int len = A.length()-k;
13         for (int i=0; i<A.length(); i++) {
14             char c = A.charAt(i);
15             while (!stack.isEmpty() && c<stack.peek() && A.length()-i-1>=len-stack.size()) {
16                 stack.pop();
17             }
18             if (stack.size() < len) stack.push(c);
19         }
20         StringBuffer res = new StringBuffer();
21         while (!stack.isEmpty()) {
22             res.insert(0, stack.pop());
23         }
24         while (res.length()>0 && res.charAt(0)=='0') {
25             res.deleteCharAt(0);
26         }
27         return res.toString();
28     }
29 }

這道題跟Leetcode裏面的那道Next Permutation很像,那個題要找比一個數大的下一個數,因而從這個數的右邊開始,找第一個遞減的位置所在。這道題也是相似,只不過從這個數的左邊開始,找第一個遞減的位置所在。那道題是想要改動的影響最小,因此從右邊開始掃描。這道題是想要改動的影響最大,因此從左邊開始掃描。blog

這道題,刪掉一個數,至關於用這個數後面的數代替這個數。因此後面這個數必定要比當前小才行。因此找的是第一個遞減的位置,把大的那個數刪了。rem

這樣作一次就是找到了:刪除哪個數,使得剩下的數最小。對剩下的數再作k次,就能夠找到刪除哪k個數,使得剩下的數最小。這實際上是一個Greedy算法,由於這樣每作一次,獲得的都是當前最優的結果。get

看起來須要O(Nk)時間複雜度,但其實用一個Stack,再記錄pop了幾回,O(2N)就行了

 1 public class Solution {
 2     /**
 3      *@param A: A positive integer which has N digits, A is a string.
 4      *@param k: Remove k digits.
 5      *@return: A string
 6      */
 7     public String DeleteDigits(String A, int k) {
 8         Stack<Integer> st = new Stack<Integer>();
 9         int popCount = 0;
10         StringBuffer res = new StringBuffer();
11         for (int i=0; i<A.length(); i++) {
12             int num = (int)(A.charAt(i) - '0');
13             if (st.isEmpty()) st.push(num);
14             else if (num >= st.peek()) {
15                 st.push(num);
16             }
17             else {
18                 if (popCount < k) {
19                     st.pop();
20                     i--;
21                     popCount++;
22                 }
23                 else {
24                     st.push(num);
25                 }
26             }
27         }
28         while (popCount < k) {
29             st.pop();
30             popCount++;
31         }
32         while (!st.isEmpty()) {
33             res.insert(0, st.pop());
34         }
35         while (res.length() > 1 && res.charAt(0) == '0') {
36             res.deleteCharAt(0);
37         }
38         return res.toString();
39     }
40 }
相關文章
相關標籤/搜索