282 Expression Add Operators

282 Expression Add Operators 


简单版写一下
https://www.youtube.com/watch?v=v05R1OIIg08&t=332s

https://github.com/tongzhang1994/Facebook-Interview-Coding/blob/master/282.%20Expression%20Add%20Operators.java

=======================================
Original version: 


Time complexity: n^ 2 *  4 ^ n
N is the number of elements in the string 
There are n levels in the dfs graph. There are 4 options each time. (In the dfs graph, there are three , because we put the prefix out on the side), it actually have four cases each time. So 4 ^ n . 

For each number, we did operation like     sb.append("-").append(cur).   And.    num.substring(start, i + 1)) 
We did n append for each result. we need to get substring , this depends on the size of the substring , which is n in the worst case 
So n^ 2 

So time complexity in total is n ^ 2 * 4 ^ n 

Space complexity is o(n), because we used only one string builder pass down and up in the dfs graph. 
The length of the string is n. 



class Solution {
    public List<String> addOperators(String num, int target) {
      List<String> result = new ArrayList<>();
      StringBuilder sb = new StringBuilder();
      dfs(result, sb, num, target, 0, 0, 0);
      return result;
    }
    
    private void dfs(List<String> result, StringBuilder sb, String num, 
                     int target, int start, long eval, long prev){
      // stopping condition
      if(start == num.length()){
        if(eval == target){
          result.add(sb.toString());
        }
        return; // return whether this is a success combination or not
        // otherwise will stay in this loop forever
  
      }
      
      // else keep doing dfs 
      // handle prefix different cases 
      for(int i = start; i < num.length(); i++){
        // before we have valid prefix, check if it can be valid 
        // if the first char is 0, the only case that it can be valid 
        // is when its one single 0, cases like 01, 0123, are not valid
        // one single 0 when i = start 
        if(num.charAt(start) == '0' && i != start){     // num.charAt(start) == '0', not "0", char ' ' , String " "
          break;
        }
        // else its valid 
        int len = sb.length();
        long cur = Long.valueOf(num.substring(start, i + 1)); // why use long?  Long.valueOf 
        
        // if its the first time, we don't +-x the first time 
        if(start == 0){
          dfs(result, sb.append(cur), num, target, i + 1, eval + cur, cur);
          sb.setLength(len);
        }else{
          // if its not the first time, means have a path started already
          // + 
          dfs(result, sb.append("+").append(cur), num, target, i + 1, eval + cur, cur);
          // length recovery for -
          sb.setLength(len);
          // -
          dfs(result, sb.append("-").append(cur), num, target, i + 1, eval - cur, -cur);
          sb.setLength(len);
          // *
          dfs(result, sb.append("*").append(cur), num, target, i + 1, eval - prev + prev * cur, prev * cur);
          // we dont need to do backtracking here because 
          sb.setLength(len);
        }
        //sb.setLength(len);
      }
          
        
    }
}
   







// in the example if the string given is "123" 

                    prefix = ' 1 '                         prefix = '12'                           
                  +     -    *    ()                    +     -    *    ()
                  2     2    2    2                   3      3    3      3
              +-*()  ....  ....   ....
              3333   3333. 3333   3333
                          
                      
// there are two sb.setLength(len)
// the innner one is backtracking recovery from "1 + 2" back to len = 1, so it's "1" , and then it can go to " 1 - 2" 
// the outer one is backtracking recovery from prefix "1" to len = 0, which is empty string, and then go to preifx"12"
                      
// another example for the prefix backtracking 
// say the given string is "123456". and we are on the path of "1 + 2 - 3"
// now we can have prefix "4", "45", "456". before we add any prefix(which is cur in the code above), we keep the length of 
// of the sb, before adding any prefix, so the len is 5 right now. 
                
           case(1)
           " 1 + 2 - 3"          
              
            +  -  *  ()
          
            4  4  4   4 
      
                      
                      
           case(2)           
                      
          " 1 + 2 - 3"          
              
          +   -    *   ()
          
          45  45  45   45  
                      
                      
// suppose we are done with case(1), we want to go to case (2), how do we do it? 
// answer: before we start to append operators and  4 in the first case, we keep the len of sb, which is 5 , and then we append the operators and 4. after we are done with case 1, we can move on to case 2, since the len of sb changed already, we do recovery back to " 1 + 2 - 3" using   sb.setLength(len), the outer one, because the for loop is when we have differnt options, like "4", "45", "456". 
 
// if (nums.charAt(start) == '0' && i != start)    break;
// for example : we have the string as "1230456"
// say we are on the path of "1 + 2 - 3" and now we are facing options : "0", "04", "045", "0456"
// since "04", "045", "0456" are not valid numbers, we can only take "0", which i = start. 
                      
                      
 // () means concatenate , example: 2()3 = 23                      
                      
                      
                      
12345 
                         
level1                                     1                                  12            123         1234        12345 
                            /          /      \         \
                           +-x       +-x      +-x       +-x 
level2                     2         23       234       2345
          /        /         |              /  \
         +-x     +-x    +-x       +-x    +-x 
level3   3       34     345       4       45
                      
                      
// a question: why in the code, we dont have ()?  
// suppose we have concatenate operation() explicitly for every number , then 1()2 = 12, which we have at level 1
// 1()23 = 123, which we also have in the level 1
// 1 + 2()3 = 123, which we have at the level 1
// 1 * 23()4 = 1 * 234, which we have at level 2 
                      



example : outer sb.setLength(len); 


from:
       1
      +-x
       2
         
         
         
transition: 

   1       len(1) = 1  outer sb.setLength(len);           
            

to: 
                      
          1
         +-x
         23
                        
=====================================================================                      
                      
 example : inner sb.setLength(len);                     
                      
from:                       
       1
       +
       2                   
    
         
         
         
transiton:

   1     len(1) = 1     inner  sb.setLength(len); 
          


to:

        1
        -
        2                   
                           






Example that why we don’t have inner sb.setLength(len) after * 

      
      2 
        
+-x    +-x
3      34
        
after we are done from  2 
                       x
                        3
        
we want to go to     2 
                    +-x
                    34
        
the reason that we dont need to have the inner sb.setLength(len) after 2 * 3 
        
is that we have outer sb.setLength(len), which
takes us from        to                the transition is 2 
                 2           2
                +-x         +-x
                3            34
        

==========================================
  sb.setLength(len); for backtracking 
https://www.tutorialspoint.com/java/lang/stringbuffer_setlength.htm
public class StringBufferDemo {
 
   public static void main(String[] args) {
  
      StringBuffer buff = new StringBuffer("tutorials");
      System.out.println("buffer1 = " + buff);  
      
      // length of stringbuffer
      System.out.println("length = " + buff.length());
 
      // set the length of stringbuffer to 5
      buff.setLength(5);

      // print new stringbuffer value after changing length
      System.out.println("buffer2 = " + buff);
      
      // length of stringbuffer after changing length
      System.out.println("length = " + buff.length());
   }
}
Let us compile and run the above program, this will produce the following result −
buffer1 = tutorials
length = 9
buffer2 = tutor
length = 5









You can get substring from the given string object by one of the two methods:
1. public String substring(int startIndex): This method returns new String object containing the substring of the given string from specified startIndex (inclusive).
2. public String substring(int startIndex, int endIndex): This method returns new String object containing the substring of the given string from specified startIndex to endIndex.
In case of string:
* startIndex: inclusive
* endIndex: exclusive
Let's understand the startIndex and endIndex by the code given below.

1. String s="hello";  
2. System.out.println(s.substring(0,2));//he  



简单版
https://github.com/tongzhang1994/Facebook-Interview-Coding/blob/master/282.%20Expression%20Add%20Operators.java

Time o(3^ n) space 
public List<String> allPoss(String num, int target){
    List<String> result = new ArrayList<>();
    String tmp = "";
    dfs(num, target, tmp, result, 0, 0);
    return result;
}

private void dfs(String num, int target, String tmp, List<String> result, int start, int sum){
    if(start == num.length()){
        if(sum == target){
            result.add(tmp);
        }
        return;
    }
    for(int i = start; i < num.length(); i++){
        if(num.charAt(start) == '0' && i != start) break;
        Integer current = Integer.valueOf(num.substring(start, i+1));
        if(start == 0){
            dfs(num, target, tmp + current, result, i+1, sum + current);
        }else{
            dfs(num, target, tmp + "+" + current, result, i+1, sum + current);
            dfs(num, target, tmp + "-" + current, result, i+1, sum - current);
        }

    }
}

猜你喜欢

转载自www.cnblogs.com/tobeabetterpig/p/9455046.html