Equations are given in the format A / B = k, where A and B are variables represented as strings, and k is a real number (floating point number). Given some queries, return the answers. If the answer does not exist, return -1.0.
Example: Given a / b = 2.0, b / c = 3.0. queries are: a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ? . return [6.0, 0.5, -1.0, 1.0, -1.0 ].
Solution1: Union-find
By using union-find method, we could keep the relations. So now first we find out how many distinct variables there are and build a union-find set for each variable. Let each one be there parent and initialize the value as 1.0. Then we update the relation and value by these rules: keep the root value as 1, just update the children’s value. if a/c = 2, then we take a as root, and give c value as 2, so it keep a multiple relation between root and child. when union method work, we point one root to another and change its value to a multiple to the original value, so its the right multiple to root. Every time using find, we then compress its path to save time.
classSolution{ publicdouble[] calcEquation(String[][] equations, double[] values, String[][] queries) { // keep variables distinct HashMap<String, Integer> variables = new HashMap<>(); int len = 0; for (String[] equation: equations) { if (!variables.containsKey(equation[0])) { variables.put(equation[0], len++); } if (!variables.containsKey(equation[1])) { variables.put(equation[1], len++); } } // create the union-find array Node[] nodes = new Node[len]; for (int i = 0; i < nodes.length; ++i) { nodes[i] = new Node(i); } // update the union-find array for (int i = 0; i < equations.length; ++i) { int index0 = variables.get(equations[i][0]); int index1 = variables.get(equations[i][1]); int root0 = find(nodes, index0); int root1 = find(nodes, index1); nodes[root1].parent = root0; nodes[root1].value = nodes[index0].value * values[i] / nodes[index1].value; } // query double[] result = newdouble[queries.length]; for (int i = 0; i < queries.length; ++i) { if (!variables.containsKey(queries[i][0]) || !variables.containsKey(queries[i][1])) { result[i] = -1.0; continue; } int index0 = variables.get(queries[i][0]); int index1 = variables.get(queries[i][1]); int root0 = find(nodes, index0); int root1 = find(nodes, index1); if (root0 != root1) { result[i] = -1.0; continue; } result[i] = nodes[index1].value / nodes[index0].value; } return result; } privateintfind(Node[] nodes, int k){ int p = k; while (nodes[p].parent != p) { p = nodes[p].parent; nodes[k].value *= nodes[p].value; } nodes[k].parent = p; return p; } classNode{ int parent; double value; publicNode(int parent){ this.parent = parent; value = 1.0d; } } }
Solution 2: DFS
By using dfs, we just need to use a visited set and each time if we find the query directly, we return the value. If not, we try to find the first part match, then change the query into a new query, and try to find the new query.
classSolution{ publicdouble[] calcEquation(String[][] equations, double[] values, String[][] queries) { // keep variables distinct HashSet<String> variables = new HashSet<>(); for (String[] equation: equations) { variables.add(equation[0]); variables.add(equation[1]); } double[] result = newdouble[queries.length]; int index = 0; for (String[] query: queries) { if (!variables.contains(query[0]) || !variables.contains(query[1])) { result[index++] = -1.0; continue; } result[index++] = helper(equations, values, query, new HashSet<Integer>()); } return result; } privatedoublehelper(String[][] equations, double[] values, String[] query, HashSet<Integer> visitedEquations){ // directly find query equation for (int i = 0; i < equations.length; ++i) { if (equations[i][0].equals(query[0]) && equations[i][1].equals(query[1])) { return values[i]; } elseif (equations[i][0].equals(query[1]) && equations[i][1].equals(query[0])) { return1.0 / values[i]; } } for (int i = 0; i < equations.length; ++i) { if (visitedEquations.contains(i)) continue; if (equations[i][0].equals(query[0])) { visitedEquations.add(i); double value = values[i] * helper(equations, values, new String[]{equations[i][1], query[1]}, visitedEquations); if (value > 0) { return value; } else { visitedEquations.remove(i); } } if (equations[i][1].equals(query[0])) { visitedEquations.add(i); double value = helper(equations, values, new String[]{equations[i][0], query[1]}, visitedEquations) / values[i]; if (value > 0) { return value; } else { visitedEquations.remove(i); } } } return -1.0; } }
Split Array Largest Sum(LeetCode 410)
Given an array which consists of non-negative integers and an integer m, you can split the array into mnon-empty continuous subarrays. Write an algorithm to minimize the largest sum among these msubarrays.
Note: If n is the length of array, assume the following constraints are satisfied:
1 ≤ n ≤ 1000
1 ≤ m ≤ min(50, n)
Examples:
1 2 3 4 5 6 7 8 9 10 11
Input: nums = [7,2,5,10,8] m = 2
Output: 18
Explanation: There are four ways to split nums into two subarrays. The best way is to split it into [7,2,5] and [10,8], where the largest sum among the two subarrays is only 18.
Solution 1: DFS
We create a array visited[len][m] which visited[start][m] means start from index start and split the array into m parts. Its like a memo method which could speed up.
We need to know that there is a max value in nums, and there will be a solution which is >= max, so the answer would be in [max, sum], then we just binary search in this range and check the answer is valid or not. By checking valid, we need to try to split the array into m part which each part is <= value, so when we could split and no elements left, we need to decrease to value, when we could not, it means the value is to small, we need to increase it. Finally we will get the answer.
classSolution{ publicintsplitArray(int[] nums, int m){ if (nums == null || m < 1 || m > nums.length) return -1; int max = -1; long sum = 0; for (int num: nums) { max = max >= num ? max : num; sum += num; } long left = (long)max; long right = sum; while (left <= right) { long mid = (left + right) >>> 1; if (valid(mid, nums, m)) { right = mid - 1; } else { left = mid + 1; } } return (int)left; } privatebooleanvalid(long target, int[] nums, int m){ int count = 1; long sum = 0; for (int num: nums) { sum += num; if (sum > target) { sum = (long)num; ++count; if (count > m) { returnfalse; } } } returntrue; } }
Read N Characters Given Read4(LeetCode 157)
The API: int read4(char *buf) reads 4 characters at a time from a file.
The return value is the actual number of characters read. For example, it returns 3 if there is only 3 characters left in the file.
By using the read4 API, implement the function int read(char *buf, int n) that reads ncharacters from the file.
Note: The read function will only be called once for each test case.
/* The read4 API is defined in the parent class Reader4. int read4(char[] buf); */
publicclassSolutionextendsReader4{ /** * @param buf Destination buffer * @param n Maximum number of characters to read * @return The number of characters read */ publicintread(char[] buf, int n){ char[] buf4 = newchar[4]; int length = 0; int num = 4; while (num == 4 && length < n) { num = read4(buf4); for (int i = length; i < n && i < length + num; ++i) { buf[i] = buf4[i-length]; } length = Math.min(n, length+num); } return length; } }
Read N Characters Given Read4 II - Call multiple times
The API: int read4(char *buf) reads 4 characters at a time from a file.
The return value is the actual number of characters read. For example, it returns 3 if there is only 3 characters left in the file.
By using the read4 API, implement the function int read(char *buf, int n) that reads ncharacters from the file.
Note: The read function may be called multiple times.
Solution
There are two more corner case need to concern about.
File has been read out
file still left but the bug loaded last time and didn’t read.
publicclassSolutionextendsReader4{ /** * @param buf Destination buffer * @param n Maximum number of characters to read * @return The number of characters read */ char[] buff = newchar[4]; int start = 0; int num = 0; publicintread(char[] buf, int n){ int res = 0; while (res < n) { if (start == 0) { num = read4(buff); } if (num == 0) break; while (res < n && start < num) { buf[res++] = buff[start++]; } if (start == num) { start == 0; } } return res; } }
Basic Calculator
Implement a basic calculator to evaluate a simple expression string.
The expression string contains only non-negative integers, +, -, *, / , () operators and empty spaces . The integer division should truncate toward zero.
Example 1:
1 2
Input: "3+2*(2+2)+3" Output: 14
Solution
Based on the calculator with only +-*\, we just add a recursion to solve the parentheses.
classSolution{ publicintcalculate(String s){ int from = s.indexOf("("); int to = s.lastIndexOf(")"); if (from >= 0 && to >= 0) { String sub = s.substring(from+1, to); int value = calculate(sub); s = s.substring(0, from)+value+s.substring(to+1); } ArrayDeque<Integer> numStack = new ArrayDeque<>(); char sign = '+'; int num = 0; for(int i = 0; i < s.length(); i++){ char c = s.charAt(i); if (Character.isDigit(c)){ num = num * 10 + (c - '0'); } if (!Character.isDigit(c) && ' ' != c || i == s.length() - 1){ switch(sign){ case'+': numStack.push(num); break; case'-' : numStack.push(-num); break; case'*': numStack.push(numStack.pop()*num); break; case'/': numStack.push(numStack.pop()/num); break; } num = 0; sign = c; } } int answer = 0; for(int i : numStack){ answer += i; } return answer; } }