Showing posts with label Scan from right. Show all posts
Showing posts with label Scan from right. Show all posts

LeetCode 1014 - Best Sightseeing Pair


https://leetcode.com/problems/best-sightseeing-pair/
Given an array A of positive integers, A[i] represents the value of the i-th sightseeing spot, and two sightseeing spots i and j have distance j - i between them.
The score of a pair (i < j) of sightseeing spots is (A[i] + A[j] + i - j) : the sum of the values of the sightseeing spots, minus the distance between them.
Return the maximum score of a pair of sightseeing spots.

Example 1:
Input: [8,1,5,2,6]
Output: 11
Explanation: i = 0, j = 2, A[i] + A[j] + i - j = 8 + 5 + 0 - 2 = 11

Note:
  1. 2 <= A.length <= 50000
  2. 1 <= A[i] <= 1000

X. Scan from right to left
https://leetcode.com/problems/best-sightseeing-pair/discuss/261067/Detailed-Explanation-using-DP-O(n)-Time-or-O(1)-Space
int Solution :: maxScoreSightseeingPair(vector<int>& a)
{
    int n = a.size();
    int maxOverallGain = INT_MIN;
    int maxEndRight = a[n-1] - (n-1);
    for(int i=n-2; i>=0; i--)
    {
        maxEndRight = max(maxEndRight, a[i+1] - (i+1));
        maxOverallGain = max(maxOverallGain, a[i] + i + maxEndRight);
    }
    return maxOverallGain;
    
}

X.
https://leetcode.com/problems/best-sightseeing-pair/discuss/260909/JavaPython-Descriptive-solution.O(N)-Time-or-O(1)-Space.-Very-similar-to-Kadence-Algo!
The goal is to keep track of:
  • Maximum So far and add it to the cur_cell and maintain maximum result
  • Here, max_so_far contains : A[i] + i
Original Given Formula : A[i] + A[j] + i - j
  • Break in two parts : A[i] + i and A[j] -j
  • Keep MAX_VALUE of first part among the elements seen so far
  • Add the current element to max_so_far and check the result is changing or not
  • Also, keep updating the max_so_far at each step
    public int maxScoreSightseeingPair(int[] a) {
        int max_so_far = a[0];
        int result = 0;
        for(int i=1;i<a.length;i++){
            result = Math.max(result, max_so_far + a[i] - i);
            max_so_far = Math.max(max_so_far, a[i] + i);
        }   
        return result;
    }
https://leetcode.com/problems/best-sightseeing-pair/discuss/260850/JavaC%2B%2BPython-One-Pass
Count the current best score in all previous sightseeing spot.
Note that, as we go further, the score of previous spot decrement.

Explanation

cur will record the best score that we have met.
We iterate each value a in the array A,
update res by max(res, cur + a)
Also we can update cur by max(cur, a).
Note that when we move forward,
all sightseeing spot we have seen will be 1 distance further.
So for the next sightseeing spot cur = Math.max(cur, a) **- 1**
It's kinds of like, "A near neighbor is better than a distant cousin."
https://leetcode.com/problems/best-sightseeing-pair/discuss/260884/C%2B%2B-O(n)-best-time-to-buy-and-sell-stock
It's similar to Best Time to Buy and Sell Stock, but instead of min price, we track max value, and our max value decays every step due to the distance penalty.

Solution

  • Track the maximum value of A[i] as max_i.
  • Every turn, decrement max_ito account for j - i.
  • Track and return the maximum score.
    public int maxScoreSightseeingPair(int[] A) {
        int max = A[0];
        int res = Integer.MIN_VALUE;
        for (int i = 1; i < A.length; i++) {
            max = Math.max(max, A[i - 1] + i - 1);
            res = Math.max(res, max + A[i] - i);
        }
        return res;
    }

https://leetcode.com/problems/best-sightseeing-pair/discuss/261411/Java-O(N)-Easy-to-Understand-Clean-Code-beats-100

LeetCode 880 - Decoded String at Index


https://leetcode.com/problems/decoded-string-at-index/
An encoded string S is given.  To find and write the decoded string to a tape, the encoded string is read one character at a time and the following steps are taken:
  • If the character read is a letter, that letter is written onto the tape.
  • If the character read is a digit (say d), the entire current tape is repeatedly written d-1 more times in total.
Now for some encoded string S, and an index K, find and return the K-th letter (1 indexed) in the decoded string.

Example 1:
Input: S = "leet2code3", K = 10
Output: "o"
Explanation: 
The decoded string is "leetleetcodeleetleetcodeleetleetcode".
The 10th letter in the string is "o".
Example 2:
Input: S = "ha22", K = 5
Output: "h"
Explanation: 
The decoded string is "hahahaha".  The 5th letter is "h".
Example 3:
Input: S = "a2345678999999999999999", K = 1
Output: "a"
Explanation: 
The decoded string is "a" repeated 8301530446056247680 times.  The 1st letter is "a".
Note:
  1. 2 <= S.length <= 100
  2. S will only contain lowercase letters and digits 2 through 9.
  3. S starts with a letter.
  4. 1 <= K <= 10^9
  5. The decoded string is guaranteed to have less than 2^63 letters
https://www.acwing.com/solution/LeetCode/content/779/
首先计算出解码后的字符串的长度 len。
然后倒序遍历字符:(1) 当前字符为小写字母,若 K == len,则说明当前字母就是索引 K,直接返回;否则 len 自减 1。(2) 当前字符为数字,则先将 len = len / S[i],找到重复之前的长度。若 K % len == 0,则说明索引 K 是循环节的最后一个字母,则直接从 i 开始向前找到第一个字母并返回即可。否则,K = K % len。
https://blog.csdn.net/fuxuemingzhu/article/details/81977433
如果模拟题目中的操作进行解码,空间占用过大,一定会通不过。而且,题目只要求了求指定位置的字符,并没有要求所有的字符,所以全部解码没有必要。

参考了官方的解答。思路如下:

比如,对于一个解码了的字符串,appleappleappleappleappleapple,并且要求的索引K=24的话,那么结果和K=4是一样的。因为单词apple的size=5,重复了6次。所以第K个索引和第K%size个索引是一样的。

所以我们使用反向的计算,保持追踪解码字符串的size,如果解码字符串等于一个word重复了d次的时候,我们可以把K变化为K % (word.length).

算法:

首先,找出解码字符串的长度。然后,我们反向查找,保持追踪size,也就是对编码字符串S[0], S[1], ..., S[i]解码后的长度。

如果找到的是一个数字S[i],那么意味着解码字符串S[0], S[1], ..., S[i-1]的长度应该是size / Integer(S[i]);否则应该是size-1.
https://blog.csdn.net/qq_26440803/article/details/84261151
从题目的意思来看,我们可以很容易的使用暴力破解的方式来解决,但是可以肯定的是会超时。接下来我们选择逆向思维来解题,由于该题每次碰到数字都会将前面一段字符串重复d-1次,也就是说,每次遇见数字,那么数字之前的的字符串会重复d次。那么我们这样一来我们就可以将所得的结果分成d等份,这样每个等份的结果都是一样的。

在这里还需要提到一个特性:如果一个单词的长度为n,它重复x此,那么我们在这个单词组成的字符串中,任意K与K%n的结果都一样。

举个栗子:

字符串leetleetleetleetleetleet,对于单词leet来说重复6次,我们取K=3,那么3%4与K=3的结果是一样的。利用这些特性我们可以使用逆向思维的方式,将字符串逐渐缩小范围求解,如果我们求k那么可以转换为K%n,这样一步一步我们就可以不用考虑内存,考虑时间问题。

首先我们需要先求出字符串的长度,出现数字直接做乘法,否则我们自增。

然后我们对初始字符串进行倒序遍历,由于题目的设定,我们最后一位肯定是数字,那么我们可以认为,之前的字符串重复d次,这样我们可以利用上面的特性对所求的字符串进行缩减K%n。我们所求的目标K一定在第一个重复的字符串中,以题目例子来说:

leet2code3->leetleetcodeleetleetcodeleetleetcode 缩减一下

leetleetcode k一定是在这个字符串中,因为k与k%n结果等价。

由于上述操作我们实际上是截去了一部分字符串,将重复的n次截取掉了n-1次,接下来就需要缩减size了,这对于求size是一个逆向的过程,所以我们遇见字符串就自减,遇见数字做除法。

然后重复我们之前的操作,对于k缩减为K%n,一直到满足K缩减为0,且它必须是一个字符。

当k=10,针对leetleetcode来说,K==K%10,因为此时K小于了单词的长度,所以起不到截取的目的,不能够缩小检索的范围,所以我们可以为了缩小范围,我们从后面开始遍历,对于非数字自减,这样我们就可以缩小size的范围,且不影响K,当k==size则满足我们的要求。正面检索到了我们需要的位置。

https://blog.csdn.net/zjucor/article/details/81429686
Discuss里有很简单的写法:先往右扩,扩到超过K,然后往回退

idea真的很simple,但是确实有效,其实就是个stack,看到题目应该要能想到能用stack来解的

We decode the string and N keeps the length of decoded string, until N >= K.
Then we go back from the decoding position.
If it's S[i] = d is a digit, then N = N / d before repeat and K = K % N is what we want.
If it's S[i] = c is a character, we return c if K == 0 or K == N

https://leetcode.com/articles/decoded-string-at-index/
Approach 1: Work Backwards
If we have a decoded string like appleappleappleappleappleapple and an index like K = 24, the answer is the same if K = 4.
In general, when a decoded string is equal to some word with size length repeated some number of times (such as apple with size = 5 repeated 6 times), the answer is the same for the index K as it is for the index K % size.
We can use this insight by working backwards, keeping track of the size of the decoded string. Whenever the decoded string would equal some word repeated d times, we can reduce K to K % (word.length).
Algorithm
First, find the length of the decoded string. After, we'll work backwards, keeping track of size: the length of the decoded string after parsing symbols S[0], S[1], ..., S[i].
If we see a digit S[i], it means the size of the decoded string after parsing S[0], S[1], ..., S[i-1]will be size / Integer(S[i]). Otherwise, it will be size - 1.

  public String decodeAtIndex(String S, int K) {
    long size = 0;
    int N = S.length();

    // Find size = length of decoded string
    for (int i = 0; i < N; ++i) {
      char c = S.charAt(i);
      if (Character.isDigit(c))
        size *= c - '0';
      else
        size++;
    }

    for (int i = N - 1; i >= 0; --i) {
      char c = S.charAt(i);
      K %= size;
      if (K == 0 && Character.isLetter(c))
        return Character.toString(c);

      if (Character.isDigit(c))
        size /= c - '0';
      else
        size--;
    }

    throw null;
  }

https://leetcode.com/problems/decoded-string-at-index/discuss/157390/Logical-Thinking-with-Clear-Code
Only the character in the Kth position matters rather than the whole string decoded, so we only keep track of curLength (long data type to avoid integer overflow).
Let's see the code commented, first a1, a2, then b1, b2. They are matching except that we manage K in a2, b2.
Since the result character can only be a letter rather than digit, in b2 we ought to check K. Whenever K % curLength == 0, we figure out the result.
    public String decodeAtIndex(String S, int K) {
        
        long curLength = 0;
        char c = 0;
        
        for (int i = 0; i < S.length(); i++) {
            c = S.charAt(i);
            if (Character.isDigit(c)) { \\ a1
                curLength *= c - '0';
            }
            else { \\ b1
                curLength++;
            }
        }
        
        for (int i = S.length() - 1; i >= 0; i--) {
            c = S.charAt(i);
            if (Character.isDigit(c)) { \\ a2
                curLength /= c - '0';
                K %= curLength;
            }
            else { \\ b2
                if (K == 0 || K == curLength) {
                    return "" + c;
                }
                curLength--;
            }
        }
        
        throw null;
    }

X. https://buptwc.com/2018/08/05/Leetcode-884-Decoded-String-an-Index/

  1. 这道题是把字符串按照给定的规则展开,然后返回展开后的字符串的第K个字符,应该要怎么思考呢?
  2. 我不知道大家注意到note的第5点没有,为什么他在这里突然加这么一点,告诉我们长度小于2^63,其实就是在暗示我们要用到总长度(因为我们不可能真把展开后的字符串写出来)
  3. 然后这里的测试样例也有点迷惑作用,因为他故意不给出最后以字符结尾的例子,就是担心把思路直接暴露出来了,我们来看一个例子
  4. S = ‘leet2code3problem’,这个字符串展开后总长度为43,’problem’是没有重复的部分,前面’leet2code3’总长度是36,那么假设此时K = 37,38,39…,43,我们可以直接得出答案。那如果K小于37呢,那么问题是不是可以转换成在S=’leet2code3’求第K个字符(多余的部分可以直接不要)
  5. 当以数字结尾时,那么整个字符串就是S[:-1]的若干次重复,例如此时S=’leet2code3’的长度为36,设K=18吧,那么基本字符串的长度应该为36/3=12,那么我们要求的字符应该是第18%12=6个字符,现在问题转换成了S=’leet2code’,K=6,又变成我们第4点中分析的情况了,依次类推即可
思路:
  1. 分析过程很简单明了,但是代码却不太好写,比较繁杂
  2. 我们先去找S中最后一个数字的位置,然后判断K是不是处于这个数字后面的那串字符串中(关键),若是则直接返回
  3. 若不是则改变S,K的值,注意了我们的总长度不能每次改变一次S重新计算一次,那样太麻烦了(不过我猜应该不会超时,因为s长度不超过100),而是每次通过减去多余字符串的长度和除以结尾数字来改变!!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Solution(object):
    def decodeAtIndex(self, S, K):
        """
        :type S: str
        :type K: int
        :rtype: str
        """
        # 先计算总长度
        M = 0
        for i in range(len(S)):
            if '1' < S[i] <= '9': M *= int(S[i])
            else: M += 1
        
        def helper(S,K,M):
            # 找到最后数字出现的位置
            index = -1
            for i in range(len(S)-1,-1,-1):
                if '1' < S[i] <= '9': index = i;break
            # 若没有数字,说明已经是最简字符串了,直接返回即可
            if index == -1: return S[K-1]
            # 判断K是不是在数字后面的那串字符串中
            if M-K < len(S)-1-index: return S[K-M-1]
            # 先减去多余字符串的长度,然后再除以最后数字的大小,然后调整K的大小
            M -= len(S)-index-1
            M //= int(S[index])
            K %= M
            # 这里一个小问题,假如K=3,M=3,那么实际应该返回第三个字符但是这里去mod的话会是0,所以要单独处理这种情况
            if K == 0: K = M
            return helper(S[:index],K,M)
        return helper(S,K,M)



X. http://hehejun.blogspot.com/2018/08/leetcodedecoded-string-at-index.html
首先我们可以从左到右遍历到第K个字符,慢慢展开字符串即可。但是这种方法显而易见是有缺点的,如果展开的字符串太长是会MLE的。时间复杂度为O(N),但是空间复杂度可能非常大
    string decodeAtIndex(string S, int K) {
        string pattern;
        int len = S.size();
        for(int i = 0; i < len; ++i)
        {
            if (isalpha(S[i]))
            {
                if (--K == 0)return string(1, S[i]);
                pattern += S[i];
            }
            else
            {
                long n = S[i] - '0' - 1, pLen = pattern.size(), totalLen = n * pLen;
                if (K <= totalLen)return string(1, (pattern[(K - 1) % pLen]));
                K -= totalLen;
                string buff = pattern;
                while (n--)pattern += buff;
            }
        }
        return "";
    }


LeetCode 439 - Ternary Expression Parser


Related: Pocket Gems - Ternary Expression to Binary Tree
http://bookshadow.com/weblog/2016/10/23/leetcode-ternary-expression-parser/
Given a string representing arbitrarily nested ternary expressions, calculate the result of the expression. You can always assume that the given expression is valid and only consists of digits 0-9, ?, :, T and F (T and F represent True and False respectively).
Note:
  1. The length of the given string is ≤ 10000.
  2. Each number will contain only one digit.
  3. The conditional expressions group right-to-left (as usual in most languages).
  4. The condition will always be either T or F. That is, the condition will never be a digit.
  5. The result of the expression will always evaluate to either a digit 0-9, T or F.
Example 1:
Input: "T?2:3"

Output: "2"

Explanation: If true, then result is 2; otherwise result is 3.
Example 2:
Input: "F?1:T?4:5"

Output: "4"

Explanation: The conditional expressions group right-to-left. Using parenthesis, it is read/evaluated as:

             "(F ? 1 : (T ? 4 : 5))"                   "(F ? 1 : (T ? 4 : 5))"
          -> "(F ? 1 : 4)"                 or       -> "(T ? 4 : 5)"
          -> "4"                                    -> "4"
Example 3:
Input: "T?T?F:5:3"

Output: "F"

Explanation: The conditional expressions group right-to-left. Using parenthesis, it is read/evaluated as:

             "(T ? (T ? F : 5) : 3)"                   "(T ? (T ? F : 5) : 3)"
          -> "(T ? F : 3)"                 or       -> "(T ? F : 5)"
          -> "F"                                    -> "F"
X.https://www.cnblogs.com/grandyang/p/6022498.html
这道题让我们解析一个三元表达式,我们通过分析题目中的例子可以知道,如果有多个三元表达式嵌套的情况出现,那么我们的做法是从右边开始找到第一个问号,然后先处理这个三元表达式,然后再一步一步向左推,这也符合程序是从右向左执行的特点。那么我最先想到的方法是用用一个stack来记录所有问号的位置,然后根据此问号的位置,取出当前的三元表达式,调用一个eval函数来分析得到结果,能这样做的原因是题目中限定了三元表达式每一部分只有一个字符,而且需要分析的三元表达式是合法的,然后我们把分析后的结果和前后两段拼接成一个新的字符串,继续处理之前一个问号,这样当所有问号处理完成后,所剩的一个字符就是答案
    string parseTernary(string expression) {
        string res = expression;
        stack<int> s;
        for (int i = 0; i < expression.size(); ++i) {
            if (expression[i] == '?') s.push(i);
        }
        while (!s.empty()) {
            int t = s.top(); s.pop();
            res = res.substr(0, t - 1) + eval(res.substr(t - 1, 5)) + res.substr(t + 4);
        }
        return res;
    }
    string eval(string str) {
        if (str.size() != 5) return "";
        return str[0] == 'T' ? str.substr(2, 1) : str.substr(4);
    }


下面这种方法也是利用栈stack的思想,但是不同之处在于不是存问号的位置,而是存所有的字符,将原数组从后往前遍历,将遍历到的字符都压入栈中,我们检测如果栈首元素是问号,说明我们当前遍历到的字符是T或F,然后我们移除问号,再取出第一部分,再移除冒号,再取出第二部分,我们根据当前字符来判断是放哪一部分进栈,这样遍历完成后,所有问号都处理完了,剩下的栈顶元素即为所求:


http://www.chongchonggou.com/g_609521024.html
  1. 用stack来做,对string从右往左遍历:遇到?,则根据?前的T/F从stack顶上两个数选一个保留;遇到数字或者F/T,直接push;遇到:不用操作!
  2. 为什么从右往左遍历string?因为对每个“?”,选取“?”右边的两个数中的一个,而每个数又可以包含”?”。考虑string是嵌套的,因此需要先得到?右边的两个数的值,再根据?从两个数中选一个,所以需要对string从右往左遍历!更简单的说法:同样是?,位于左边的?优先级低,需要后处理;位于右边的?优先级高,需要先处理。即:表面看都是问号,但位置不同,优先级不同,这是所有嵌套类问题的通解!
https://segmentfault.com/a/1190000008939830
从右往左看,? 作为决定最小单位的符号,每次遇到一个?, 就拆解离?最近的两个小单位。宏观上看是,从小到大。
    public String parseTernary(String expression) {
        if(expression == null || expression.length() == 0) return "";
        Deque<Character> stk = new LinkedList<>();
        
        for(int i=expression.length()-1; i >= 0; i--){
            char c = expression.charAt(i);
            if(!stk.isEmpty() && stk.peek() == '?'){
                stk.pop();  // pop ?
                char first = stk.pop();
                stk.pop(); // pop :
                char second = stk.pop();
                
                if(c == 'T') stk.push(first);
                else stk.push(second);
            } else {
                stk.push(c);
            }
        }
        
        return String.valueOf(stk.peek());
    }
https://discuss.leetcode.com/topic/64409/very-easy-1-pass-stack-solution-in-java-no-string-concat
Iterate the expression from tail, whenever encounter a character before '?', calculate the right value and push back to stack.
P.S. this code is guaranteed only if "the given expression is valid" base on the requirement.
public String parseTernary(String expression) {
    if (expression == null || expression.length() == 0) return "";
    Deque<Character> stack = new LinkedList<>();

    for (int i = expression.length() - 1; i >= 0; i--) {
        char c = expression.charAt(i);
        if (!stack.isEmpty() && stack.peek() == '?') {

            stack.pop(); //pop '?'
            char first = stack.pop();
            stack.pop(); //pop ':'
            char second = stack.pop();

            if (c == 'T') stack.push(first);
            else stack.push(second);
        } else {
            stack.push(c);
        }
    }

    return String.valueOf(stack.peek());
}
https://discuss.leetcode.com/topic/64512/java-short-clean-code-no-stack

https://discuss.leetcode.com/topic/64524/short-python-solutions-one-o-n
栈(Stack)数据结构
循环直到栈中元素为1并且表达式非空:
取栈顶的5个元素,判断是否为一个可以解析的表达式。若是,则解析后压栈
否则从右向左将expression中的字符压入栈stack
Collect chars from back to front on a stack, evaluate ternary sub-expressions as soon as possible:
def parseTernary(self, expression):
    stack = []
    for c in reversed(expression):
        stack.append(c)
        if stack[-2:-1] == ['?']:
            stack[-5:] = stack[-3 if stack[-1] == 'T' else -5]
    return stack[0]
Originally my check was stack[-4::2] == [':', '?'], but @YJL1228's is right, looking for ? is enough.
https://discuss.leetcode.com/topic/64389/easy-and-concise-5-lines-python-java-solution
The time complexity seems very high(may be O(n^2)). Using lastIndexOf means that u need to scan the whole String each loop, which costs a lot of time.
    public String parseTernary(String expression) {
        while (expression.length() != 1) {
            int i = expression.lastIndexOf("?");    // get the last shown '?'
            char tmp;
            if (expression.charAt(i-1) == 'T') { tmp = expression.charAt(i+1); }
            else { tmp = expression.charAt(i+3); }
            expression = expression.substring(0, i-1) + tmp + expression.substring(i+4);
        }
        return expression;
    }

X. Recursion
https://github.com/maiquynhtruong/Leetcode/blob/master/ternary-expression-parser.java
 public static String parseTernary(String expression) {
  if (expression.length() < 2) {
   return expression;
  } else {
   String[] strs = expression.substring(2).split(":");
   if (expression.charAt(0) == 'T') {
    return parseTernary(strs[0]);
   } else {
    return parseTernary(strs[1]);
   }
  }
 }
 
 public static String parseTernary(String expression) {
  if (expression == null || expression.length() == 0) {
   return expression;
  }
  Stack<Character> s = new Stack<Character>();
  for (int i = expression.length() - 1; i >= 0; i--) {
   char c = expression.charAt(i);
   if (!s.empty() && s.peek() == '?') {
    s.pop(); // remove '?'
    char first = s.pop();
    s.pop(); // remove ':'
    char second = s.pop();
    if (c == 'T') {
     s.push(first);
    } else {
     s.push(second);
    }
   } else {
    s.push(c);
   }
  }
  return String.valueOf(s.peek());
 }

https://medium.com/@honda.wei/leetcode-破關之路-439-ternary-expression-parser-上鎖題-a34fae94156
  1. 用遞迴。方式和上面相反,從字串前端開始遍歷字串。此時可把問號(?)和分號(:)看作一個組合,若問號和分號的數量一樣,就處理這個組合。此時可從該字串的第一個字來確認是T還是F,如果是T,則抓取第2個字元到分號之間的子字串,也就是分號左邊,來往下遞迴。如果是F,則抓取分號右邊的子字串,來往下遞迴。在遍歷的過程中,在處理此段邏輯時,因為時機點是問號和分號的數量一樣,所以此時索引的值會停留在分號這個位置。
細部處理
  1. 在用遞迴時,要注意的是判斷問號和分號的數量一樣時,接下來的處理要在確認當前是分號的情況下才能作,也就是
for (int i = 0; i < expression.length(); i++) {
            if (exp.charAt(i) == '?')
                questionMarkCnt++;
            else if (exp.charAt(i) == ':') {
                colonCnt++;
            
                if (questionMarkCnt == colonCnt) {
                    if ('T' == exp.charAt(0)) {
                    // left side
                        return parseTernary(exp.substring(2,i));
                    }
                    else {
                        return parseTernary(exp.substring(i+1));
                    }
                }
                
            } 
  
        }
若寫成下面,則表示有可能是在索引值為為問號時進行處理(下面的程式碼會出錯)
for (int i = 0; i < expression.length(); i++) {
            if (exp.charAt(i) == '?')
                questionMarkCnt++;
            else if (exp.charAt(i) == ':') {
                colonCnt++;
             }            
             
             if (questionMarkCnt == colonCnt) {
               if ('T' == exp.charAt(0)) {
                    // left side
                    return parseTernary(exp.substring(2,i));
               }
               else {
                    return parseTernary(exp.substring(i+1));
               }
             }
https://blog.csdn.net/zqh_1991/article/details/52901605
    string parseTernary(string expression) {
        int len=expression.size();
        if(len==1) return expression;
        int count1=0,count2=0;
        for(int i=0;i<len;i++) {
            if(expression[i]=='?') {
                count1++;
            }
            else if(expression[i]==':') {
                count2++;
                if(count1==count2) {
                    if(expression[0]=='T') {
                        return parseTernary(expression.substr(2,i-2));  //表达式的左边
                    }
                    else return parseTernary(expression.substr(i+1));   //表达式的右边
                }
            }
        }
        return "";
    }

? : 所组成的最小单位,可以看作一对括号。 ?类似(, :类似 )。
从左往右看,:作为决定一组完整最小单位的符号。每次找到一对就可以按:分为左右两个子问题递归解决。
宏观上看是从大到小拆开,从小到大递归回去。
https://discuss.leetcode.com/topic/68336/5ms-java-dfs-solution
https://yijiajin.github.io/leetcode/2017/01/11/LC439.-Ternary-Expression-Parser/
The key idea is to find the legitimate : separating two "values".
This : has the property that the number of ? ahead of this : should equals the number of :, similar to the case of ( and ).
Only problem is the time complexity is up to O(n^2) in the worse case.
For example, T?T?T?T?T?1:2:3:4:5:6.
    public String parseTernary(String expression) {
        if(expression == null || expression.length() == 0){
            return expression;
        }
        char[] exp = expression.toCharArray();
        
        return DFS(exp, 0, exp.length - 1) + "";
        
    }
    public char DFS(char[] c, int start, int end){
        if(start == end){
            return c[start];
        }
        int count = 0, i =start;
        for(; i <= end; i++){
            if(c[i] == '?'){
                count ++;
            }else if (c[i] == ':'){
                count --;
                if(count == 0){
                    break;
                }
            }
        }
        return c[start] == 'T'? DFS(c, start + 2, i - 1) : DFS(c, i+1,end);
    }
https://discuss.leetcode.com/topic/64389/easy-and-concise-5-lines-python-java-solution
To avoid use lastIndexOf, we can easily scan through whole string at first. I've added modified version below, however it costs extra 3 lines.
    def parseTernary(self, expression):
        # begin with the last question.
        idx = []
        for i in xrange(len(expression)):
            if expression[i] == "?": idx += i,
        while len(expression) != 1:
            j = idx.pop()
            tmp = expression[j+1] if expression[j-1] == 'T' else expression[j+3]
            expression = expression[:j-1] + tmp + expression[j+4:]

        return expression
http://hongzheng.me/leetcode/leetcode-439-ternary-expression-parser/
一个公式由3部分组成 <bool>?<left>:<right>, bool值只能为T或F, left或right可以为子公式或是单一的值. 所以只要能够正确的划分这三个部分, 就能用递归来处理.
这里我们发现?和:是成对出现的, 用一个flag来计数, 遇到?加1, 遇到:减一, 当flag == 0的时候, 说明正好为left和right的分界.
http://www.voidcn.com/blog/zqh_1991/article/p-6244665.html
    string parseTernary(string expression) {
        int len=expression.size();
        if(len==1) return expression;
        int count1=0,count2=0;
        for(int i=0;i<len;i++) {
            if(expression[i]=='?') {
                count1++;
            }
            else if(expression[i]==':') {
                count2++;
                if(count1==count2) {
                    if(expression[0]=='T') {
                        return parseTernary(expression.substr(2,i-2));  //表达式的左边
                    }
                    else return parseTernary(expression.substr(i+1));   //表达式的右边
                }
            }
        }
        return "";
    }

X. Build express tree
https://scottduan.gitbooks.io/leetcode-review/ternary_expression_parser.html
Let's assume the input ternary expression is valid, we can build the tree in preorder manner.
Each time we scan two characters, the first character is either ? or :, the second character holds the value of the tree node. When we see ?, we add the new node to left. When we see :, we need to find out the ancestor node that doesn't have a right node, and make the new node as its right child.
public TreeNode convert(char[] expr) {
  if (expr.length == 0) {
    return null;
  }

  TreeNode root = new TreeNode(expr[0]);

  Stack<TreeNode> stack = new Stack<>();

  for (int i = 1; i < expr.length; i += 2) {
    TreeNode node = new TreeNode(expr[i + 1]);

    if (expr[i] == '?') {
      stack.peek().left = node;
    }

    if (expr[i] == ':') {
      stack.pop();
      while (stack.peek().right != null) {
        stack.pop();
      }
      stack.peek().right = node;
    }

    stack.push(node);
  }

  return root;
}
https://discuss.leetcode.com/topic/64397/java-o-n-using-binary-tree
    public String parseTernary(String expression) {
        if(expression == null || expression.length() == 0) return "";
        Node root = buildTree(expression.toCharArray());
        return evaluate(root) + "";
    }
    static class Node {
        char val;
        Node left;
        Node right;
        Node parent;
        
        public Node(char c) {
            val = c;
            left = null;
            right = null;
            parent = null;
        }
    }
    private static Node buildTree(char[] ch) {
        Node root = new Node(ch[0]);
        Node node = root;
        for(int i = 1; i < ch.length; i++) {
            if(ch[i] == '?') {
                Node left = new Node(ch[i + 1]);
                node.left = left;
                left.parent = node;
                node = node.left;
            }
            else if(ch[i] == ':') {
                node = node.parent;
                while(node.right != null && node.parent != null) {
                    node = node.parent;
                }
                Node right = new Node(ch[i + 1]);
                node.right = right;
                right.parent = node;
                node = node.right;
            }
        }
        return root;
    }
    private static char evaluate(Node root) {
        while(root.val == 'T' || root.val == 'F') {
            if(root.left == null && root.right == null) break;
            if(root.val == 'T') root = root.left;
            else root = root.right;
        }
        return root.val;
    }

Only problem is the time complexity is up to O(n^2) in the worse case.
For example, T?T?T?T?T?1:2:3:4:5:6.

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