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); } } }
282 Expression Add Operators
猜你喜欢
转载自www.cnblogs.com/tobeabetterpig/p/9455046.html
今日推荐
周排行