Data Structure and Algorithm
Array & ArrayList
1. Move Zeros
双指针
class Solution { public void moveZeroes(int[] nums) { if (nums.length == 0) { return; } int i = 0; int j = 0; int len = nums.length; while (j < len) { while (i < len && nums[i] != 0) { i++; } while (j < len && (j < i || nums[j] == 0)) { j++; } if (i < len && j < len) { swap(nums, i, j); } } } public void swap(int[] nums, int i, int j) { int tmp = nums[i]; nums[i] = nums[j]; nums[j] = tmp; } }
2. Missing Number - Not Bug Free
思路一: HashSet
class Solution { public int missingNumber(int[] nums) { HashSet set = new HashSet(); for (int i : nums) { set.add(i); } for (int i = 0; i < nums.length + 1; i++) { if (!set.contains(i)) { return i; } } return nums.length; } }
思路二: Swap. - Not Bug Free - Bug Free
class Solution { public int missingNumber(int[] nums) { for (int i = 0; i < nums.length; i++) { while (nums[i] != i && nums[i] <= nums.length - 1) { swap(nums, i, nums[i]); } } for (int i = 0; i < nums.length; i++) { if (i != nums[i]) { return i; } } return nums.length; } public void swap(int[] nums, int i, int j) { int tmp = nums[i]; nums[i] = nums[j]; nums[j] = tmp; } }
3. 3Sum Closest - Not Bug Free - Bug Free
坑:将sum写在判断语句之后会引起漏掉。
class Solution { public int threeSumClosest(int[] nums, int target) { Arrays.sort(nums); int sum = nums[0] + nums[1] + nums[2]; for (int i = 0; i < nums.length; i++) { int j = i + 1; int k = nums.length - 1; while (j < k) { int tmp = nums[i] + nums[j] + nums[k]; sum = Math.abs(sum - target) > Math.abs(tmp - target) ? tmp : sum; if (tmp == target) { return tmp; } else if (tmp > target) { k--; } else { j++; } } } return sum; } }
4. Max Consecutive Ones - Not Bug Free - Not Bug Free
坑:注意好循环之后i, j的所在位置. 注意max的计算之后 i 的值要变化.
class Solution { public int findMaxConsecutiveOnes(int[] nums) { int max = 0; int i = 0; int j = 0; while (j < nums.length) { while (i < nums.length && (i < j || nums[i] != 1)) { i++; } while (j < nums.length && (j < i || nums[j] == 1)) { j++; } max = max > (j - i) ? max : (j - i); } return max; } }
5. Rotate Array - Not Bug Free - Bug Free
坑: index从0开始,第一个reverse是(0, K-1).
class Solution { public void rotate(int[] nums, int k) { if (nums.length == 0) { return; } k = k%nums.length; reverse(nums, 0, nums.length - 1); reverse(nums, 0, k - 1); reverse(nums, k, nums.length - 1); } public void reverse(int[] nums, int i, int j) { while (i < j) { int tmp = nums[i]; nums[i] = nums[j]; nums[j] = tmp; i++; j--; } } }
6. First Missing Positive - Not Bug Free - Very Important - Not Bug Free
坑: 注意index可能 < 0.
class Solution { public int firstMissingPositive(int[] nums) { for (int i = 0; i < nums.length; i++) { while (nums[i] != i + 1 && nums[i] > 0 && nums[i] <= nums.length && nums[i] != nums[nums[i] - 1]) { swap(nums, i, nums[i] - 1); } } for (int i = 0; i < nums.length; i++) { if (nums[i] != i + 1) { return i + 1; } } return nums.length + 1; } public void swap(int[] nums, int i, int j) { int tmp = nums[i]; nums[i] = nums[j]; nums[j] = tmp; } }
7. Majority Element
class Solution { public int majorityElement(int[] nums) { Arrays.sort(nums); return nums[nums.length/2]; } }
8. Merge Sorted Array
class Solution { public void merge(int[] nums1, int m, int[] nums2, int n) { int[] tmp = new int[m+n]; int i = 0; int j = 0; int k = 0; while (j < m && k < n) { tmp[i++] = nums1[j] < nums2[k] ? nums1[j++] : nums2[k++]; } while (j < m) { tmp[i++] = nums1[j++]; } while (k < n) { tmp[i++] = nums2[k++]; } System.out.println(Arrays.toString(tmp)); } }
9. Largest Number At Least Twice of Others - Not Bug Free - Not Bug Free
心得1:比较元素时将[0]作为基准,从[1]开始比较. 认真分析判断条件.
心得2:比较元素时将[0]作为基准,从[1]开始比较. 认真分析判断条件.
class Solution { public int dominantIndex(int[] nums) { if (nums.length == 0) { return -1; } int max = nums[0]; int index = 0; for (int i = 1; i < nums.length; i++) { if (nums[i] >= 2 * max) { max = nums[i]; index = i; } else if (max < 2 * nums[i]){ index = -1; if (max < nums[i]) { max = nums[i]; } } } return index; } }
10. Max Chunks To Make Sorted ( I & II) - Not Bug Free - Not Bug Free
思路:if max(arr[ : A-1]) <= min(arr[A-1 : ]), then we can split it into two chunks.
class Solution { public int maxChunksToSorted(int[] arr) { int[] max = new int[arr.length]; int[] min = new int[arr.length]; max[0] = arr[0]; min[arr.length - 1] = arr[arr.length - 1]; for (int i = 1; i < arr.length; i++) { max[i] = Math.max(arr[i], max[i-1]); } for (int i = arr.length - 2; i >= 0; i--) { min[i] = Math.min(arr[i], min[i+1]); } int ans = 0; for (int i = 0; i < arr.length - 1; i++) { if (max[i] <= min[i+1]) { ans++; } } return ans + 1; } }
11. remove Element - Not Bug Free - Not Bug Free
Pitfall: Template for two-pointer; Be careful when calculating length.
Pitfall: There are two ways of calculating length. One is by using "i" and the other is to use (nums.length - (j - i)).
class Solution { public int removeElement(int[] nums, int elem) { int i = 0; int j = 0; while (j < nums.length) { while (i < nums.length && nums[i] != elem) { i++; } while (j < nums.length && (j < i || nums[j] == elem)) { j++; } if (i < nums.length && j < nums.length) { swap(nums, i, j); } } // OR return nums.length - (j - i); return i; } public void swap(int[] nums, int i, int j) { int tmp = nums[i]; nums[i] = nums[j]; nums[j] = tmp; } }
12. Subarray Sum - Not Bug Free - Not Bug Free
坑:edge cases,想清楚逻辑.
坑:subarray的两个Index 可以相同. 当 nums[i] == 0 时直接返回.
public class Solution { public List<Integer> subarraySum(int[] nums) { // write your code here List<Integer> ans = new ArrayList<>(); for (int i = 0; i < nums.length; i++) { int sum = nums[i]; if (sum == 0) { ans.add(i); ans.add(i); return ans; } for (int j = i + 1; j < nums.length; j++) { sum += nums[j]; if (sum == 0) { ans.add(i); ans.add(j); return ans; } } } return ans; } }
13. Remove Duplicates from Sorted Array - Not Bug Free - Not Bug Free
思路:当不在乎后面数的时候可以不用swap,而是直接后面的值赋给前面。本质是双指针,先找到一个值,然后再找下一个与其值不等的值,再赋值。
坑:双指针;在纸上画出逻辑;加上comment.
public class Solution { public int removeDuplicates(int[] nums) { // TODO: len == 0 if (nums.length == 0) { return 0; } if (nums.length == 1) { return 1; } int i = 1; int j = 1; int cnt = 1; while (j < nums.length) { if (nums[j] == nums[j-1]) { j++; } else { cnt = 1; nums[i++] = nums[j++]; } } return i; } }
14. Product of Array Except Self - Not Bug Free - Bug Free
思路:分左右两端乘积. 先计算左边乘积,再计算右边乘积
class Solution { public int[] productExceptSelf(int[] nums) { int[] ans = new int[nums.length]; int tmp = 1; for (int i = 0; i < nums.length; i++) { ans[i] = tmp; tmp *= nums[i]; } tmp = 1; for (int i = nums.length - 1; i >= 0; i--) { ans[i] *= tmp; tmp *= nums[i]; } return ans; } }
15. 3Sum - Not Bug Free - Bug Free
思路:2 sum的思路,很多细节要注意。尝试想几个test case,分析他们,然后再代码。
class Solution { public List<List<Integer>> threeSum(int[] nums) { List<List<Integer>> results = new ArrayList<>(); if (nums.length < 3) { return results; } Arrays.sort(nums); int sum = nums[0] + nums[1] + nums[2]; for (int i = 0; i < nums.length - 2; i++) { // skip duplicates if (i > 0 && nums[i] == nums[i-1]) { continue; } int j = i + 1; int k = nums.length - 1; while (j < k) { sum = nums[i] + nums[j] + nums[k]; if (sum == 0) { // j++ and k-- is to prevent infinite loop results.add(Arrays.asList(nums[i], nums[j++], nums[k--])); // skip duplicates [j] == [j-1] because of [j++] in the above step while (j < k && nums[j] == nums[j-1]) { j++; } // skip duplicates [k] == [k+1] because of [k--] in the above step while (j < k && nums[k] == nums[k+1]) { k--; } } else if (sum > 0) { k--; } else { j++; } } } return results; } }
16. 4Sum - Not Bug Free - Bug Free
思路:如何跳过重复值,sum在何处计算。
public class Solution { public List<List<Integer>> fourSum(int[] nums, int target) { Arrays.sort(nums); List<List<Integer>> ans = new ArrayList<>(); for (int i = 0; i < nums.length - 3; i++) { if (i > 0 && nums[i] == nums[i-1]) { continue; } for (int j = i+1; j < nums.length -2; j++) { if (j > i+1 && nums[j] == nums[j-1]) { continue; } int m = j + 1; int k = nums.length - 1; while (m < k) { int sum = nums[i] + nums[j] + nums[m] + nums[k]; if (sum == target) { ans.add(Arrays.asList(nums[i], nums[j], nums[m++], nums[k--])); while (m < k && nums[m] == nums[m-1]) { m++; } while (m < k && nums[k] == nums[k+1]) { k--; } } else if (sum < target) { m++; } else { k--; } } } } return ans; } }
17. Remove Duplicates from Sorted Array II - Not Bug Free - Not Bug Free
思路:初始化count = 1, 一旦后一个和前一个不相等,count 又变为 = 1.
判断nums[i] == nums[i+1] 没有 nums[i] == nums[i-1] 好,前者容易漏掉元素。
坑:第一个循环里一点你给要写成nums[i++] = nums[j++]. 因为当cnt再次等于1时,单纯的i++, j++不会将后面的值重新付给前面了
class Solution { public int removeDuplicates(int[] nums) { // TODO len = 0 if (nums.length == 0) { return 0; } int cnt = 1; int i = 1; int j = 1; while (j < nums.length) { if (nums[j] == nums[j-1]) { if (cnt < 2) { cnt++; nums[i++] = nums[j++]; } else { j++; } } else { cnt = 1; nums[i++] = nums[j++]; } } return i; } }
18. Minimum Size Subarray Sum - Not Bug Free - Not Bug Free
思路:双指针。
坑:计算长度时,j会等于len,然后循环就终止了,所以这个不行!!!
public class Solution { public int minimumSize(int[] nums, int s) { // write your code here int i = 0; int j = 0; int sum = 0; int min = Integer.MAX_VALUE; while (j < nums.length) { /* 计算长度时,j会等于len,然后循环就终止了,所以这个不行!!! if (sum < s) { sum += nums[j++]; } else { if (j >= i) { min = Math.min(min, j-i); sum -= nums[i++]; } } */ sum += nums[j++]; while (sum >= s && i <= j) { min = Math.min(min, j-i); sum -= nums[i++]; } } return min == Integer.MAX_VALUE ? -1 : min; } }
19. Subarray Sum Closest - Not Bug Free - New
思路:本质是prefixSum(m) - prefixSum(n)的最小值. prefixSum排序,计算哪组prefixSum(i+1) - prefixSum(i)最小. 返回 (lower+1, upper).
20. Fruit Into Baskets - 1st Not Bug Free
思路:双指针
坑:注意while loop后面的index要适当变化。firstIdx, firstValue, lastIdx, lastValue.
1 class Solution { 2 public int totalFruit(int[] tree) { 3 if (tree == null) { 4 return 0; 5 } 6 if (tree.length <= 2) { 7 return tree.length; 8 } 9 int i = 0; 10 int j = 0; 11 int max = 0; 12 while (i < tree.length && j < tree.length) { 13 while (j < tree.length && (j < i || tree[i] == tree[j])) { 14 j++; 15 } 16 int first = tree[i]; 17 int firstIdx = i; 18 int second = 0; 19 if (j < tree.length) { 20 second = tree[j]; 21 while (j < tree.length && j >= 0 && (tree[j] == second || tree[j] == first)) { 22 j++; 23 } 24 } 25 int lastIdx = j - 1; 26 int lastValue = tree[lastIdx]; 27 max = Math.max(j - firstIdx, max); 28 if (tree[lastIdx] == lastValue) { 29 while (lastIdx < tree.length && lastIdx >= 0 && tree[lastIdx] == lastValue) { 30 lastIdx--; 31 } 32 lastIdx++; 33 } 34 i = lastIdx; 35 } 36 return max; 37 } 38 }
String
1. Repeated string match - Not Bug Free - Bug Free
坑:Substring长度最多为bLength/aLength + 1; indexOf的应用.
class Solution { public int repeatedStringMatch(String A, String B) { int aLength = A.length(); int bLength = B.length(); if (aLength == 0 && bLength == 0) { return 1; } if (aLength == 0 || bLength == 0) { return -1; } int times = 1; if (aLength > bLength) { while (times <= 2) { String str = makeString(A, times); if (isSubstring(str, B)) { return times; } times++; } return -1; } times = bLength/aLength; while (times <= bLength/aLength + 1) { String str = makeString(A, times); if (isSubstring(str, B)) { return times; } times++; } return -1; } public boolean isSubstring(String A, String B) { for (int i = 0; i <= A.length() - B.length(); i++) { if (A.substring(i, i + B.length()).equals(B)) { return true; } } return false; } public String makeString(String A, int times) { String str = ""; while (times-- != 0) { str += A; } return str; } }
class Solution { public int repeatedStringMatch(String A, String B) { int aLength = A.length(); int bLength = B.length(); StringBuilder str = new StringBuilder(); int nums = 0; while (str.indexOf(B) < 0) { if (str.length() > aLength + bLength) { return -1; } str.append(A); nums++; } return nums; } }
2. Repeated Substring Pattern - Not Bug Free - Not Bug Free
坑:Substring的长度最多为原String的1/2; 长度取余必须为0; 一部分一部分比较.
坑:关于str.length() 的loop最大值可以到str.length(); while loop有continue语句很危险,要记得用for loop.
class Solution { public boolean repeatedSubstringPattern(String s) { if (s == "") { return true; } for (int i = 1; i <= s.length()/2; i++) { String subStr = s.substring(0, i); if (s.length()%subStr.length() != 0) { continue; } for (int j = i; j <= s.length() - subStr.length(); j += subStr.length()) { if (!subStr.equals(s.substring(j, j+subStr.length()))) { break; } if (j == s.length() - subStr.length()) { return true; } } } return false; } }
public boolean repeatedSubstringPattern(String str) { int l = str.length(); for(int i=l/2;i>=1;i--) { if(l%i==0) { int m = l/i; String subS = str.substring(0,i); StringBuilder sb = new StringBuilder(); for(int j=0;j<m;j++) { sb.append(subS); } if(sb.toString().equals(str)) return true; } } return false; }
public boolean repeatedSubstringPattern(String str) { String s = str + str; return s.substring(1, s.length() - 1).contains(str); }
3. Valid Parentheses - Bug Free
class Solution { public boolean isValid(String str) { Stack<Character> s = new Stack<>(); int i = 0; while (i < str.length()) { switch (str.charAt(i++)) { case '(': s.push('('); break; case '{': s.push('{'); break; case '[': s.push('['); break; case ')': if (s.empty() || !s.pop().equals('(')) { return false; } break; case '}': if (s.empty() || !s.pop().equals('{')) { return false; } break; case ']': if (s.empty() || !s.pop().equals('[')) { return false; } break; default: break; } } return s.empty(); } }
4. Reverse String - Not Bug Free
坑: 注意while的i--.
class Solution { public String reverseString(String s) { int len = s.length(); char[] arr = new char[len]; int i = len - 1; while (i >= 0) { arr[len - 1 - i] = s.charAt(i); i--; } return new String(arr); } }
还可以利用string里的char交换.
public class Solution { public String reverseString(String s) { char[] arr = s.toCharArray(); int len = arr.length; for (int i = 0; i < len/2; i++) { char tmp = arr[i]; arr[i] = arr[len - 1 - i]; arr[len - 1 - i] = tmp; } return new String(arr); } }
5. Implement strStr()
class Solution { public int strStr(String haystack, String needle) { if (needle.length() == 0) { return 0; } for (int i = 0; i < haystack.length(); i++) { if (haystack.charAt(i) == needle.charAt(0)) { for (int j = 0; j < needle.length(); j++) { if (i + j >= haystack.length()) { return -1; } if (haystack.charAt(i + j) != needle.charAt(j)) { break; } if (j == needle.length() - 1) { return i; } } } } return -1; } }
6. Longest Common Prefix
class Solution { public String longestCommonPrefix(String[] strs) { if (strs.length == 0) { return ""; } int max = 0; for (int i = 0; i <= strs[0].length(); i++) { String s = strs[0].substring(0, i); for (int j = 1; j < strs.length; j++) { if (i > strs[j].length() || !s.equals(strs[j].substring(0, i))) { return strs[0].substring(0, max); } } max = i; } return strs[0].substring(0, max); } }
思路二:从最长的开始判断,如果不行,长度减一,再进行判断.
class Solution { public String longestCommonPrefix(String[] strs) { if (strs.length == 0) { return ""; } String pre = strs[0]; int i = 1; while (i < strs.length) { if (strs[i].indexOf(pre) != 0) { pre = pre.substring(0, pre.length() - 1); i = 1; } else { i++; } } return pre; } }
7. Reverse Words in a String - Very Important - Not Bug Free - Not Bug Free
坑: 我忘记去掉字符串尾部的space了。
public class Solution { public String reverseWords(String s) { // write your code here // get rid of spaces in the front and end // reverse the whole string // reverse every word if (s.equals("")) { return ""; } char[] chars = s.toCharArray(); int len = chars.length; reverse(chars, 0, len - 1); reverseWord(chars, 0, 0, len); return cleanSpaces(chars, len); } public void reverse(char[] chars, int i, int j) { while (i < j) { char tmp = chars[i]; chars[i++] = chars[j]; chars[j--] = tmp; } } public void reverseWord(char[] chars, int i, int j, int len) { while (j < len) { while (i < len && (i < j || chars[i] == ' ')) { i++; } while (j < len && (j < i || chars[j] != ' ')) { j++; } reverse(chars, i, j-1); } } public String cleanSpaces(char[] chars, int len) { int i = 0; int j = 0; System.out.println(String.valueOf(chars)); while (j < len) { while (j < len && chars[j] == ' ') { j++; } while (j < len && chars[j] != ' ') { chars[i++] = chars[j++]; } while (j < len && chars[j] == ' ') { j++; } if (j < chars.length) { chars[i++] = ' '; } } return String.valueOf(chars).substring(0, i); } }
8. Strstr - Not Bug Free
坑:lenS - lenT 注意循环的条件;i + lenT > lenS也是循环终止的条件
public class Solution { public int strStr(String source, String target) { if (source == null || target == null) { return -1; } char[] s = source.toCharArray(); char[] t = target.toCharArray(); if (s.length < t.length) { return -1; } if (t.length == 0) { return 0; } int i = 0; while (i < s.length) { while (i < s.length && s[i] != t[0]) { i++; } if (i + t.length > s.length) { return -1; } for (int m = 0; m < t.length; m++) { if (i+m < s.length && t[m] != s[i+m]) { i++; break; } if (m == t.length - 1) { return i; } } } return -1; } }
LinkedList
1. Remove Nth Node From End of List - Not Bug Free - Bug Free
思路:快慢指针.
坑:n = n = n > len ? len - n%len : n;
class Solution { public ListNode removeNthFromEnd(ListNode head, int n) { if (head == null) { return head; } int len = 0; ListNode cur = head; while (cur != null) { len++; cur = cur.next; } n = n > len ? len - n%len : n; ListNode dummy = new ListNode(-1); dummy.next = head; ListNode fast = dummy; ListNode slow = dummy; while (n-- != 0) { fast = fast.next; } while (fast.next != null) { fast = fast.next; slow = slow.next; } slow.next = slow.next.next; return dummy.next; } }
2. Middle Node - Not Bug Free
坑:分奇偶讨论 fast.next != null && fast.next.next != null
public ListNode middle(ListNode head) { ListNode fast = head; ListNode slow = head; while (fast.next != null && fast.next.next != null) { fast = fast.next.next; slow = slow.next; } return slow; }
3. Linked List Cycle
思路:和Middle Node思路一致.
public class Solution { public boolean hasCycle(ListNode head) { if (head == null) { return false; } ListNode fast = head; ListNode slow = head; while (fast.next != null && fast.next.next != null) { if (fast.next == slow) { return true; } fast = fast.next.next; slow = slow.next; } return false; } }
4. Remove Duplicates from Sorted List
要和面试官讨论dummy node的值是否可以为-1
class Solution { public ListNode deleteDuplicates(ListNode head) { if (head == null) { return null; } ListNode dummy = new ListNode(Integer.MIN_VALUE); dummy.next = head; ListNode cur = dummy; while (cur.next != null) { if (cur.val == cur.next.val) { cur.next = cur.next.next; } else { cur = cur.next; } } return dummy.next; } }
5. Reverse Linked List - Not Bug Free
坑:当dummy的初始值为null的时候要特别注意.
class Solution { public ListNode reverseList(ListNode head) { if (head == null) { return null; } ListNode dummy = null; ListNode pre = dummy; ListNode cur = head; while (cur != null) { ListNode next = cur.next; cur.next = pre; pre = cur; cur = next; } return pre; } }
思路二:不使用dummy node
class Solution { public ListNode reverseList(ListNode head) { if (head == null || head.next == null) { return head; } ListNode cur = head; ListNode next = cur.next; while (next != null) { ListNode third = next.next; next.next = cur; cur = next; next = third; } head.next = null; return cur; } }
6. Swap Nodes in Pairs - Not Bug Free
坑: 分奇偶讨论while循环的条件cur != null && cur.next != null; dummy node 作为模板使用.
class Solution { public ListNode swapPairs(ListNode head) { if (head == null || head.next == null) { return head; } ListNode dummy = new ListNode(-1); dummy.next = head; ListNode pre = dummy; ListNode cur = head; while (cur != null && cur.next != null) { ListNode next = cur.next; ListNode fourth = next.next; pre.next = next; next.next = cur; cur.next = fourth; pre = cur; cur = fourth; } return dummy.next; } }
7. Merge Two Sorted Lists - Not Bug Free
与merge sort思路一样
class Solution { public ListNode mergeTwoLists(ListNode l1, ListNode l2) { ListNode dummy = new ListNode(-1); ListNode cur = dummy; while (l1 != null && l2 != null) { if (l1.val < l2.val) { cur.next = new ListNode(l1.val); l1 = l1.next; } else { cur.next = new ListNode(l2.val); l2 = l2.next; } cur = cur.next; } while (l1 != null) { cur.next = new ListNode(l1.val); l1 = l1.next; cur = cur.next; } while (l2 != null) { cur.next = new ListNode(l2.val); l2 = l2.next; cur = cur.next; } return dummy.next; } }
8. Add Two Numbers - Not Bug Free
思路:计算carry然后建立node
class Solution { public ListNode addTwoNumbers(ListNode l1, ListNode l2) { ListNode dummy = new ListNode(-1); ListNode cur = dummy; int carry = 0; while (l1 != null || l2 != null || carry != 0) { if (l1 != null) { carry += l1.val; l1 = l1.next; } if(l2 != null){ carry += l2.val; l2 = l2.next; } cur.next = new ListNode(carry%10); carry = carry/10; cur = cur.next; } return dummy.next; } }
9. Remove Linked List Elements
思路:建立dummy node, 注意while循环的条件.
class Solution { public ListNode removeElements(ListNode head, int val) { ListNode dummy = new ListNode(-1); dummy.next = head; ListNode cur = dummy; while (cur.next != null) { if (cur.next.val == val) { cur.next = cur.next.next; }else { cur = cur.next; } } return dummy.next; } }
10. Reverse Linked List II - To be revisited
class Solution { public ListNode reverseBetween(ListNode head, int m, int n) { if (m == n) { return head; } ListNode dummy = new ListNode(-1); dummy.next = head; ListNode pre = dummy; int step = m - 1; while (step-- != 0) { pre = pre.next; } ListNode first = pre; ListNode second = pre.next; pre = pre.next; ListNode cur = pre.next; ListNode next = cur.next; step = n - m; while (step-- != 0) { next = cur.next; cur.next = pre; pre = cur; cur = next; } first.next = pre; second.next = cur; return dummy.next; } }
11. Reorder List - To be revisited
思路: 快慢指针找到List的中部,反转后半部List, 双指针前后靠近.
坑:注意已经指向null.
ListNode mid = slow; mid.next = null; ListNode pre = slow; ListNode cur = pre.next; while (cur != null) { ... }
public class Solution { public void reorderList(ListNode head) { if (head == null) { return; } ListNode fast = head; ListNode slow = head; ListNode l1 = head; while (fast != null && fast.next != null) { fast = fast.next.next; slow = slow.next; } ListNode mid = slow; ListNode pre = slow; ListNode cur = pre.next; while (cur != null) { ListNode next = cur.next; cur.next = pre; pre = cur; cur = next; } mid.next = null; while (pre.next != null) { ListNode left = l1.next; ListNode right = pre.next; l1.next = pre; pre.next = left; l1 = left; pre = right; } } }
12. Rotate List
class Solution { public ListNode rotateRight(ListNode head, int k) { if (head == null || head.next == null || k == 0) { return head; } int count = 0; ListNode dummy = new ListNode(-1); dummy.next = head; ListNode pre = dummy; while (pre.next != null) { pre = pre.next; count++; } ListNode end = pre; pre = dummy; int time = count - k%count; while (time-- != 0) { pre = pre.next; } end.next = head; dummy.next = pre.next; pre.next = null; return dummy.next; } }
13. Partition List
按照值的大小建立2条linked list,2个dummy node. 最后把他们连起来.
class Solution { public ListNode partition(ListNode head, int x) { if (head == null) { return null; } ListNode cur = head; ListNode lHead = new ListNode(-1); ListNode rHead = new ListNode(-1); ListNode l = lHead; ListNode r = rHead; int lCount = 0; int rCount = 0; while (cur != null) { if (cur.val < x) { l.next = cur; l = l.next; lCount++; }else { r.next = cur; r = r.next; rCount++; } cur = cur.next; } if (lCount == 0 || rCount == 0) { return head; }else { r.next = null; l.next = rHead.next; return lHead.next; } } }
14. Palindrome Linked List
思路:快慢指针找到中点,反转第二部分,双指针一起遍历.
class Solution { public boolean isPalindrome(ListNode head) { if (head == null || head.next == null) { return true; } ListNode fast = head; ListNode slow = head; int count = 0; while (fast.next != null && fast.next.next != null) { fast = fast.next.next; slow = slow.next; count++; } count = fast.next == null ? count*2 + 1 : count*2 + 2; ListNode pre = slow.next; ListNode cur = pre.next; while (cur != null) { ListNode next = cur.next; cur.next = pre; pre = cur; cur = next; } int times = count/2; while (times-- != 0) { if (head.val != pre.val) { return false; } head = head.next; pre = pre.next; } return true; } }
Stack & Queue
1. Implement minStack
坑:注意stack为空的情况;stack的syntax;exception的syntax
public class MinStack { public Stack<Integer> stack; public Stack<Integer> minStack; public MinStack() { this.stack = new Stack<Integer>(); this.minStack = new Stack<Integer>(); } public int pop() { if (this.stack.isEmpty()) { throw new RuntimeException("Your stack is empty"); } this.stack.pop(); this.minStack.pop(); } public void push(int val) { this.stack.push(val); if (this.minStack.size() != 0) { if ((int)this.minStack.peek() > val) { this.minStack.push(val); } else { this.minStack.push((int)this.minStack.peek()); } } else { this.minStack.push(val); } } public int getMin() { if (this.stack.isEmpty()) { throw new RuntimeException("Your stack is empty"); } return (int)this.minStack.peek(); }
2. Implement queue using two stacks
思路:一个stackPush,一个StackPop.
public class TwoStackQueue { private Stack<Integer> sPush; private Stack<Integer> sPop; public TwoStackQueue() { this.sPush = new Stack<Integer>(); this.sPop = new Stack<Integer>(); } public void add(int val) { this.sPush.push(val); } public int poll() { if (this.sPush.isEmpty() && this.sPop.isEmpty()) { throw new RuntimeException("Your queue is empty"); } if (this.sPop.isEmpty()) { while (!this.sPush.isEmpty()) { this.sPop.push((int)this.sPush.pop()); } } return (int)this.sPop.pop(); } public int peek() { if (this.sPush.isEmpty() && this.sPop.isEmpty()) { throw new RuntimeException("Your queue is empty"); } if (this.sPop.isEmpty()) { while (!this.sPush.isEmpty()) { this.sPop.push((int)this.sPush.pop()); } } return (int)this.sPop.peek(); } }
3. Using recursive function to reverse a stack
public static int getButtom(Stack s) { int ret = (int)s.pop(); if (s.isEmpty()) { return ret; } else { int temp = getButtom(s); s.push(ret); return temp; } } public static void reverse(Stack s) { if (s.isEmpty()) { return; } else { int buttom = getButtom(s); reverse(s); s.push(buttom); } }
4. Remove Duplicate Letters - 1st Not Bug Free
思路:用stack,frequency, visited, 注意frequency[cur]-- 的位置。注意是一个while 循环。
1 class Solution { 2 public String removeDuplicateLetters(String s) { 3 int[] frequency = new int[256]; 4 for (int i : s.toCharArray()) { 5 frequency[i]++; 6 } 7 boolean[] visited = new boolean[256]; 8 Stack<Character> stack = new Stack<>(); 9 for (int i =0; i < s.length(); i++) { 10 Character cur = s.charAt(i); 11 frequency[cur]--; 12 if (visited[cur]) { 13 continue; 14 } 15 while (!stack.isEmpty() && cur < stack.peek() && frequency[stack.peek()] > 0) { 16 visited[stack.pop()] = false; 17 } 18 stack.push(cur); 19 visited[cur] = true; 20 } 21 StringBuilder builder = new StringBuilder(); 22 while (!stack.isEmpty()) { 23 builder.append(stack.pop()); 24 } 25 return builder.reverse().toString(); 26 } 27 28 }
5. Largest Rectangle in Histogram - 1st Not Bug Free
1 class Solution { 2 public int largestRectangleArea(int[] heights) { 3 if (heights == null || heights.length == 0) { 4 return 0; 5 } 6 Stack<Integer> s = new Stack<>(); 7 int max = 0; 8 for (int i = 0; i <= heights.length; i++) { 9 int cur = i == heights.length ? 0 : heights[i]; 10 while (!s.isEmpty() && cur < heights[s.peek()]) { 11 int h = heights[s.pop()]; 12 int start = s.isEmpty() ? -1 : s.peek(); 13 int curArea = h * (i - start - 1); 14 max = Math.max(max, curArea); 15 } 16 s.push(i); 17 } 18 return max; 19 } 20 }
6. Trapping Rain Water - 1st Not Bug Free
1 class Solution { 2 public int trap(int[] height) { 3 int res = 0; 4 int j = 0; 5 Stack<Integer> s = new Stack<>(); 6 while (j < height.length) { 7 int cur = height[j]; 8 if (s.isEmpty() || cur <= height[s.peek()]) { 9 s.push(j++); 10 } else { 11 int low = height[s.pop()]; 12 if (s.isEmpty()) continue; 13 int h = Math.min(height[s.peek()]-low, height[j]-low); 14 res += h * (j - s.peek() - 1); 15 } 16 } 17 return res; 18 } 19 }
7. Next Greater Element I - 1st Not Bug Free
思路:建立递增stack,如果peek < nums[i], 弹出。放入map里面。
1 class Solution { 2 public int[] nextGreaterElement(int[] nums1, int[] nums2) { 3 Map<Integer, Integer> map = new HashMap<>(); 4 Stack<Integer> s = new Stack<>(); 5 for (int i = 0; i < nums2.length; i++) { 6 while (!s.isEmpty() && s.peek() < nums2[i]) { 7 map.put(s.pop(), nums2[i]); 8 } 9 s.push(nums2[i]); 10 } 11 int[] res = new int[nums1.length]; 12 for (int i = 0; i < nums1.length; i++) { 13 res[i] = map.containsKey(nums1[i]) ? map.get(nums1[i]) : -1; 14 } 15 return res; 16 } 17 }
8. Next Greater Element II - 1st Not Bug Free
思路:增长array,map里面存放index,建立递增stack,如果peek < nums[i], 弹出。放入map里面。
1 class Solution { 2 public int[] nextGreaterElements(int[] nums) { 3 if (nums == null || nums.length == 0) { 4 return nums; 5 } 6 int[] newArray = new int[2*nums.length-1]; 7 for (int i = 0; i < nums.length; i++) { 8 newArray[i] = nums[i]; 9 10 } 11 12 for (int i = 0; i < nums.length - 1; i++) { 13 newArray[nums.length+i] = nums[i]; 14 } 15 16 Map<Integer, Integer> map = new HashMap<>(); 17 Stack<Integer> s = new Stack<>(); 18 for (int i = 0; i < newArray.length; i++) { 19 while (!s.isEmpty() && newArray[s.peek()] < newArray[i]) { 20 map.put(s.pop(), i); 21 } 22 s.push(i); 23 } 24 int[] res = new int[nums.length]; 25 for (int i = 0; i < nums.length; i++) { 26 res[i] = map.containsKey(i) ? newArray[map.get(i)] : -1; 27 } 28 return res; 29 } 30 }
9. Score of Parentheses - 1st Not Bug Free
思路:( 就push(-1), ) 就计算在同一层的个数。最后在乘以2. 会把最后一个-1给pop,所以求出stack的和就好了。
1 class Solution { 2 public int scoreOfParentheses(String S) { 3 Stack<Integer> stack = new Stack<>(); 4 char[] arr = S.toCharArray(); 5 for (char i : arr) { 6 if (i == '(') { 7 stack.push(-1); 8 } else { 9 int curLevelSum = 0; 10 while (!stack.isEmpty() && stack.peek() != -1) { 11 curLevelSum += stack.pop(); 12 } 13 stack.pop(); 14 stack.push(curLevelSum == 0 ? 1 : 2 * curLevelSum); 15 } 16 } 17 int sum = 0; 18 while (!stack.isEmpty()) { 19 sum += stack.pop(); 20 } 21 return sum; 22 } 23 }
10.Daily Temperatures
思路:和Next Greater Element II一样里面存放index。
1 class Solution { 2 public int[] dailyTemperatures(int[] temperatures) { 3 if (temperatures == null || temperatures.length == 0) { 4 return temperatures; 5 } 6 Map<Integer, Integer> map = new HashMap<>(); 7 Stack<Integer> s = new Stack<>(); 8 for (int i = 0; i < temperatures.length; i++) { 9 while (!s.isEmpty() && temperatures[s.peek()] < temperatures[i]) { 10 map.put(s.peek(), i - s.pop()); 11 } 12 s.push(i); 13 } 14 int[] res = new int[temperatures.length]; 15 for (int i = 0; i < temperatures.length; i++) { 16 res[i] = map.containsKey(i) ? map.get(i) : 0; 17 } 18 return res; 19 } 20 }
11. All sum 0 Subarrays - 1st Not Bug Free
思路:建立一个index 为sum(记录从0 到i的sum), value 为i的hashmap, 如果有重复的key出现,说明i, j之间和为零。
声明一个new comparator来比较list。
1 static List<List<Integer>> findSubArrays(int[] arr) { 2 HashMap<Integer, List<Integer>> map = new HashMap<>(); 3 List<List<Integer>> results = new ArrayList<>(); 4 int sum = 0; 5 List index = new ArrayList<>(); 6 index.add(-1); 7 map.put(0, index); 8 for (int i = 0; i < arr.length; i ++) { 9 sum += arr[i]; 10 if (map.containsKey(sum)) { 11 index = map.get(sum); 12 for (int j = 0; j < index.size(); j ++) { 13 List result = new ArrayList<>(); 14 result.add(index.get(j) + 1); 15 result.add(i); 16 results.add(result); 17 } 18 index.add(i); 19 } else { 20 index = new ArrayList<>(); 21 index.add(i); 22 map.put(sum, index); 23 } 24 } 25 Comparator comparator = new MyComparator(); 26 Collections.sort(results, comparator); 27 return results; 28 } 29 30 static class MyComparator implements Comparator { 31 public int compare(List a, List b) { 32 for (int i = 0; i < a.size(); i ++) { 33 if (a.get(i) != b.get(i)) { 34 return a.get(i) - b.get(i); 35 } 36 else continue; 37 } 38 return 0; 39 } 40 }
12. BST Inorder Traversal - 1st Not Bug Free
思路;建立一个stack,root = cur, 如果cur != null 或者 stack不为空,进行判断。一直往左走,走到尽头,弹出一个,再往右走,此时cur = null,继续弹出,这时弹出的是parent,存储parent,再往右走。就可以了。
1 /** 2 * Definition for a binary tree node. 3 * public class TreeNode { 4 * int val; 5 * TreeNode left; 6 * TreeNode right; 7 * TreeNode(int x) { val = x; } 8 * } 9 */ 10 class Solution { 11 public List<Integer> inorderTraversal(TreeNode root) { 12 List<Integer> res = new ArrayList<>(); 13 Stack<TreeNode> s = new Stack<>(); 14 TreeNode cur = root; 15 while (!s.isEmpty() || cur != null) { 16 while (cur != null) { 17 s.push(cur); 18 cur = cur.left; 19 } 20 cur = s.pop(); 21 res.add(cur.val); 22 cur = cur.right; 23 } 24 return res; 25 } 26 }
13. BST Preorder Traversal - 1st Not Bug Free
思路:visit中间,push 左边,push 右边
1 class Solution { 2 public List<Integer> preorderTraversal(TreeNode root) { 3 List<Integer> result = new ArrayList<Integer>(); 4 if (root == null) return result; 5 Stack<TreeNode> stack = new Stack<TreeNode>(); 6 stack.push(root); 7 while (!stack.isEmpty()){ 8 TreeNode node = stack.pop(); 9 result.add(node.val); 10 if (node.right != null) stack.push(node.right); 11 if (node.left != null) stack.push(node.left); 12 } 13 return result; 14 } 15 }
14. Bad Hair Day
15. Remove Duplicate Letters - 2nd Not Bug Free
思路:建立stack,freq,visited。
while (!stack.isEmpty() && stack.peek() > cur && freq[stack.peek()] > 0)
visited[stack.pop()] = false;
1 class Solution { 2 public String removeDuplicateLetters(String s) { 3 int[] freq = new int[256]; 4 for (char i : s.toCharArray()) { 5 freq[i]++; 6 } 7 boolean[] visited = new boolean[256]; 8 Stack<Character> stack = new Stack<>(); 9 for (int i = 0; i < s.length(); i++) { 10 char cur = s.charAt(i); 11 freq[cur]--; 12 if (visited[cur]) { 13 continue; 14 } 15 while (!stack.isEmpty() && stack.peek() > cur && freq[stack.peek()] > 0) { 16 visited[stack.pop()] = false; 17 } 18 stack.push(cur); 19 visited[cur] = true; 20 } 21 StringBuilder res = new StringBuilder(); 22 while (!stack.isEmpty()) { 23 res.append(stack.pop()); 24 } 25 return res.reverse().toString(); 26 } 27 28 }
Recursion - DFS
1. KnapsackI: True or false
思路一:最直接的recursion.
public static boolean exist(int[] nums, int target, int index) { if (target == 0) { return true; } if (index == nums.length || target < 0) { return false; } return exist(nums, target - nums[index], index++) || exist(nums, target, index++); }
2. KnapsackII: element can be reused but no dupulicate solutions
技巧:有for-loop就不用“用”或“不用”了
1 public static void knapsackII(int[] nums, List<List<Integer>> results, List<Integer> items, int target, int index) { 2 if (target == 0) { 3 results.add(new ArrayList(items)); 4 return; 5 } 6 7 if (target < 0 || index == nums.length) { 8 return; 9 } 10 11 for (int i = index; i < nums.length; i++) { 12 if (i > 0 && nums[i] == nums[i-1]) { 13 continue; 14 } 15 items.add(nums[i]); 16 knapsackII(nums, results, items, target - nums[i], i); 17 items.remove(items.size() - 1); 18 // 不需要! 19 //knapsackII(nums, results, items, target, i+1); 20 } 21 }
knapsackIII: element cannot be reused but can contain dupulicate solutions
1 public static void knapsackIII(int[] nums, List<List<Integer>> results, List<Integer> items, int target, int index) { 2 if (target == 0) { 3 results.add(new ArrayList(items)); 4 return; 5 } 6 7 if (target < 0 || index == nums.length) { 8 return; 9 } 10 11 for (int i = index; i < nums.length; i++) { 12 items.add(nums[i]); 13 knapsackIII(nums, results, items, target - nums[i], i + 1); 14 items.remove(items.size() - 1); 15 } 16 }
knapsackIV: return the max weight of the bag
注意边界条件,利用oldSize和curSize
1 public static int knapsackIV(int[] nums, int target, int curSize, int oldSize, int index) { 2 if (target == 0) { 3 return curSize; 4 } 5 6 if (target < 0) { 7 return oldSize; 8 } 9 10 if (target > 0 && index == nums.length) { 11 return curSize; 12 } 13 14 return Math.max(knapsackIV(nums, target - nums[index], curSize + nums[index], curSize, index+1), knapsackIV(nums, target, curSize, curSize, index+1)); 15 }
3. Maze - 1
1 public static boolean exist(char[][] board, int startX, int startY, int targetX, int targetY) { 2 if (startX == targetX && startY == targetY) { 3 return true; 4 } 5 if (startX < 0 || startX >= board.length || startY < 0 || startY >= board[0].length || board[startX][startY] == 'X') { 6 return false; 7 } 8 int[] dx = {1, -1, 0, 0}; 9 int[] dy = {0, 0, 1, -1}; 10 board[startX][startY] = 'X'; 11 for (int i = 0; i < 4; i++) { 12 if (exist(board,startX + dx[i], startY + dy[i], targetX, targetY)) { 13 return true; 14 } 15 } 16 board[startX][startY] = '.'; 17 return false; 18 }
4. Maze - 2
Print all paths
1 public static void printPath(List<List<Character>> results, List<Character> items, char[][] board, int startX, int startY, int targetX, int targetY) { 2 if (startX == targetX && startY == targetY) { 3 results.add(new ArrayList<>(items)); 4 return; 5 } 6 if (startX < 0 || startX >= board.length || startY < 0 || startY >= board[0].length || board[startX][startY] == 'X') { 7 return; 8 } 9 int[] dx = {1, -1, 0, 0}; 10 int[] dy = {0, 0, 1, -1}; 11 char[] dir = {'R', 'L', 'D', 'U'}; 12 board[startX][startY] = 'X'; 13 for (int i = 0; i < 4; i++) { 14 items.add(dir[i]); 15 printPath(results, items, board, startX + dx[i], startY + dy[i], targetX, targetY); 16 items.remove(items.size() - 1); 17 } 18 board[startX][startY] = '.'; 19 }
5. Subset - No duplication
public void solve2(List<List<Integer>> result, int[] num, List<Integer> item, int index){ if(index == num.length){ result.add(new ArrayList<Integer>(item)); return; } for(int i = index; i < num.length; i++){ item.add(num[i]); solve2(result, num, item, i + 1); item.remove(item.size() - 1); } solve2(result, num, item, num.length); }
6. Subset - Duplication
public static void solve3(List<List<Integer>> results, int[] nums, List<Integer> items, int index) { if (index == nums.length) { results.add(new ArrayList<>(items)); return; } for (int i = index; i < nums.length; i++) { if (i > index && nums[i] == nums[i-1]) { continue; } items.add(nums[i]); solve3(results, nums, items, i + 1); items.remove(items.size() - 1); } solve3(results, nums, items, nums.length); }
7. Permutation - No duplication
class Solution { public List<List<Integer>> permute(int[] nums) { List<List<Integer>> results = new ArrayList<>(); boolean[] visited = new boolean[nums.length]; solve(results, new ArrayList<Integer>(), nums, visited); return results; } public void solve(List<List<Integer>> results, List<Integer> items, int[] nums, boolean[] visited) { if (items.size() == nums.length) { results.add(new ArrayList<>(items)); return; } for (int i = 0; i < nums.length; i++) { if (visited[i]) { continue; } visited[i] = true; items.add(nums[i]); solve(results, items, nums, visited); items.remove(items.size() - 1); visited[i] = false; } } }
8. Permutation - Duplication - 3rd Not Bug Free
坑:忘记visited[i-1] == false; 不需要用index
public class Solution { public List<List<Integer>> permuteUnique(int[] nums) { List<List<Integer>> results = new ArrayList<>(); Arrays.sort(nums); boolean[] visited = new boolean[nums.length]; solve(results, new ArrayList<Integer>(), nums, visited); return results; } public void solve(List<List<Integer>> results, List<Integer> items, int[] nums, boolean[] visited) { if (items.size() == nums.length) { results.add(new ArrayList<>(items)); return; } for (int i = 0; i < nums.length; i++) { if (visited[i] || (i > 0 && nums[i] == nums[i-1] && !visited[i-1])) { continue; } visited[i] = true; items.add(nums[i]); solve(results, items, nums, visited); items.remove(items.size() - 1); visited[i] = false; } } }
9. Combinational Sum - No Duplication - To be revisited
坑:要注意for循环里面不能再solve(results, items, nums, target, i+1)了; 不然就重复了.
坑:注意题目要求,每个元素是否可以使用多次。
private void solve(List<List<Integer>> results, List<Integer> items, int [] nums, int target, int index){ if(index == nums.length) { return; } if(target == 0) { results.add(new ArrayList<>(items)); return; } for(int i = index; i < nums.length; i++){ if (target >= nums[i]) { items.add(nums[i]); solve(results, items, nums, target - nums[i], i); items.remove(items.size() - 1); } } }
10. Combinational Sum - Duplication - 3rd Not Bug Free
有index的时候, 就是if (i > index && nums[i] == nums[i-1]). 要是没有就是if (i > 0 && nums[i] == nums[i-1])
注意for-loop里面是i, 而不是index参与下一次recursive call
坑:注意题目要求,每个元素是否可以使用多次。
public void solve(List<List<Integer>> results, List<Integer> items, int[] nums, int target, int index){ if(target == 0){ results.add(new ArrayList<>(items)); return; } if(index == nums.length){ return; } for(int i = index; i < nums.length; i++){ if(i > index && nums[i] == nums[i-1] ){ continue; } if(nums[i] <= target){ items.add(nums[i]); solve(results, items, nums, target - nums[i], i + 1); items.remove(items.size() - 1); } } }
11. Palindrome
public void solve(List<List<String>> results, List<String> items, String s, int index){ if(s.length() == index){ results.add(new ArrayList<>(items)); return; } for(int i = index; i < s.length(); i++){ if(isPalin(s.substring(index, i+1))){ items.add(s.substring(index, i+1)); solve(results, items, s, i+1); items.remove(items.size() - 1); } } }
12. Restore IP address
class Solution { public List<String> restoreIpAddresses(String s) { List<String> results = new ArrayList<>(); solve(results, "", s, 0, 4); return results; } public void solve(List<String> results, String items, String s, int index, int times){ if(index == s.length() && times == 0){ results.add(items); return; } if(times < 0){ return; } for(int i = index; i < s.length(); i++){ String tmp = s.substring(index, i+1); if(isValid(tmp)){ String newStr = times == 1 ? items + tmp : items + tmp + "."; times--; solve(results, newStr, s, i+1, times); times++; } } } public boolean isValid(String s){ double value = Double.parseDouble(s); if(s.charAt(0) == '0'){ return s.length() == 1; } return value <= 255 && value >= 0; } }
13. Word search
class Solution { public boolean exist(char[][] board, String word) { boolean[][] visited = new boolean[board.length][board[0].length]; List<Character> items = new ArrayList<Character>(); for(int row = 0; row < board.length; row++){ for(int col = 0; col < board[0].length; col++){ if(board[row][col] == word.charAt(0)){ if(solve(board, word, items, visited, row, col, 0)){ return true; } } } } return false; } public boolean solve(char[][] board, String word, List<Character> items, boolean[][] visited, int x, int y, int index){ if(index == word.length()){ return true; } if(x < 0 || x > board.length - 1 || y < 0 || y > board[0].length - 1 || visited[x][y] == true || board[x][y] != word.charAt(index)){ return false; } int[] dx = {1, 0, -1, 0}; int[] dy = {0, 1, 0 , -1}; visited[x][y] = true; for(int j = 0; j< 4; j++){ if(solve(board, word, items, visited, x + dx[j], y + dy[j], index+1)){ return true; } } visited[x][y] = false; return false; } }
14. Gray Code - 1st Not Bug Free
For example, given n = 2, return [0,1,3,2]. Its gray code sequence is:
00 - 0 01 - 1 11 - 3 10 - 2
思路:寻找规律
解法一:Recursive
1 class Solution { 2 public List<Integer> grayCode(int n) { 3 List<Integer> result = new ArrayList(); 4 if (n == 0) { 5 result.add(0); 6 return result; 7 } 8 List<Integer> middle = new ArrayList(); 9 middle.add(0); 10 middle.add(1); 11 solve(n-1, middle, result, n); 12 return result; 13 } 14 15 public void solve(int n, List<Integer> middle, List<Integer> result, int total) { 16 if (n == 0) { 17 for (Integer i : middle) { 18 result.add(i); 19 } 20 return; 21 } 22 List<Integer> newMiddle = new ArrayList(); 23 for (Integer i : middle) { 24 newMiddle.add(i); 25 } 26 for (int i = middle.size() - 1; i >=0; i--) { 27 newMiddle.add(middle.get(i) + (1<<(total - n))); 28 } 29 solve(n-1, newMiddle, result, total); 30 } 31 }
解法二:for-loop
1 class Solution { 2 public List<Integer> grayCode(int n) { 3 List<Integer> result = new ArrayList(); 4 result.add(0); 5 for (int i = 1; i <= n; i++) { 6 int size = result.size(); 7 for (int j = size - 1; j >= 0; j--) { 8 result.add(result.get(j) + (1 << (i - 1))); 9 } 10 } 11 return result; 12 } 13 }
15. Binary Tree Maximum Path Sum --- 2nd Not Bug Free
思路:由于TreeNode的数据结构,只能从root入手;计算左边(root.left)和右边(root.right)的值;每个node都可以选择 root, root + left, 和root + right, 和root + left + right, 这样用来保证parent-child关系但是返回上一级的时候是返回的branchMax, 也就是说root + left, 或root + right, 或root + 0。这样一来,不是每一个node都能返回 root + left + right.
1 class Solution { 2 int max_sum = Integer.MIN_VALUE; 3 public int maxPathSum(TreeNode root) { 4 if (root == null) { 5 return 0; 6 } 7 branchMax(root); 8 return max_sum; 9 } 10 11 public int branchMax(TreeNode root) { 12 if (root == null) { 13 return 0; 14 } 15 int leftSum = branchMax(root.left); 16 int rightSum = branchMax(root.right); 17 int bMax = root.val + Math.max(0, Math.max(leftSum, rightSum)); 18 max_sum = Math.max(max_sum, Math.max(bMax, root.val + leftSum + rightSum)); 19 return bMax; 20 } 21 }
16. Path Sum II --- 2nd Not Bug Free
坑:如果满足条件直接return,items将不会进行backtracking,注意item.add()的位置; 注意题目条件,必须是leaf节点.
1 class Solution { 2 public List<List<Integer>> pathSum(TreeNode root, int sum) { 3 List<List<Integer>> result = new ArrayList<>(); 4 if (root == null) { 5 return result; 6 } 7 solve(result, new ArrayList<Integer>(), root, sum); 8 return result; 9 } 10 11 public void solve(List<List<Integer>> result, List<Integer> items, TreeNode root, int sum) { 12 if (root == null) return; 13 14 items.add(root.val); 15 if (root.left == null && root.right == null && sum == root.val) { 16 result.add(new ArrayList<>(items)); 17 } 18 19 solve(result, items, root.left, sum - root.val); 20 solve(result, items, root.right, sum - root.val); 21 items.remove(items.size() - 1); 22 } 23 }
解法二:坑:元素可能是负数
class Solution { public List<List<Integer>> pathSum(TreeNode root, int sum) { List<List<Integer>> res = new ArrayList<>(); solve(root, sum, res, new ArrayList<Integer>()); return res; } public void solve(TreeNode root, int sum, List<List<Integer>> res, List<Integer> items) { if (root == null) { return; } if (root.left == null && root.right == null && sum == root.val) { items.add(root.val); res.add(new ArrayList<>(items)); items.remove(items.size() - 1); return; } items.add(root.val); solve(root.left, sum - root.val, res, items); solve(root.right, sum - root.val, res, items); items.remove(items.size() - 1); } }
17. Lucky Numbers ---- 1st Not Bug Free
两个index: idx 和 i+1; * 和 / 要注意,定义一个post,代表表达式里面的最后一个数。
1 // "static void main" must be defined in a public class. 2 public class Main { 3 public static void main(String[] args) { 4 int target = 888; 5 String num = "7765332111"; 6 System.out.println(String.valueOf(lucky(num, target))); 7 } 8 9 public static List<String> lucky(String num, int target) { 10 List<String> res = new ArrayList<>(); 11 solve(num, target, res, "", 0, 0, 0); 12 return res; 13 } 14 15 public static void solve(String num, int target, List<String> res, String cur, int idx, long curVal, long post) { 16 if (idx == num.length()) { 17 if ((int)curVal == target) { 18 res.add(cur); 19 } 20 return; 21 } 22 for (int i = idx; i < num.length(); i++) { 23 if (num.charAt(idx) == '0' && i != idx) { 24 break; 25 } 26 String sub = num.substring(idx, i+1); 27 long val = Long.valueOf(sub); 28 if (idx == 0) { 29 solve(num, target, res, cur + sub, i+1, val, val); 30 } else { 31 solve(num, target, res, cur + "+" + sub, i+1, curVal+val, val); 32 solve(num, target, res, cur + "-" + sub, i+1, curVal+val, val); 33 solve(num, target, res, cur + "*" + sub, i+1, curVal-post + post*val, post*val); 34 if (val != 0 && post%val == 0) { 35 solve(num, target, res, cur + "/" + sub, i+1, curVal-post + post/val, post/val); 36 } 37 } 38 } 39 } 40 }
18. Remove Invalid Parentheses ---- 1st Not Bug Free
思路:定义rmL, rmR, open, 左括号和右括号可以要或者不要。StringBuilder 的backtrace。
1 class Solution { 2 public List<String> removeInvalidParentheses(String s) { 3 int rmL = 0, rmR = 0, open = 0; 4 for (int i = 0; i < s.length(); i++) { 5 char cur = s.charAt(i); 6 if (cur == '(') { 7 rmL++; 8 } else if (cur == ')') { 9 if (rmL != 0) { 10 rmL--; 11 } else { 12 rmR++; 13 } 14 15 } 16 } 17 Set<String> set = new HashSet<>(); 18 solve(s, set, rmL, rmR, open, new StringBuilder(), 0); 19 return new ArrayList<String>(set); 20 } 21 22 public void solve(String s, Set<String> set, int rmL, int rmR, int open, StringBuilder sb, int idx) { 23 if (rmL < 0 || rmR < 0 || open < 0) { 24 return; 25 } 26 if (idx == s.length()) { 27 if (rmL == 0 && rmR == 0 && open == 0) { 28 set.add(sb.toString()); 29 } 30 return; 31 } 32 33 char cur = s.charAt(idx); 34 35 if (cur == '(') { 36 solve(s, set, rmL, rmR, open+1, sb.append(cur), idx+1); 37 sb.setLength(sb.length() - 1); 38 solve(s, set, rmL-1, rmR, open, sb, idx+1); 39 } else if (cur == ')') { 40 solve(s, set, rmL, rmR, open-1, sb.append(cur), idx+1); 41 sb.setLength(sb.length() - 1); 42 solve(s, set, rmL, rmR-1, open, sb, idx+1); 43 } else { 44 solve(s, set, rmL, rmR, open, sb.append(cur), idx+1); 45 sb.setLength(sb.length() - 1); 46 } 47 48 } 49 }
19. Validate Binary Search Tree ---- 1st Not Bug Free
思路一:转化为inOrder,看是否由小到大的顺序排列。
1 class Solution { 2 List<Integer> res = new ArrayList<>(); 3 4 public boolean isValidBST(TreeNode root) { 5 inOrder(root); 6 for (int i = 1; i < res.size(); i++) { 7 if (res.get(i) <= res.get(i-1)) { 8 return false; 9 } 10 } 11 return true; 12 } 13 14 public void inOrder(TreeNode root) { 15 if (root == null) { 16 return; 17 } 18 inOrder(root.left); 19 res.add(root.val); 20 inOrder(root.right); 21 } 22 }
思路二:helper(node, max, min)
1 class Solution { 2 public boolean isValidBST(TreeNode root) { 3 return helper(root, Long.MAX_VALUE, Long.MIN_VALUE); 4 } 5 6 public boolean helper(TreeNode root, long max, long min) { 7 if (root == null) return true; 8 return root.val < max && root.val > min && helper(root.right, max, root.val) && helper(root.left, root.val, min); 9 } 10 }
20. Flatten Binary Tree to Linked List ---- 1st Not Bug Free
思路一:postOrder in terms of (right, left, root)
1 class Solution { 2 TreeNode prev = null; 3 public void flatten(TreeNode root) { 4 if (root == null) { 5 return; 6 } 7 flatten(root.right); 8 flatten(root.left); 9 root.right = prev; 10 root.left = null; 11 prev = root; 12 } 13 }
思路二:non-recursive
1 class Solution { 2 TreeNode prev = null; 3 public void flatten(TreeNode root) { 4 if (root == null) { 5 return; 6 } 7 TreeNode cur = root; 8 while (cur != null) { 9 if (cur.left != null) { 10 TreeNode last = cur.left; 11 while (last.right != null) { 12 last = last.right; 13 } 14 last.right = cur.right; 15 cur.right = cur.left; 16 cur.left = null; 17 } 18 cur = cur.right; 19 } 20 } 21 }
BFS
1. The Maze II. --- 1st Not Bug Free
坑:
1 if (dis < distance[x][y]) { 2 distance[x][y] = dis; 3 if (x != dest[0] || y != dest[1]) { 4 queue.offer(new Pair(x, y)); 5 } 6 }
1 public class Solution { 2 /** 3 * @param maze: the maze 4 * @param start: the start 5 * @param destination: the destination 6 * @return: the shortest distance for the ball to stop at the destination 7 */ 8 public int shortestDistance(int[][] maze, int[] start, int[] dest) { 9 // write your code here 10 int row = maze.length; 11 int col = maze[0].length; 12 int[][] distance = new int[row][col]; 13 for (int i = 0; i < row; i++) { 14 for (int j = 0; j < col; j++) { 15 distance[i][j] = Integer.MAX_VALUE; 16 } 17 } 18 int[] dx = {-1,1,0,0}; 19 int[] dy = {0,0,-1,1}; 20 Queue<Pair> queue = new LinkedList<Pair>(); 21 queue.offer(new Pair(start[0], start[1])); 22 distance[start[0]][start[1]] = 0; 23 while (!queue.isEmpty()) { 24 Pair pair = queue.poll(); 25 26 for (int i = 0; i < 4; i++) { 27 int x = pair.x; 28 int y = pair.y; 29 int dis = distance[x][y]; 30 while (x >= 0 && x < row && y >= 0 && y < col && maze[x][y] == 0) { 31 x += dx[i]; 32 y += dy[i]; 33 dis++; 34 } 35 x -= dx[i]; 36 y -= dy[i]; 37 dis--; 38 if (dis < distance[x][y]) { 39 distance[x][y] = dis; 40 if (x != dest[0] || y != dest[1]) { 41 queue.offer(new Pair(x, y)); 42 } 43 } 44 45 } 46 } 47 int res = distance[dest[0]][dest[1]]; 48 return res == Integer.MAX_VALUE ? -1 : res; 49 } 50 } 51 52 class Pair { 53 int x; 54 int y; 55 public Pair(int a, int b) { 56 x = a; 57 y = b; 58 } 59 }
2. Maze III --- 1st Not Bug Free
坑: String[] dir = {"d", "l", "r", "u"}; 是根据行列号变化而变得
if (dis < distance[x][y] || (dis == distance[x][y] && s1.compareTo(path[x][y]) < 0)) { distance[x][y] = dis; path[x][y] = s1; if (x != dest[0] || y != dest[1]) { queue.offer(new Pair(x, y)); } }
1 public class Solution { 2 /** 3 * @param maze: the maze 4 * @param ball: the ball position 5 * @param hole: the hole position 6 * @return: the lexicographically smallest way 7 */ 8 public String findShortestWay(int[][] maze, int[] start, int[] dest) { 9 // write your code here 10 int row = maze.length; 11 int col = maze[0].length; 12 int[][] distance = new int[row][col]; 13 String[][] path = new String[row][col]; 14 for (int i = 0; i < row; i++) { 15 for (int j = 0; j < col; j++) { 16 distance[i][j] = Integer.MAX_VALUE; 17 path[i][j] = ""; 18 } 19 } 20 int[] dx = {1, 0, 0, -1}; 21 int[] dy = {0, -1, 1, 0}; 22 String[] dir = {"d", "l", "r", "u"}; 23 Queue<Pair> queue = new LinkedList<Pair>(); 24 queue.offer(new Pair(start[0], start[1])); 25 distance[start[0]][start[1]] = 0; 26 path[start[0]][start[1]] = ""; 27 while (!queue.isEmpty()) { 28 Pair pair = queue.poll(); 29 for (int i = 0; i < 4; i++) { 30 int x = pair.x; 31 int y = pair.y; 32 int dis = distance[x][y]; 33 String currentPath = path[x][y]; 34 while (x >= 0 && x < row && y >= 0 && y < col && maze[x][y] == 0 && (x != dest[0] || y != dest[1])) { 35 x += dx[i]; 36 y += dy[i]; 37 dis++; 38 } 39 if (x != dest[0] || y != dest[1]) { 40 x -= dx[i]; 41 y -= dy[i]; 42 dis--; 43 } 44 String s1 = currentPath.concat(dir[i]); 45 if (dis < distance[x][y] || (dis == distance[x][y] && s1.compareTo(path[x][y]) < 0)) { 46 distance[x][y] = dis; 47 path[x][y] = s1; 48 if (x != dest[0] || y != dest[1]) { 49 queue.offer(new Pair(x, y)); 50 } 51 } 52 } 53 } 54 55 String result = path[dest[0]][dest[1]]; 56 return distance[dest[0]][dest[1]] == Integer.MAX_VALUE ? "impossible" : result; 57 } 58 } 59 60 class Pair { 61 int x; 62 int y; 63 public Pair(int a, int b) { 64 x = a; 65 y = b; 66 } 67 }
3. Word Ladder I --- 1st Not Bug Free
思路:两个Queue,每一层存储distance为1的list。为了防止有重复建立Set
坑: 用26个字母进行for-loop,running time会大大缩短. 用set保存wordlist会让contains操作变为O(1).
1 class Solution { 2 public int ladderLength(String beginWord, String endWord, List<String> wordList) { 3 int distance = 1; 4 Set<String> wordSet = new HashSet<String>(); 5 Set<String> visited = new HashSet<String>(); 6 for (String s : wordList) { 7 wordSet.add(s); 8 } 9 Queue<String> queue = new LinkedList<>(); 10 queue.offer(beginWord); 11 while (!queue.isEmpty()) { 12 Set<String> queue1 = new HashSet<>(); 13 distance++; 14 while (!queue.isEmpty()) { 15 String top = queue.poll(); 16 Set<String> oneWordList = getWordWithinDistance(top, wordList, wordSet, visited); 17 if (oneWordList.contains(endWord)) { 18 return distance; 19 } 20 queue1.addAll(oneWordList); 21 } 22 queue.addAll(queue1); 23 } 24 return 0; 25 } 26 27 public Set<String> getWordWithinDistance(String beginWord, List<String> wordList, Set<String> wordSet, Set<String> visited) { 28 Set<String> oneWordList = new HashSet<>(); 29 char[] char1 = beginWord.toCharArray(); 30 for (int i = 0; i < char1.length; i++) { 31 char cur = char1[i]; 32 for (char a = 'a'; a < 'z'; a++) { 33 if (a == cur) { 34 continue; 35 } 36 char1[i] = a; 37 String newString = new String(char1); 38 if (visited.contains(newString)) { 39 continue; 40 } 41 if (wordSet.contains(newString)) { 42 oneWordList.add(newString); 43 visited.add(newString); 44 } 45 } 46 char1[i] = cur; 47 } 48 return oneWordList; 49 } 50 51 }
4. Word Ladder II --- 1st Not Bug Free
思路:BFS + DFS, BFS用来建立shortest path, DFS 用来输出。每走一层,建立一个HashMap<String, List<String>>, 之后用于返回路径。
坑:为了防止有重复建立Set.
1 class Solution { 2 public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) { 3 List<List<String>> result = new ArrayList<>(); 4 HashMap<String, List<String>> preList = new HashMap(); 5 Set<String> visited = new HashSet(); 6 visited.add(beginWord); 7 Set<String> wordSet = new HashSet<String>(); 8 for (String s : wordList) { 9 wordSet.add(s); 10 } 11 Queue<String> queue = new LinkedList<>(); 12 queue.offer(beginWord); 13 14 while (!queue.isEmpty() ) { 15 Set<String> queue1 = new HashSet<>(); 16 boolean isFinished = false; 17 while (!queue.isEmpty()) { 18 String top = queue.poll(); 19 Set<String> oneWordList = getWordWithinDistance(top, wordSet); 20 for (String word : oneWordList) { 21 if (word.equals(endWord)) { 22 isFinished = true; 23 } 24 if (!visited.contains(word)) { 25 updatePreList(preList, word, top); 26 queue1.add(word); 27 } 28 } 29 } 30 visited.addAll(queue1); 31 if (isFinished) { 32 getPath(result, preList, new ArrayList<>(), endWord); 33 break; 34 } 35 queue.addAll(queue1); 36 } 37 return result; 38 } 39 40 public void updatePreList(HashMap<String, List<String>> preList, String cur, String pre) { 41 if (!preList.containsKey(cur)) { 42 preList.put(cur, new ArrayList<String>()); 43 } 44 preList.get(cur).add(pre); 45 } 46 47 public void getPath(List<List<String>> result, HashMap<String, List<String>> preList, List<String> cur, String endWord) { 48 if (!preList.containsKey(endWord)) { 49 cur.add(endWord); 50 Collections.reverse(cur); 51 result.add(cur); 52 return; 53 } 54 cur.add(endWord); 55 for (String pre : preList.get(endWord)) { 56 List<String> newCur = new ArrayList<>(cur); 57 //newCur.add(endWord); 58 getPath(result, preList, newCur, pre); 59 } 60 61 } 62 63 public Set<String> getWordWithinDistance(String beginWord, Set<String> wordSet) { 64 Set<String> oneWordList = new HashSet<>(); 65 char[] char1 = beginWord.toCharArray(); 66 for (int i = 0; i < char1.length; i++) { 67 char cur = char1[i]; 68 for (char a = 'a'; a <= 'z'; a++) { 69 if (a == cur) { 70 continue; 71 } 72 char1[i] = a; 73 String newString = new String(char1); 74 75 if (wordSet.contains(newString)) { 76 oneWordList.add(newString); 77 } 78 } 79 char1[i] = cur; 80 } 81 return oneWordList; 82 } 83 }
5. Binary Tree Right Side View
思路:双queue,每一层先读right node, 再读left node, 每一层先peek第一个,加入list
1 /** 2 * Definition for a binary tree node. 3 * public class TreeNode { 4 * int val; 5 * TreeNode left; 6 * TreeNode right; 7 * TreeNode(int x) { val = x; } 8 * } 9 */ 10 class Solution { 11 public List<Integer> rightSideView(TreeNode root) { 12 List<Integer> result = new ArrayList<>(); 13 if (root == null) { 14 return result; 15 } 16 Queue<TreeNode> queue = new LinkedList<>(); 17 queue.offer(root); 18 while (!queue.isEmpty()) { 19 Queue<TreeNode> queue1 = new LinkedList<>(); 20 TreeNode ele = queue.peek(); 21 result.add(ele.val); 22 while (!queue.isEmpty()) { 23 TreeNode top = queue.poll(); 24 if (top.right != null) { 25 queue1.offer(top.right); 26 } 27 if (top.left != null) { 28 queue1.offer(top.left); 29 } 30 } 31 queue = queue1; 32 } 33 return result; 34 } 35 }
6. Find Largest Value in Each Tree Row --- 1st Not Bug Free
坑:每一层sort一下比较慢,设置max = Integer.MIN_VALUE, 然后每次加入node时比较大小,更新max。
最后一层的时候要设置判断条件,不然max直接等于Integer.MIN_VALUE. 合适的判断方法是boolean hasMore = false,如果有子节点hasMore = true;否则就可以退出了.
1 /** 2 * Definition for a binary tree node. 3 * public class TreeNode { 4 * int val; 5 * TreeNode left; 6 * TreeNode right; 7 * TreeNode(int x) { val = x; } 8 * } 9 */ 10 class Solution { 11 public List<Integer> largestValues(TreeNode root) { 12 List<Integer> result = new ArrayList<>(); 13 if (root == null) { 14 return result; 15 } 16 result.add(root.val); 17 Queue<TreeNode> queue = new LinkedList<>(); 18 queue.offer(root); 19 while (!queue.isEmpty()) { 20 Queue<TreeNode> queue1 = new LinkedList<>(); 21 int max = Integer.MIN_VALUE; 22 boolean hasMore = false; 23 while (!queue.isEmpty()) { 24 TreeNode top = queue.poll(); 25 if (top.left != null) { 26 queue1.offer(top.left); 27 max = Math.max(top.left.val, max); 28 hasMore = true; 29 } 30 if (top.right != null) { 31 queue1.offer(top.right); 32 max = Math.max(top.right.val, max); 33 hasMore = true; 34 } 35 } 36 if (hasMore) { 37 result.add(max); 38 queue = queue1; 39 } 40 } 41 return result; 42 } 43 }
7. Employee Importance
思路:双queue,先建立HashMap<id, employee>, 便于之后寻找.
1 /* 2 // Employee info 3 class Employee { 4 // It's the unique id of each node; 5 // unique id of this employee 6 public int id; 7 // the importance value of this employee 8 public int importance; 9 // the id of direct subordinates 10 public List<Integer> subordinates; 11 }; 12 */ 13 class Solution { 14 public int getImportance(List<Employee> employees, int id) { 15 Queue<Employee> queue = new LinkedList<>(); 16 HashMap<Integer, Employee> map = new HashMap<>(); 17 for (Employee p : employees) { 18 if (p.id == id) { 19 queue.offer(p); 20 } 21 map.put(p.id, p); 22 } 23 int importance = 0; 24 while (!queue.isEmpty()) { 25 Queue<Employee> queue1 = new LinkedList<>(); 26 while (!queue.isEmpty()) { 27 Employee top = queue.poll(); 28 importance += top.importance; 29 if (top.subordinates.size() != 0) { 30 for (int subId : top.subordinates) { 31 queue1.offer(map.get(subId)); 32 } 33 } 34 } 35 queue = queue1; 36 } 37 return importance; 38 } 39 }
8. Minesweeper
思路:双queue,BFS, 建立visited[x][y].
坑:要判断是否出界,x < 0 || x >= board.length || y < 0 || y >= board[0].length || visited[x][y]
1 class Solution { 2 public char[][] updateBoard(char[][] board, int[] click) { 3 boolean[][] visited = new boolean[board.length][board[0].length]; 4 Queue<Click> queue = new LinkedList<>(); 5 queue.offer(new Click(click[0], click[1])); 6 int[] dx = {-1,-1,-1,0,0,1,1,1}; 7 int[] dy = {-1,0,1,-1,1,-1,0,1}; 8 while (!queue.isEmpty()) { 9 Queue<Click> queue1 = new LinkedList<>(); 10 while (!queue.isEmpty()) { 11 Click top = queue.poll(); 12 int x = top.x; 13 int y = top.y; 14 if (x < 0 || x >= board.length || y < 0 || y >= board[0].length || visited[x][y]) { 15 continue; 16 } 17 visited[x][y] = true; 18 if (board[x][y] == 'M') { 19 board[x][y] = 'X'; 20 return board; 21 } 22 if (board[x][y] == 'E') { 23 int minesAdj = 0; 24 for (int i = 0; i < 8; i++) { 25 if (x+dx[i] >= 0 && x+dx[i] < board.length && y+dy[i] >= 0 && y+dy[i] < board[0].length && (board[x+dx[i]][y+dy[i]] == 'M')) { 26 minesAdj++; 27 } 28 } 29 if (minesAdj == 0) { 30 board[x][y] = 'B'; 31 for (int i = 0; i < 8; i++) { 32 queue1.add(new Click(x+dx[i], y+dy[i])); 33 } 34 } else { 35 board[x][y] = Integer.toString(minesAdj).charAt(0); 36 } 37 } 38 } 39 queue = queue1; 40 } 41 return board; 42 } 43 } 44 45 class Click { 46 int x; 47 int y; 48 public Click (int x, int y) { 49 this.x = x; 50 this.y = y; 51 } 52 }
9. Open the Lock --- 1st Not Bug Free
思路:双queue,BFS, 建立visited. 每一位都可以向左或是向右。
坑:0 向左是9!
class Solution { public int openLock(String[] deadends, String target) { if (target.equals("0000")) { return 0; } int total = 0; Set<String> dead = new HashSet<>(); for (String s : deadends) { dead.add(s); } Set<String> visited = new HashSet<>(); Queue<String> queue = new LinkedList<>(); queue.offer("0000"); while (!queue.isEmpty()) { Queue<String> queue1 = new LinkedList<>(); total++; while (!queue.isEmpty()) { String top = queue.poll(); if (visited.contains(top)) { continue; } if (dead.contains(top)) { continue; } if (top.equals(target)) { return total - 1; } visited.add(top); for (int i = 0; i < 4; i++) { char[] lockChar = top.toCharArray(); int lockVal = Character.getNumericValue(top.charAt(i)); int lockValLeft = 0; if (lockVal == 0) { lockValLeft = 9; } else { lockValLeft = (lockVal - 1) % 10; } lockChar[i] = Integer.toString(lockValLeft).charAt(0); String lockStrLeft = new String(lockChar); queue1.offer(lockStrLeft); int lockValRight = (lockVal + 1) % 10; lockChar[i] = Integer.toString(lockValRight).charAt(0); String lockStrRight = new String(lockChar); queue1.offer(lockStrRight); } } queue = queue1; } return -1; } }
10. Pacific Atlantic Water Flow --- 2nd Not Bug Free
坑:DFS时visited[x][y] 不可以是return,而应该是continue;
思路:从4条边往里面流,流动的条件要改为正好相反;
1 class Solution { 2 3 public List<int[]> pacificAtlantic(int[][] matrix) { 4 List<int[]> result = new ArrayList<int[]>(); 5 if(matrix == null || matrix.length == 0 || matrix[0].length == 0) { 6 return result; 7 } 8 boolean[][] pacific = new boolean[matrix.length][matrix[0].length]; 9 boolean[][] atlantic = new boolean[matrix.length][matrix[0].length]; 10 11 for (int i = 0; i < matrix.length; i++) { 12 solve(matrix, i, 0, pacific); 13 solve(matrix, i, matrix[0].length-1, atlantic); 14 } 15 16 for (int j = 0; j < matrix[0].length; j++) { 17 solve(matrix, 0, j, pacific); 18 solve(matrix, matrix.length-1, j, atlantic); 19 } 20 21 for (int i = 0; i < matrix.length; i++) { 22 for (int j = 0; j < matrix[0].length; j++) { 23 if (pacific[i][j] && atlantic[i][j]) { 24 result.add(new int[]{i, j}); 25 } 26 } 27 } 28 return result; 29 } 30 31 public void solve(int[][] matrix, int i, int j, boolean[][] visited) { 32 int[] dx = {-1,1,0,0}; 33 int[] dy = {0,0,-1,1}; 34 int m = matrix.length, n = matrix[0].length; 35 visited[i][j] = true; 36 for (int k = 0; k < 4; k++) { 37 int x = i + dx[k]; 38 int y = j + dy[k]; 39 if(x < 0 || y < 0 || x >= m || y >= n || visited[x][y] || matrix[i][j] > matrix[x][y]){ 40 continue; 41 } 42 solve(matrix, x, y, visited); 43 } 44 45 } 46 }
11. Binary Tree Zigzag Level Order Traversal
思路:odd的时候先right, 再left。even的时候反过来。用stack instead of queue。最后一个list为空,不要加进去。
1 class Solution { 2 public List<List<Integer>> zigzagLevelOrder(TreeNode root) { 3 Stack<TreeNode> stack1 = new Stack<>(); 4 List<List<Integer>> res = new ArrayList<>(); 5 if (root == null) return res; 6 else stack1.push(root); 7 List<Integer> initList = new ArrayList<>(); 8 initList.add(root.val); 9 res.add(initList); 10 boolean isOdd = true; 11 while (!stack1.isEmpty()) { 12 List<Integer> tmp = new ArrayList<>(); 13 Stack<TreeNode> stack2 = new Stack<>(); 14 while (!stack1.isEmpty()) { 15 TreeNode top = stack1.pop(); 16 if (isOdd) { 17 if (top.right != null) { 18 stack2.push(top.right); 19 tmp.add(top.right.val); 20 } 21 if (top.left != null) { 22 stack2.push(top.left); 23 tmp.add(top.left.val); 24 } 25 } else { 26 if (top.left != null) { 27 stack2.push(top.left); 28 tmp.add(top.left.val); 29 } 30 if (top.right != null) { 31 stack2.push(top.right); 32 tmp.add(top.right.val); 33 } 34 } 35 } 36 stack1 = stack2; 37 isOdd = !isOdd; 38 if (tmp.size() > 0) res.add(tmp); 39 } 40 return res; 41 } 42 }
Dynamic Programming
1. Coin Change --- 2nd Not Bug Free
坑:从最小的coin出发,先填充第一行,可以整除的就赋值,不能的赋值为-1.
分为选的不选。选k的时候从0出发能覆盖不选的情况,利于处理。
1 class Solution { 2 public int coinChange(int[] coins, int amount) { 3 Arrays.sort(coins); 4 int num = coins.length; 5 int[][] result = new int[num][amount+1]; 6 for (int i = 0; i < amount+1; i++) { 7 if (i % coins[0] == 0) { 8 result[0][i] = i / coins[0]; 9 } else { 10 result[0][i] = -1; 11 } 12 13 } 14 15 for (int i = 1; i < num; i++) { 16 for (int amt = 0; amt < amount+1; amt++) { 17 int index = i; 18 if (coins[index] > amt) { 19 result[i][amt] = result[i-1][amt]; 20 } else { 21 int tmp2 = Integer.MAX_VALUE; 22 for (int k = 0; k <= amt/coins[index]; k++) { 23 if (result[i-1][amt - coins[index] * k] != -1) { 24 tmp2 = Math.min(tmp2, k + result[i-1][amt - coins[index] * k]); 25 } 26 } 27 if (tmp2 != Integer.MAX_VALUE) { 28 result[i][amt] = tmp2; 29 } else { 30 result[i][amt] = -1; 31 } 32 33 } 34 } 35 36 } 37 return result[num-1][amount]; 38 } 39 40 }
2. Longest Increasing Subsequence --- 2nd Not Bug Free
思路:dp[i]代表nums[i]是sub string的最大值时候的长度,num[i]的值大于sub string里的其他值。dp[i]初始值全为1.
if nums[i] > nums[j]: dp[i] = max(dp[i], dp[j]+1),
2nd time max = 1;
1 class Solution { 2 public int lengthOfLIS(int[] nums) { 3 if (nums == null || nums.length == 0) { 4 return 0; 5 } 6 int len = nums.length; 7 int[] result = new int[len]; 8 int max = 1; 9 Arrays.fill(result,1); 10 11 for (int i = 1; i < len; i++) { 12 for (int j = 0; j < i; j++) { 13 if (nums[j] < nums[i]) { 14 result[i]= Math.max(result[i], result[j]+1); 15 } 16 } 17 max = Math.max(max, result[i]); 18 } 19 return max; 20 } 21 }
3. Longest Common Sequence --- 1st Not Bug Free
思路:if a[i] = a[j]; dp[i][j] = dp[i-1][j-1] +1 else: dp[i][j] = max(dp[i][j-1], dp[i-1][j] );
每一个元素都有取于不取两种选择,所以row + 1, col + 1.
1 public int longestCommonSubsequence(String A, String B) { 2 // write your code here 3 if (A == null || B == null || A.length() == 0 || B.length() == 0) { 4 return 0; 5 } 6 7 int m = A.length(); 8 int n = B.length(); 9 int[][] maxCommon = new int[m+1][n+1]; 10 for(int i = 0; i <= m; i ++) { 11 maxCommon[i][0] = 0; 12 } 13 for(int j = 0; j <= n; j ++) { 14 maxCommon[0][j] = 0; 15 } 16 for(int i = 1; i <= m; i ++) { 17 for(int j = 1; j <= n; j ++) { 18 if(A.charAt(i-1) == B.charAt(j-1)) { 19 maxCommon[i][j] = maxCommon[i-1][j-1] + 1; 20 } 21 else { 22 maxCommon[i][j] = Math.max(maxCommon[i][j-1], maxCommon[i-1][j]); 23 } 24 } 25 } 26 return maxCommon[m][n]; 27 }
4. Scramble String --- 1st Not Bug Free
思路一:recursive
1 class Solution { 2 public boolean isScramble(String s1, String s2) { 3 if (s1 == null || s2 == null || s1.length() != s2.length()) { 4 return false; 5 } 6 if (s1.equals(s2)) { 7 return true; 8 } 9 char[] c1 = s1.toCharArray(); 10 char[] c2 = s2.toCharArray(); 11 Arrays.sort(c1); 12 Arrays.sort(c2); 13 if (!Arrays.equals(c1, c2)) return false; 14 int len = s1.length(); 15 for (int i = 1; i < len; i++) { 16 if (isScramble(s1.substring(0,i), s2.substring(0,i)) && isScramble(s1.substring(i,len), s2.substring(i,len))) 17 return true; 18 if (isScramble(s1.substring(0,i), s2.substring(s2.length() - i)) && isScramble(s1.substring(i), s2.substring(0, s2.length() - i))) 19 return true; 20 21 } 22 return false; 23 } 24 }
思路二: DP
1 class Solution { 2 public boolean isScramble(String s1, String s2) { 3 if (s1 == null || s2 == null || s1.length() != s2.length()) { 4 return false; 5 } 6 if (s1.equals(s2)) { 7 return true; 8 } 9 char[] c1 = s1.toCharArray(); 10 char[] c2 = s2.toCharArray(); 11 Arrays.sort(c1); 12 Arrays.sort(c2); 13 int len = s1.length(); 14 boolean[][][] dp = new boolean[len][len][len+1]; 15 16 for (int i = 0; i < len; i++) { 17 for (int j = 0; j < len; j++) { 18 dp[i][j][1] = s1.charAt(i) == s2.charAt(j); 19 } 20 } 21 22 for (int l = 2; l <= len; l++) { 23 for (int i = 0; i <= len - l; i++) { 24 for (int j = 0; j <= len - l; j++) { 25 for (int k = 1; k <= l; k++) { 26 dp[i][j][l] = dp[i][j][l] || (dp[i][j][k] && dp[i+k][j+k][l-k] || dp[i][j+l-k][k] && dp[i+k][j][l-k]); 27 } 28 } 29 } 30 } 31 return dp[0][0][len]; 32 } 33 }
5. Maximum Subarray--- 1st Not Bug Free
思路:dp[i-1]是否大于零,如果小于零,dp[i] = nums[i], 否则,dp[i] = dp[i-1] + nums[i].
其他题目也可以用max来记录最大/小值
1 class Solution { 2 public int maxSubArray(int[] nums) { 3 if (nums == null || nums.length == 0) { 4 return Integer.MIN_VALUE; 5 } 6 7 int[] dp = new int[nums.length]; 8 dp[0] = nums[0]; 9 int max = nums[0]; 10 11 for (int i = 1; i < nums.length; i++) { 12 dp[i] = dp[i-1] > 0 ? dp[i-1] + nums[i] : nums[i]; 13 max = Math.max(dp[i], max); 14 } 15 return max; 16 } 17 }
6. Dungeon Game--- 2nd Not Bug Free
思路:从下往上走,如果某个值 <= 0, dp[i][j] = 1; 最后循环的条件要注意!!!
1 class Solution { 2 public int calculateMinimumHP(int[][] dungeon) { 3 int row = dungeon.length; 4 int col = dungeon[0].length; 5 6 int[][] dp = new int[row][col]; 7 dp[row-1][col-1] = 1 - dungeon[row-1][col-1]; 8 if (dp[row-1][col-1] <= 0) { 9 dp[row-1][col-1] = 1; 10 } 11 for (int j = col - 1; j > 0; j--) { 12 dp[row-1][j-1] = dp[row-1][j] - dungeon[row-1][j-1]; 13 if (dp[row-1][j-1] <= 0) { 14 dp[row-1][j-1] = 1; 15 } 16 } 17 18 for (int i = row - 1; i > 0; i--) { 19 dp[i-1][col-1] = dp[i][col-1] - dungeon[i-1][col-1]; 20 if (dp[i-1][col-1] <= 0) { 21 dp[i-1][col-1] = 1; 22 } 23 } 24 25 for (int i = row - 2; i >= 0; i--) { 26 for (int j = col - 2; j >= 0; j--) { 27 int pre = Math.min(dp[i + 1][j], dp[i][j + 1]); 28 dp[i][j] = pre - dungeon[i][j] <= 0 ? 1 : pre - dungeon[i][j]; 29 } 30 } 31 return dp[0][0]; 32 } 33 }
7. Ones and Zeroes--- 1st Not Bug Free
思路:拥有的资源和要解决的问题都从0开始. 逐步加大,直到最后,就得出答案了。
问:大问题的小问题是什么? 拥有不同的m和n,能凑出多少str。前3个str能凑多少个?前五个str能凑多少个?前十个?前n个?当strs的指针指到1时能凑多少?指到2时能凑多少?n时能凑多少?
答:自然得出dp[strs.length][m+1][n+1]
问:大问题和小问题之间的关系是什么?当dp[i][j][k]无法凑出来,自然就要看dp[i-1][j][k];
答:当dp[i][j][k]能凑出来,那就要看要i和不要i的最大值,要i的话就是dp[i-1][j - lenMN[0]][k - lenMN[1]] + 1,不要i的话就是dp[i-1][j][k].
1 class Solution { 2 public int findMaxForm(String[] strs, int m, int n) { 3 int[][][] dp = new int[strs.length+1][m+1][n+1]; 4 5 for (int i = 1; i <= strs.length; i++) { 6 for (int j = 0; j<= m; j++) { 7 for (int k = 0; k <= n; k++) { 8 int[] lenMN = get(strs[i-1]); 9 if (j == 0 && k == 0) { 10 dp[i][j][k] = 0; 11 } else if (lenMN[0] > j || lenMN[1] > k) { 12 dp[i][j][k] = dp[i-1][j][k]; 13 } else { 14 dp[i][j][k] = Math.max(dp[i-1][j-lenMN[0]][k-lenMN[1]] + 1, dp[i-1][j][k]); 15 } 16 } 17 } 18 } 19 20 return dp[strs.length][m][n]; 21 } 22 23 public int[] get(String str) { 24 int[] res = new int[2]; 25 char[] c = str.toCharArray(); 26 for (char i : c) { 27 res[i == '0' ? 0 : 1]++; 28 } 29 return res; 30 } 31 32 33 }
8. Interleaving String - 2nd Not Bug Free
思路:和其他dp不同之处是:看似有3个str,i, j, k, 但其实i+j = k, 所以2d的dp就可以搞定。
含义还是一样,前i个str1和前j个str2能否凑钱i+j个str3. 这样关系就出来了。
坑:dp[i][0] = dp[i-1][0] && s3.charAt(idx) == s1.charAt(idx);
dp[i][j] = (dp[i-1][j] && s3.charAt(i+j-1) == s1.charAt(idx1)) || (dp[i][j-1] && s3.charAt(i+j-1) == s2.charAt(idx2));
1 class Solution { 2 public boolean isInterleave(String s1, String s2, String s3) { 3 int len1 = s1.length(); 4 int len2 = s2.length(); 5 int len3 = s3.length(); 6 7 if (len1+len2 != len3) { 8 return false; 9 } 10 11 boolean[][] dp = new boolean[len1+1][len2+1]; 12 13 for (int i = 0; i <= len1; i++) { 14 for (int j = 0; j <= len2; j++) { 15 if (i == 0 && j == 0) { 16 dp[i][j] = true; 17 } else if (i == 0 ) { 18 dp[i][j] = dp[i][j-1] && s3.charAt(i+j-1) == s2.charAt(j-1); 19 } else if (j == 0) { 20 dp[i][j] = dp[i-1][j] && s3.charAt(i+j-1) == s1.charAt(i-1); 21 } else { 22 dp[i][j] = (dp[i][j-1] && (s3.charAt(i+j-1) == s2.charAt(j-1)) || (dp[i-1][j] && s3.charAt(i+j-1) == s1.charAt(i-1))); 23 } 24 } 25 } 26 27 return dp[len1][len2]; 28 } 29 }
9. House Robber II - 2nd Not Bug Free
思路:分为第一个被rob或不被rob两种情况讨论。
1 class Solution { 2 public int rob(int[] nums) { 3 if (nums == null || nums.length == 0) { 4 return 0; 5 } 6 int len = nums.length; 7 if (len == 1) { 8 return nums[0]; 9 } 10 11 int[] firstNums = new int[len-1]; 12 for (int i = 0; i < nums.length-1; i++) { 13 firstNums[i] = nums[i]; 14 } 15 int firstRobbed = helper(firstNums); 16 17 int[] secondNums = new int[len-1]; 18 for (int i = 0; i < secondNums.length; i++) { 19 secondNums[i] = nums[i+1]; 20 } 21 int firstNotRobbed = helper(secondNums); 22 return Math.max(firstRobbed, firstNotRobbed); 23 } 24 25 public int helper(int[] nums) { 26 if (nums == null || nums.length == 0) { 27 return 0; 28 } 29 int[] dp = new int[nums.length+1]; 30 dp[0] = 0; 31 dp[1] = nums[0]; 32 33 for (int i = 2; i <= nums.length; i++) { 34 int index = i - 1; 35 dp[i] = Math.max(dp[i-2]+nums[index], dp[i-1]); 36 } 37 return dp[nums.length]; 38 } 39 }
10. Maximum Subarray - 2nd Not Bug Free
思路:看dp[i-1]是否大于0
1 class Solution { 2 public int maxSubArray(int[] nums) { 3 if (nums == null || nums.length == 0) { 4 return 0; 5 } 6 if (nums.length == 1) { 7 return nums[0]; 8 } 9 int[] dp = new int[nums.length]; 10 dp[0] = nums[0]; 11 int max = nums[0]; 12 for (int i = 1; i < nums.length; i++) { 13 if (dp[i-1] >= 0) { 14 dp[i] = dp[i-1] + nums[i]; 15 } else { 16 dp[i] = nums[i]; 17 } 18 max = Math.max(dp[i], max); 19 } 20 return max; 21 } 22 }
11. Triangle - 2nd Not Bug Free
思路:dp[i][j]表示第ith行,第jth列的min sum,分情况讨论,当在最右侧,最左侧,中间来讨论。
1 class Solution { 2 public int minimumTotal(List<List<Integer>> triangle) { 3 if (triangle == null || triangle.size() == 0 || triangle.get(0).size() == 0) { 4 return 0; 5 } 6 int size = triangle.size(); 7 // ith row, jth column --> min sum 8 int[][] dp = new int[size][size]; 9 dp[0][0] = triangle.get(0).get(0); 10 11 for (int i = 1; i < size; i++) { 12 for (int j = 0; j <= i; j++) { 13 if (i == j) { 14 dp[i][j] = dp[i-1][j-1] + triangle.get(i).get(j); 15 } else { 16 if (j == 0) { 17 dp[i][j] = dp[i-1][j] + triangle.get(i).get(j); 18 } else { 19 dp[i][j] = Math.min(dp[i-1][j], dp[i-1][j-1]) + triangle.get(i).get(j); 20 } 21 } 22 } 23 } 24 int res = dp[size-1][0]; 25 for (int j = 1; j < size; j++) { 26 res = Math.min(res, dp[size-1][j]); 27 } 28 return res; 29 } 30 }
12. Distinct Subsequences - 2nd Not Bug Free
思路:dp[i][j] = dp[i-1][j-1] + dp[i][j-1] OR dp[i][j] = dp[i][j-1];
1 class Solution { 2 public int numDistinct(String s, String t) { 3 if (s == null || t == null || s.length() < t.length()) { 4 return 0; 5 } 6 if (s.length() == t.length()) { 7 return s.equals(t) ? 1 : 0; 8 } 9 int[][] dp = new int[t.length()+1][s.length()+1]; 10 11 for (int j = 0; j <= s.length(); j++) { 12 dp[0][j] = 1; 13 } 14 15 for (int i = 1; i <= t.length(); i++) { 16 for (int j = 1; j <= s.length(); j++) { 17 18 if (s.charAt(j-1) == t.charAt(i-1)) { 19 dp[i][j] = dp[i-1][j-1] + dp[i][j-1]; 20 } else { 21 dp[i][j] = dp[i][j-1]; 22 } 23 24 } 25 } 26 return dp[t.length()][s.length()]; 27 } 28 }
Tree & Graph
1. DFS Treversal
public static void preOrder(TreeNode root) { if (root == null) { return; } System.out.println(root.val); preOrder(root.left); preOrder(root.right); } public static void inOrder(TreeNode root) { if (root == null) { return; } inOrder(root.left); System.out.println(root.val); inOrder(root.right); } public static void postOrder(TreeNode root) { if (root == null) { return; } postOrder(root.left); postOrder(root.right); System.out.println(root.val); }
2. BFS Treversal
public static void solve1(TreeNode root) { Queue<TreeNode> q = new LinkedList<TreeNode>(); q.offer(root); while (!q.isEmpty()) { TreeNode top = q.poll(); System.out.printf("%d ", top.val); if (top.left != null) { q.offer(top.left); } if (top.right != null) { q.offer(top.right); } } } public static void solve2(TreeNode root) { Queue<TreeNode> q1 = new LinkedList<TreeNode>(); q1.offer(root); int level = 0; while (!q1.isEmpty()) { System.out.printf("Level %d-----", level++); Queue<TreeNode> q2 = new LinkedList<TreeNode>(); while (!q1.isEmpty()) { TreeNode top = q1.poll(); System.out.printf("%d ", top.val); if (top.left != null) { q2.offer(top.left); } if (top.right != null) { q2.offer(top.right); } } q1 = q2; System.out.printf("\n"); } }
3. Max Binary Tree Depth
public static int maxDepth(TreeNode root) { if (root == null) { return 0; } return 1 + Math.max(maxDepth(root.left), maxDepth(root.right)); }
4. Min Binary Tree Depth
public static int minDepth(TreeNode root) { if (root == null) { return 0; } int min = 1; Queue<TreeNode> q = new LinkedList<TreeNode>(); q.offer(root); while (!q.isEmpty()) { Queue<TreeNode> q2 = new LinkedList<TreeNode>(); while (!q.isEmpty()) { TreeNode top = q.poll(); if (top.left == null && top.right == null) { return min; } if (top.left != null) { q2.offer(top.left); } if (top.right != null) { q2.offer(top.right); } } q = q2; min++; } return min; } public static int minDepth(TreeNode root) { if (root == null) { return 0; } if (root.left == null && root.right == null) { return 1; } if (root.left == null && root.right != null) { return minDepth(root.right) + 1; } if (root.left != null && root.right == null) { return minDepth(root.left) + 1; } return Math.min(minDepth(root.left), minDepth(root.right)) + 1; }
5. Course Schedule - 1st Not Bug Free
1 class Solution { 2 public boolean canFinish(int numCourses, int[][] prerequisites) { 3 List<List<Integer>> list = new ArrayList<>(); 4 for (int i = 0; i < numCourses; i++) { 5 list.add(new ArrayList<Integer>()); 6 } 7 int[] preNum = new int[numCourses]; 8 for (int i = 0; i < prerequisites.length; i++) { 9 list.get(prerequisites[i][1]).add(prerequisites[i][0]); 10 preNum[prerequisites[i][0]]++; 11 } 12 // 进行n轮,应该有n个课可以上,不然就是false;如果没有prerequisites 13 // 就可以上 14 for (int i = 0; i < numCourses; i++) { 15 boolean hasCourseAva = false; 16 for (int j = 0; j < numCourses; j++) { 17 if (preNum[j] == 0) { 18 hasCourseAva = true; 19 for (int k : list.get(j)) { 20 preNum[k]--; 21 } 22 preNum[j] = -1; 23 break; 24 } 25 } 26 if (!hasCourseAva) { 27 return false; 28 } 29 } 30 return true; 31 } 32 }
6. Clone Graph - 1st Not Bug Free
思路:建立 A --> A'; B --> B'的map关系。
1 /** 2 * Definition for undirected graph. 3 * class UndirectedGraphNode { 4 * int label; 5 * List<UndirectedGraphNode> neighbors; 6 * UndirectedGraphNode(int x) { label = x; neighbors = new ArrayList<UndirectedGraphNode>(); } 7 * }; 8 */ 9 public class Solution { 10 public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) { 11 if (node == null) { 12 return null; 13 } 14 Map<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<>(); 15 UndirectedGraphNode head = new UndirectedGraphNode(node.label); 16 map.put(node, head); 17 Queue<UndirectedGraphNode> queue = new LinkedList<>(); 18 queue.add(node); 19 20 while (!queue.isEmpty()) { 21 UndirectedGraphNode top = queue.poll(); 22 for (UndirectedGraphNode neighbor : top.neighbors) { 23 if (!map.containsKey(neighbor)) { 24 queue.add(neighbor); 25 UndirectedGraphNode newneighbor = new UndirectedGraphNode(neighbor.label); 26 map.put(neighbor, newneighbor); 27 } 28 map.get(top).neighbors.add(map.get(neighbor)); 29 } 30 } 31 return head; 32 } 33 }
7. Alien Dictionary - 1st Not Bug Free
思路:和Course Schedule差不多。
1 public class Solution { 2 /** 3 * @param words: a list of words 4 * @return: a string which is correct order 5 */ 6 public String alienOrder(String[] words) { 7 // Write your code here 8 Map<Character, Integer> preNum = new HashMap<>(); 9 Map<Character, Set<Character>> map = new HashMap<>(); 10 Set<Character> alphabet = new HashSet<>(); 11 StringBuilder order = new StringBuilder(); 12 for (String s : words) { 13 char[] arr = s.toCharArray(); 14 for (char i : arr) { 15 alphabet.add(i); 16 } 17 } 18 for (Character c : alphabet) { 19 map.put(c, new HashSet<Character>()); 20 preNum.put(c, 0); 21 } 22 for (int i = 0; i < words.length-1; i++) { 23 int len = Math.min(words[i].length(), words[i+1].length()); 24 for (int j = 0; j < len; j++) { 25 if (words[i].charAt(j) != words[i+1].charAt(j)) { 26 Set<Character> old = map.get(words[i].charAt(j)); 27 old.add(words[i+1].charAt(j)); 28 map.put(words[i].charAt(j), old); 29 preNum.put(words[i+1].charAt(j), preNum.get(words[i+1].charAt(j))+1); 30 break; 31 } 32 } 33 } 34 for (int i = 0; i < alphabet.size(); i++) { 35 boolean foundHead = false; 36 for (Map.Entry<Character, Integer> entry : preNum.entrySet()) { 37 if (entry.getValue() == 0) { 38 foundHead = true; 39 order.append(entry.getKey()); 40 preNum.put(entry.getKey(), -1); 41 for (Character c : map.get(entry.getKey())) { 42 preNum.put(c, preNum.get(c)-1); 43 } 44 break; 45 } 46 } 47 if (!foundHead) { 48 return new StringBuilder().toString(); 49 } 50 } 51 return order.toString(); 52 } 53 }
8. Minimum Height Trees - 1st Not Bug Free
思路:所有的leaves一次往里面走一步,随时更新leaves。当<= 2个node时候就可以是根。
Start two pointers from both end of the path and move one step each time, until pointers meet or one step away, at the end pointers will be at those nodes which will minimize the height because we have divided the nodes evenly so height will be minimum.
1 class Solution { 2 public List<Integer> findMinHeightTrees(int n, int[][] edges) { 3 List<Integer> res = new ArrayList<>(); 4 if (n < 1) return res; 5 List<HashSet<Integer>> graph = new ArrayList<>(); 6 for (int i = 0; i < n; i++) { 7 graph.add(new HashSet<>()); 8 } 9 for (int i = 0; i < edges.length; i++) { 10 graph.get(edges[i][0]).add(edges[i][1]); 11 graph.get(edges[i][1]).add(edges[i][0]); 12 } 13 Queue<Integer> leaves = new LinkedList<>(); 14 for (int i = 0; i < n; i++) { 15 if (graph.get(i).size() <= 1) { 16 leaves.add(i); 17 } 18 } 19 while (n > 2) { 20 n -= leaves.size(); 21 Queue<Integer> newLeaves = new LinkedList<>(); 22 while (!leaves.isEmpty()) { 23 Integer leaf = leaves.poll(); 24 Integer neighbor = graph.get(leaf).iterator().next(); 25 graph.get(neighbor).remove(leaf); 26 if (graph.get(neighbor).size() == 1) { 27 newLeaves.add(neighbor); 28 } 29 } 30 leaves = newLeaves; 31 } 32 return new ArrayList<Integer>(leaves); 33 } 34 }
9. Evaluate Division - 1st Not Bug Free
思路:建立a --> b, b --> a的路径和valu hashmap。String[] 不能作为key。
List<String> rev = Arrays.asList(start, i); 建立一个set 代表visited, 防止环出现。
1 class Solution { 2 public double[] calcEquation(String[][] equations, double[] values, String[][] queries) { 3 Map<String, Set<String>> map = new HashMap<>(); 4 Map<List<String>, Double> value = new HashMap<>(); 5 for (int i = 0; i < equations.length; i++) { 6 if (map.containsKey(equations[i][0])) { 7 Set<String> old = map.get(equations[i][0]); 8 old.add(equations[i][1]); 9 map.put(equations[i][0], old); 10 } else { 11 Set<String> newSet = new HashSet<>(); 12 newSet.add(equations[i][1]); 13 map.put(equations[i][0], newSet); 14 } 15 16 if (map.containsKey(equations[i][1])) { 17 Set<String> old = map.get(equations[i][1]); 18 old.add(equations[i][0]); 19 map.put(equations[i][1], old); 20 } else { 21 Set<String> newSet = new HashSet<>(); 22 newSet.add(equations[i][0]); 23 map.put(equations[i][1],newSet); 24 } 25 List<String> rev = new ArrayList<>(); 26 rev.add(equations[i][1]); 27 rev.add(equations[i][0]); 28 value.put(Arrays.asList(equations[i]),values[i]); 29 value.put(rev, (double)1/values[i]); 30 } 31 double[] res = new double[queries.length]; 32 for (int i = 0; i < res.length; i++) { 33 Set<String> visited = new HashSet<>(); 34 res[i] = helper(map, value, queries[i][0], queries[i][1], 1, visited); 35 if (res[i] == 0) res[i] = -1.0; 36 } 37 return res; 38 } 39 40 public double helper(Map<String, Set<String>> map, Map<List<String>, Double> value, String start, String end, double tmp, Set<String> visited) { 41 if (visited.contains(start)) { 42 return 0; 43 } 44 if (!map.containsKey(start)) { 45 return -1; 46 } 47 if (start.equals(end)) { 48 return tmp; 49 } 50 visited.add(start); 51 double res = 0; 52 for (String i : map.get(start)) { 53 List<String> rev = new ArrayList<>(); 54 rev.add(start); 55 rev.add(i); 56 if (value.containsKey(rev)) { 57 double val = value.get(rev); 58 res = helper(map, value, i, end, val*tmp,visited); 59 if (res != 0) { 60 break; 61 } 62 } 63 } 64 return res; 65 } 66 }
10. Course Schedule II - 1st Not Bug Free
思路:map.put(i, new ArrayList<Integer>())
1 class Solution { 2 public int[] findOrder(int numCourses, int[][] prerequisites) { 3 Map<Integer, List<Integer>> map = new HashMap<>(); 4 for (int i = 0; i < numCourses; i++) { 5 map.put(i, new ArrayList<Integer>()); 6 } 7 int[] preNum = new int[numCourses]; 8 for (int i = 0; i < prerequisites.length; i++) { 9 List<Integer> old = map.get(prerequisites[i][1]); 10 old.add(prerequisites[i][0]); 11 map.put(prerequisites[i][1], old); 12 preNum[prerequisites[i][0]]++; 13 } 14 int[] res = new int[numCourses]; 15 int count = 0; 16 for (int i = 0; i < numCourses; i++) { 17 for (int j = 0; j < numCourses; j++) { 18 if (preNum[j] == 0) { 19 res[i] = j; 20 count++; 21 preNum[j] = -1; 22 for (int k : map.get(j)) { 23 preNum[k]--; 24 } 25 break; 26 } 27 } 28 } 29 if (count == numCourses) { 30 return res; 31 } else { 32 return new int[0]; 33 } 34 } 35 }
11. Binary Tree Preorder Traversal
思路:利用stack,先push root;接下来while loop,先pop root,然后加右子树,再左子树。
1 class Solution { 2 public List<Integer> preorderTraversal(TreeNode root) { 3 List<Integer> res = new ArrayList<>(); 4 if (root == null) { 5 return res; 6 } 7 Stack<TreeNode> stack = new Stack<>(); 8 stack.push(root); 9 while (!stack.isEmpty()) { 10 TreeNode top = stack.pop(); 11 res.add(top.val); 12 if (top.right != null) { 13 stack.push(top.right); 14 } 15 if (top.left != null) { 16 stack.push(top.left); 17 } 18 } 19 return res; 20 } 21 }
12. Binary Tree Inorder Traversal - 2nd Not Bug Free
思路:while (!stack.isEmpty() || curNode != null) 和 if (curNode!= null) {} else {}
1 /** 2 * Definition for a binary tree node. 3 * public class TreeNode { 4 * int val; 5 * TreeNode left; 6 * TreeNode right; 7 * TreeNode(int x) { val = x; } 8 * } 9 */ 10 class Solution { 11 public List<Integer> inorderTraversal(TreeNode root) { 12 List<Integer> res = new ArrayList<>(); 13 if (root == null) { 14 return res; 15 } 16 Stack<TreeNode> stack = new Stack<>(); 17 TreeNode curNode = root; 18 while (!stack.isEmpty() || curNode != null) { 19 if (curNode!= null) { 20 stack.push(curNode); 21 curNode = curNode.left; 22 } else { 23 curNode = stack.pop(); 24 res.add(curNode.val); 25 System.out.println(curNode.val); 26 curNode = curNode.right; 27 } 28 } 29 return res; 30 } 31 }
13. Binary Tree Postorder Traversal - 1st Not Bug Free
思路:画出stack的过程图,hj 得知要建立一个visited,第二次访问时才打印出来。
坑:打印时要 cur = null;
1 /** 2 * Definition for a binary tree node. 3 * public class TreeNode { 4 * int val; 5 * TreeNode left; 6 * TreeNode right; 7 * TreeNode(int x) { val = x; } 8 * visited 9 * } 10 */ 11 class Solution { 12 public List<Integer> postorderTraversal(TreeNode root) { 13 List<Integer> res = new ArrayList<>(); 14 if (root == null) { 15 return res; 16 } 17 Stack<TreeNode> stack = new Stack<>(); 18 TreeNode cur = root; 19 while (!stack.isEmpty() || cur != null) { 20 if (cur != null) { 21 stack.push(cur); 22 cur = cur.left; 23 } else { 24 cur = stack.pop(); 25 if (!cur.visited) { 26 cur.set(true); 27 stack.push(cur); 28 cur = cur.right; 29 } else { 30 res.add(cur.val); 31 cur = null; 32 } 33 } 34 } 35 return res; 36 } 37 } 38 39 public class TreeNode{ 40 int val; 41 boolean visited = false; 42 TreeNode left; 43 TreeNode right; 44 TreeNode(int x) { 45 this.val = x; 46 } 47 48 void set(boolean visited) { 49 this.visited = visited; 50 } 51 }
14. Unique Binary Search Trees - 1st Not Bug Free
思路:G(n) = G(0) * G(n-1) + G(1) * G(n-2) + … + G(n-1) * G(0)
以第0个为root,第1个为root,第2个为root,分左右两侧。
1 class Solution { 2 public int numTrees(int n) { 3 if (n == 0) { 4 return 1; 5 } 6 if (n <= 2) { 7 return n; 8 } 9 int[] dp = new int[n+1]; 10 dp[0] = 1; 11 dp[1] = 1; 12 dp[2] = 2; 13 for (int i = 3; i <=n; i++) { 14 for (int j = 1; j <= i; j++) { 15 dp[i] += dp[i-j]*dp[j-1]; 16 } 17 } 18 return dp[n]; 19 } 20 }
15. Unique Binary Search Trees II - 1st Not Bug Free
思路:in-order来帮助。第1个为root,第2,...,n个为root,分左右两侧。
1 public class Solution { 2 public List<TreeNode> generateTrees(int n) { 3 4 return genTrees(1,n); 5 } 6 7 public List<TreeNode> genTrees (int start, int end) 8 { 9 10 List<TreeNode> list = new ArrayList<TreeNode>(); 11 12 if(start>end) 13 { 14 list.add(null); 15 return list; 16 } 17 18 if(start == end){ 19 list.add(new TreeNode(start)); 20 return list; 21 } 22 23 List<TreeNode> left,right; 24 for(int i=start;i<=end;i++) 25 { 26 27 left = genTrees(start, i-1); 28 right = genTrees(i+1,end); 29 30 for(TreeNode lnode: left) 31 { 32 for(TreeNode rnode: right) 33 { 34 TreeNode root = new TreeNode(i); 35 root.left = lnode; 36 root.right = rnode; 37 list.add(root); 38 } 39 } 40 41 } 42 43 return list; 44 } 45 }
Binary Search
1. Binary Search - Not Bug Free - Bug Free
public int binarySearch(int[] nums, int target) { int start = 0; int end = nums.length - 1; while (start <= end) { int mid = (start + end)/2; if (nums[mid] == target) { return target; } if (nums[mid] > target) { end = mid - 1; } if (nums[mid] < target) { start = mid + 1; } } return -1; }
2. Binary Insert
public int binaryInsert(int[] nums, int target) { int start = 0; int end = nums.length - 1; while (start <= end) { int mid = (start + end)/2; if (nums[mid] == target) { return mid; } if (nums[mid] > target) { end = target - 1; } if (nums[mid] < target) { start = mid + 1; } } return start; }
3. Search in rotated array - Not Bug Free - Not Bug Free
坑:if-else的使用;大于,小于范围不能有空隙。
class Solution { public int search(int[] nums, int target) { if (nums.length == 0) { return -1; } int start = 0; int end = nums.length - 1; while (start <= end) { int mid = (start + end)/2; if (nums[mid] >= nums[start]) { if (nums[mid] == target) { return mid; } else if (nums[mid] > target && target >= nums[start]) { end = mid - 1; } else { start = mid + 1; } } else { if (nums[mid] == target) { return mid; } else if (nums[mid] < target && target <= nums[end]) { start = mid + 1; } else { end = mid - 1; } } } return -1; } }
4. Sqrt - Not Bug Free - New
坑:要这样写 midVal > target / midVal, 而不是这样 midVal * midVal > target, 因为int 会溢出》
思路:三个不同的区间讨论。
class Solution { public int mySqrt(int target) { if (target < 0) { return -1; } if (target == 0 || target == 1) { return target; } int start = 1; int end = target; while (start <= end) { int midVal = start + (end - start)/2; if (midVal <= target/midVal && (midVal+1) > target/(midVal+1)) { return midVal; } else if (midVal > target/midVal) { end = midVal; } else if ((midVal+1) <= target/(midVal+1)) { start = midVal + 1; } } return start; } }
5. Find Peak Element - New - Not Bug Free
坑:考虑len = 0, 1, 2等情况。
思路:nums[mid] < nums[mid+1]: start = mid+1; else end = mid-1;
6. Wood cut - New - Not Bug Free
心得:注意while loop 的条件, start 和 end 如何改变,以及返回的是start 还是 end.
7. Find Minimum in Rotated Sorted Array II - New - Not Bug Free
心得:当 nums[mid] = nums[h], h--, 相当于在去重!!!
8. Search a 2D Matrix II - New - Not Bug Free
思路:从左下角或右上角开始找.
Sort
1. Bubble Sort
public static void bubbleSort(int[] nums) { for (int i = 0; i < nums.length; i++) { boolean swapped = false; for (int j = 0; j < nums.length - 1; j++) { if (nums[j] > nums[j+1]) { swap(nums, j, j + 1); swapped = true; } if (!swapped) { return; } } }
2. Insert Sort
坑:当有 nums[j] < nums[j-1],注意for loop 的边界条件. 以及

public static void insertSort(int[] nums) { for (int i = 0; i < nums.length - 1; i++) { for (int j = i + 1; j > 0; j--) { if (nums[j] < nums[j-1]) { swap(nums, j, j - 1); swapped = true; } } } }
3. Selection Sort
public static void selectionSort(int[] nums) { for (int i = 0; i < nums.length; i++) { int min = nums[i]; int minIndex = i; for (int j = i; j < nums.length; j++) { if (min > nums[j]) { minIndex = j; min = nums[j]; } } swap(nums, i, minIndex); } }
4. Merge Sort
public static void mergeSort(int[] nums) { solveMergeSort(nums, 0, nums.length - 1); } public static void solveMergeSort(int[] nums, int start, int end) { if (start < end) { int mid = start + (end - start)/2; solveMergeSort(nums, start, mid); solveMergeSort(nums, mid + 1, end); merge(nums, start, mid, end); } } public static void merge(int[] nums, int start, int mid, int end) { int k = start; int i = start; int j = mid + 1; int[] helper = new int[nums.length]; for (int m = start; m <= end; m++) { helper[m] = nums[m]; } while (i <= mid && j <= end) { if (helper[i] < helper[j]) { nums[k++] = helper[i++]; } else { nums[k++] = helper[j++]; } } while (i <= mid) { nums[k++] = helper[i++]; } while (j <= end) { nums[k++] = helper[j++]; } }
5. Quick Sort
public static void quickSort(int[] nums) { quickSort(nums, 0, nums.length - 1); } public static void quickSort(int[] nums, int start, int end) { if (start < end) { int pivot = partition(nums, start, end); quickSort(nums, start, pivot - 1); quickSort(nums, pivot + 1, end); } } public static int partition(int[] nums, int start, int end) { int tmp = nums[start]; while (start < end) { while (start < end && nums[end] >= tmp) { end--; } nums[start] = nums[end]; while (start < end && nums[start] <= tmp) { start++; } nums[end] = nums[start]; } nums[start] = tmp; return start; }
6. Best Meeting Point - 2nd Bug Free
思路:排序之后,最左边的点减去最右边的点。直到相遇。
1 public class Solution { 2 /** 3 * @param grid: a 2D grid 4 * @return: the minimize travel distance 5 */ 6 public int minTotalDistance(int[][] grid) { 7 // Write your code here 8 List<Integer> x = new ArrayList<>(); 9 List<Integer> y = new ArrayList<>(); 10 for (int i = 0; i < grid.length; i++) { 11 for (int j = 0; j < grid[0].length; j++) { 12 if (grid[i][j] == 1) { 13 x.add(i); 14 y.add(j); 15 } 16 } 17 } 18 Collections.sort(x); 19 Collections.sort(y); 20 int i = 0; 21 int j = x.size()-1; 22 int sum = 0; 23 while (i < j) { 24 sum += x.get(j) - x.get(i); 25 sum += y.get(j) - y.get(i); 26 i++; 27 j--; 28 } 29 return sum; 30 } 31 }
7. Largest Number - 2nd Not Bug Free
思路:string a 和 string b结合看谁大。建立comprator. 首位为0时,返回0.
坑:if (strs[0].equals("0")) return "0";
1 class Solution { 2 public String largestNumber(int[] nums) { 3 if (nums == null || nums.length == 0) { 4 return ""; 5 } 6 Comparator comparator = new Comparator<String>(){ 7 public int compare(String a, String b) { 8 return (b+a).compareTo(a+b); 9 } 10 }; 11 String[] strs = new String[nums.length]; 12 for (int i = 0; i < nums.length; i++) { 13 strs[i] = String.valueOf(nums[i]); 14 } 15 Arrays.sort(strs, comparator); 16 if (strs[0].charAt(0) == '0') { 17 return "0"; 18 } 19 StringBuilder builder = new StringBuilder(); 20 for (String s : strs) { 21 builder.append(s); 22 } 23 return builder.toString(); 24 } 25 }
8. Merge Intervals - 2nd Not Bug Free
思路:先按start排序,然后看这个关系intervals.get(i+1).start <= intervals.get(i).end。最后一个元素要额外加进去。
坑:int max = Math.max(pre.end, cur.end); 最后一个元素要额外加入进去。
1 /** 2 * Definition for an interval. 3 * public class Interval { 4 * int start; 5 * int end; 6 * Interval() { start = 0; end = 0; } 7 * Interval(int s, int e) { start = s; end = e; } 8 * } 9 */ 10 class Solution { 11 public List<Interval> merge(List<Interval> intervals) { 12 Comparator comparator = new Comparator<Interval>() { 13 public int compare(Interval a, Interval b) { 14 return a.start - b.start; 15 } 16 }; 17 List<Interval> res = new ArrayList<>(); 18 if (intervals == null || intervals.size() == 0 || intervals.size() == 1) { 19 return intervals; 20 } 21 Collections.sort(intervals, comparator); 22 23 for (int i = 0; i < intervals.size()-1; i++) { 24 if (intervals.get(i+1).start <= intervals.get(i).end) { 25 Interval combine = new Interval(intervals.get(i).start, Math.max(intervals.get(i).end, intervals.get(i+1).end)); 26 intervals.set(i+1,combine); 27 } else { 28 res.add(intervals.get(i)); 29 } 30 } 31 res.add(intervals.get(intervals.size()-1)); 32 return res; 33 } 34 }
10. Maximum Gap - 2nd Bug Free
思路:桶排序的思路,每个筒只放最大和最小值,gap就是Math.max(gap, buckets.get(i).get(0)-buckets.get(prev).get(1));
1 class Solution { 2 public int maximumGap(int[] nums) { 3 if (nums.length == 0) return 0; 4 int max = nums[0]; 5 int min = nums[0]; 6 for (int i : nums) { 7 max = Math.max(i, max); 8 min = Math.min(i, min); 9 } 10 int len = (max-min)/nums.length + 1; 11 List<List<Integer>> buckets = new ArrayList<>(); 12 int bucketSize = (max-min)/len + 1; 13 for (int i = 0; i < bucketSize; i++) { 14 buckets.add(new ArrayList<>()); 15 } 16 for (int num : nums) { 17 int i = (num-min)/len; 18 if (buckets.get(i).isEmpty()) { 19 buckets.get(i).add(num); 20 buckets.get(i).add(num); 21 } else { 22 if (num < buckets.get(i).get(0)) buckets.get(i).set(0, num); 23 if (num > buckets.get(i).get(1)) buckets.get(i).set(1, num); 24 } 25 } 26 int gap = 0, prev = 0; 27 for (int i = 1; i < bucketSize; i++) { 28 if (buckets.get(i).isEmpty()) continue; 29 gap = Math.max(gap, buckets.get(i).get(0)-buckets.get(prev).get(1)); 30 prev = i; 31 } 32 return gap; 33 34 } 35 }
11. Sort elements by frequency - 1st Not Bug Free
思路:定义comparator,按freq 和 index。建立关于freq和index的hashmap。
1 // "static void main" must be defined in a public class. 2 public class Main { 3 static class Container{ 4 int val; 5 int freq; 6 int index; 7 public Container(int val, int freq, int index) { 8 this.val =val; 9 this.freq = freq; 10 this.index = index; 11 } 12 } 13 14 public static void main(String[] args) { 15 System.out.println("Hello World!"); 16 int[] arr = {2, 5, 2, 8, 5, 6, 8, 8}; 17 System.out.println(Arrays.toString(sortFrequency(arr))); 18 } 19 20 public static int[] sortFrequency(int[] arr) { 21 Map<Integer, Integer> f = new HashMap<>(); 22 Map<Integer, Integer> idx = new HashMap<>(); 23 Comparator<Container> comparator = new Comparator<Container>(){ 24 public int compare(Container a, Container b) { 25 if (a.freq != b.freq) { 26 return b.freq - a.freq; 27 } else { 28 return a.index - b.index; 29 } 30 } 31 }; 32 for (int i = 0; i < arr.length; i++) { 33 if (f.containsKey(arr[i])) { 34 f.put(arr[i], f.get(arr[i])+1); 35 } else { 36 f.put(arr[i], 1); 37 } 38 if (!idx.containsKey(arr[i])) { 39 idx.put(arr[i],i); 40 } 41 } 42 List<Container> list = new ArrayList<>(); 43 for (Map.Entry<Integer, Integer> item : f.entrySet()) { 44 list.add(new Container(item.getKey(), item.getValue(), idx.get(item.getKey()))); 45 } 46 Collections.sort(list, comparator); 47 int[] res = new int[arr.length]; 48 int total = 0; 49 for (int i = 0; i < list.size(); i++) { 50 int count = list.get(i).freq; 51 int j = 0; 52 while (j < count) { 53 res[total+j] = list.get(i).val; 54 j++; 55 } 56 total += count; 57 } 58 return res; 59 } 60 }
HashMap
1. Anagram - Not Bug Free
public class Solution { public List<String> anagrams(String[] strs) { List<String> ans = new ArrayList<>(); HashMap<String, List<String>> map = new HashMap<>(); for (String s : strs) { char[] arr = s.toCharArray(); Arrays.sort(arr); String newStr = String.valueOf(arr); if (map.containsKey(newStr)) { List<String> newList = new ArrayList<>(map.get(newStr)); newList.add(s); map.put(newStr, newList); } else { List<String> newList = new ArrayList<String>(); newList.add(s); map.put(newStr, newList); } } for (Map.Entry<String, List<String>> entry : map.entrySet()) { if (entry.getValue().size() > 1) { for (String ss : entry.getValue()) { ans.add(ss); } } } return ans; } }
2. Contiguous Array - 2nd Bug Free
思路:站在i位置上看前i-1个数的0,1差距,站在j置上看前j-1个数的0,1差距, 如果两者相等中间有j-i个0,1相等。
坑:diff长度比nums长度大1,因为要看前n个数,所以要站在n+1的位置上。
diff[i] = diff[i - 1] + (nums[i - 1] == 0 ? -1 : 1);
1 class Solution { 2 public int findMaxLength(int[] nums) { 3 int[] diff = new int[nums.length + 1]; 4 Map<Integer, Integer> map = new HashMap<>(); 5 int max = 0; 6 int sum = 0; 7 map.put(0,0); 8 for (int i = 1; i <= nums.length; i++) { 9 diff[i] = diff[i - 1] + (nums[i - 1] == 0 ? -1 : 1); 10 if (!map.containsKey(diff[i])) { 11 map.put(diff[i], i); 12 } else { 13 max = Math.max(i - map.get(diff[i]), max); 14 } 15 } 16 return max; 17 } 18 }
新解法:
1 class Solution { 2 public int findMaxLength(int[] nums) { 3 int sum = 0; 4 int res = 0; 5 Map<Integer, Integer> map = new HashMap<>(); 6 map.put(0, -1); 7 for (int i = 0; i < nums.length; i++) { 8 if (nums[i] == 0) { 9 sum++; 10 } else { 11 sum--; 12 } 13 if (map.containsKey(sum)) { 14 res = Math.max(res, i - map.get(sum)); 15 } else { 16 map.put(sum, i); 17 } 18 } 19 return res; 20 } 21 }
3. Longest Substring Without Repeating Characters - 4th Not Bug Free
思路:双指针,其实都为0,一个不动,另一个往前移动。
坑:i = Math.max(map.get(cur)+1, i);,防止i 又往回走.
1 class Solution { 2 public int lengthOfLongestSubstring(String s) { 3 char[] arr = s.toCharArray(); 4 Map<Character, Integer> map = new HashMap<>(); 5 int max = 0; 6 for (int i = 0, j = 0; j < arr.length; j++) { 7 char cur = arr[j]; 8 if (map.containsKey(cur)) { 9 i = Math.max(map.get(cur)+1, i); 10 } 11 map.put(cur, j); 12 max = Math.max(j-i+1, max); 13 } 14 return max; 15 } 16 }
思路2:int[] cache = new int[256];
坑:cache默认值为0,这个cache[cur] > 0,会导致无法第一次向前跳,所以要默认 cache[cur] = j+1;
1 class Solution { 2 public int lengthOfLongestSubstring(String s) { 3 char[] arr = s.toCharArray(); 4 int[] cache = new int[256]; 5 int max = 0; 6 for (int i = 0, j = 0; j < arr.length; j++) { 7 char cur = arr[j]; 8 if (cache[cur] > 0) { 9 i = Math.max(cache[cur], i); 10 } 11 cache[cur] = j+1; 12 max = Math.max(j-i+1, max); 13 } 14 return max; 15 } 16 }
4. Word Pattern II - 2nd Not Bug Free
坑:
1 if (map.containsKey(cur)) { 2 String curStr = map.get(cur); 3 if (!str.startsWith(curStr, idx)) return false; 4 else return helper(p, str, map, reMap, pIdx+1, idx+curStr.length()); 5 }
1 public class Solution { 2 public boolean wordPatternMatch(String pattern, String str) { 3 // write your code here 4 char[] p = pattern.toCharArray(); 5 Map<Character, String> map = new HashMap<>(); 6 Map<String, Character> reMap = new HashMap<>(); 7 return helper(p, str, map, reMap, 0, 0); 8 } 9 10 public boolean helper(char[] p, String str, Map<Character, String> map, Map<String, Character> reMap, int pIdx, int idx) { 11 if (pIdx == p.length && idx == str.length()) { 12 return true; 13 } 14 if (pIdx == p.length || idx == str.length()) { 15 return false; 16 } 17 char cur = p[pIdx]; 18 if (map.containsKey(cur)) { 19 String curStr = map.get(cur); 20 if (!str.startsWith(curStr, idx)) return false; 21 else return helper(p, str, map, reMap, pIdx+1, idx+curStr.length()); 22 } 23 for (int i = idx; i < str.length(); i++) { 24 String curStr = str.substring(idx, i+1); 25 if (reMap.containsKey(curStr)) { 26 continue; 27 } 28 map.put(cur, curStr); 29 reMap.put(curStr, cur); 30 if (helper(p, str, map, reMap, pIdx+1, i+1)) { 31 return true; 32 } 33 map.remove(cur); 34 reMap.remove(curStr); 35 } 36 return false; 37 } 38 }
5. Minimum Window Substring - 1st Not Bug Free
思路:hashmap加双指针。一个指头,一个指尾。
模板:
1 int findSubstring(string s){ 2 vector<int> map(128,0); 3 int counter; // check whether the substring is valid 4 int begin=0, end=0; //two pointers, one point to tail and one head 5 int d; //the length of substring 6 7 for() { /* initialize the hash map here */ } 8 9 while(end<s.size()){ 10 11 if(map[s[end++]]-- ?){ /* 尾巴向右移动,直到所有元素都找到 */ } 12 13 while(/* counter condition */){ 14 15 /* 头向右移动,直到有一个元素移出去了*/ 16 17 //increase begin to make it invalid/valid again 18 19 if(map[s[begin++]]++ ?){ /*modify counter here*/ } 20 } 21 22 /* update d here if finding maximum*/ 23 } 24 return d; 25 }
class Solution { public String minWindow(String s, String t) { int[] number = new int[256]; for (int i = 0; i < t.length(); i++) { char cur = t.charAt(i); number[cur]++; } int begin = 0, end = 0, head = 0; int len = Integer.MAX_VALUE; int cnt = t.length(); while (end < s.length()) { if (number[s.charAt(end)] > 0) { cnt--; } number[s.charAt(end)]--; end++; while (cnt == 0) { if (end - begin < len) { len = end - begin; head = begin; } if (number[s.charAt(begin)] == 0) { cnt++; } number[s.charAt(begin)]++; begin++; } } return len == Integer.MAX_VALUE ? "" : s.substring(head, head + len); } }
Heap
Good at maintaining a dynamic data stream, from which largest/smallest is always needed, while there is no need for sorting.
1. Merge k Sorted Lists - 2nd Not Bug Free
思路:定义一个minHeap,将所有ListNode的头加入进去,再取出时即为最小的。
再把取出元素的下一个加入heap。建立dummy node。
1 /** 2 * Definition for singly-linked list. 3 * public class ListNode { 4 * int val; 5 * ListNode next; 6 * ListNode(int x) { val = x; } 7 * } 8 */ 9 class Solution { 10 public ListNode mergeKLists(ListNode[] lists) { 11 if (lists == null || lists.length == 0) { 12 return null; 13 } 14 Comparator<ListNode> compartor = new Comparator<ListNode>() { 15 public int compare(ListNode node1, ListNode node2) { 16 return node1.val - node2.val; 17 } 18 }; 19 PriorityQueue<ListNode> minHeap = new PriorityQueue<ListNode>(lists.length, compartor); 20 for (int i = 0; i < lists.length; i++) { 21 if (lists[i] != null) { 22 minHeap.offer(lists[i]); 23 } 24 } 25 ListNode dummy = new ListNode(-1); 26 ListNode cur = dummy; 27 while (!minHeap.isEmpty()) { 28 cur.next = minHeap.poll(); 29 cur = cur.next; 30 if (cur.next != null) { 31 minHeap.offer(cur.next); 32 } 33 } 34 return dummy.next; 35 } 36 }
2. Sliding Window Maximum - 2nd Not Bug Free
思路:定义一个maxHeap,里面装K个数,每次移动窗口时要remove之前的一个元素.
1 class Solution { 2 public int[] maxSlidingWindow(int[] nums, int k) { 3 if (nums == null || nums.length == 0) { 4 return nums; 5 } 6 PriorityQueue<Integer> maxHeap = new PriorityQueue<>(k, new Comparator<Integer>(){ 7 public int compare(Integer a, Integer b) { 8 return b - a; 9 } 10 }); 11 int[] result = new int[nums.length - k + 1]; 12 for (int i = 0; i < nums.length; i++) { 13 if (i >= k) { 14 maxHeap.remove(nums[i-k]); 15 } 16 maxHeap.add(nums[i]); 17 if (maxHeap.size() == k) { 18 result[i+1-k] = maxHeap.peek(); 19 } 20 } 21 return result; 22 } 23 }
3. Kth Largest Element in an Array - 2nd Bug Free
思路:定义一个minHeap, 要是nums[i] > minHeap.peek()就用它替换minHeap的top.
1 class Solution { 2 public int findKthLargest(int[] nums, int k) { 3 PriorityQueue<Integer> minHeap = new PriorityQueue<>(k, new Comparator<Integer>() { 4 public int compare(Integer a, Integer b) { 5 return a - b; 6 } 7 }); 8 for (int i = 0; i < nums.length; i++) { 9 if (minHeap.size() < k) { 10 minHeap.add(nums[i]); 11 } else { 12 if (minHeap.peek() < nums[i]) { 13 minHeap.poll(); 14 minHeap.add(nums[i]); 15 } 16 } 17 } 18 return minHeap.peek(); 19 } 20 }
4. Find Median from Data Stream - 2nd Not Bug Free
思路:定义一个maxHeap和minHeap,把minHeap的最小值给maxHeap,若是长度差大于1,把maxHeap的最大值给minHeap。
注意,maxHeap要用负值。
1 class MedianFinder { 2 3 /** initialize your data structure here. */ 4 PriorityQueue<Integer> minHeap = new PriorityQueue<>(); 5 PriorityQueue<Integer> maxHeap = new PriorityQueue<>(); 6 public MedianFinder() { 7 8 } 9 10 public void addNum(int num) { 11 minHeap.add(num); 12 maxHeap.add(-minHeap.poll()); 13 if (maxHeap.size() - minHeap.size() > 1) { 14 minHeap.add(-maxHeap.poll()); 15 } 16 } 17 18 public double findMedian() { 19 if (maxHeap.size() == minHeap.size()) { 20 return (double)((-maxHeap.peek() + minHeap.peek())/2.0); 21 } else { 22 return -maxHeap.peek(); 23 } 24 } 25 } 26 27 /** 28 * Your MedianFinder object will be instantiated and called as such: 29 * MedianFinder obj = new MedianFinder(); 30 * obj.addNum(num); 31 * double param_2 = obj.findMedian(); 32 */
5. Top N Numbers - 1st Not Bug Free
思路:建立minHeap,每两行处理一下,注意comparator的使用.
1 public static List<Integer> topN(int[]][] nums) { 2 List<Integer> res = new ArrayList<>(); 3 PriorityQueue<Integer> minHeap = new PriorityQueue<>(n); 4 int len = nums.length; 5 int width = nums[0].length; 6 for (int i : nums[0]) { 7 minHeap.add(i); 8 } 9 for (int i = 1; i < len; i++) { 10 int[] preList = new int[width]; 11 for (int j = width-1; j >=0; j--) { 12 preList[j] = minHeap.poll(); 13 } 14 15 int[] curList = nums[i]; 16 Arrays.sort(curList); 17 int largest = curList[width-1]; 18 for (int j = 0; j < width; j++) { 19 minHeap.add(largest + preList[j]); 20 } 21 for (int j = width - 2; j >= 0; j++) { 22 for (int r = 0; r < width; r++) { 23 if (curList[j] + preList[r] < minHeap.peek()) { 24 break; 25 } 26 minHeap.poll(); 27 minHeap.add(curList[j] + preList[r]); 28 } 29 } 30 } 31 Comparator comparator = new Comparator<Integer>(){ 32 public int compare(Integer a, Integer b) { 33 return b - a; 34 } 35 }; 36 result.addAll(minHeap); 37 Collections.sort(result, comparator); 38 return result; 39 }
6. Merge K sorted arrays - 1st Not Bug Free
思路:建立minHeap,把每个array的第一个元素放进去。每取出一个元素,就把对应元素array里的下一个元素放进去。
1 public class Solution { 2 /** 3 * @param arrays: k sorted integer arrays 4 * @return: a sorted array 5 */ 6 public int[] mergekSortedArrays(int[][] arrays) { 7 // write your code here 8 Comparator<Value> compartor = new Comparator<Value>() { 9 public int compare(Value a, Value b) { 10 return a.val - b.val; 11 } 12 }; 13 int size = 0; 14 PriorityQueue<Value> minHeap = new PriorityQueue<Value>(arrays.length, compartor); 15 for (int i = 0; i < arrays.length; i++) { 16 if (arrays[i].length != 0) 17 minHeap.offer(new Value(arrays[i][0], i, 0)); 18 size += arrays[i].length; 19 } 20 int[] res = new int[size]; 21 int total = 0; 22 while (!minHeap.isEmpty()) { 23 Value top = minHeap.poll(); 24 res[total++] = top.val; 25 if (top.index2 < arrays[top.index1].length - 1) 26 minHeap.offer(new Value(arrays[top.index1][top.index2+1], top.index1, top.index2+1)); 27 } 28 return res; 29 } 30 } 31 32 class Value { 33 int val; 34 int index1; 35 int index2; 36 37 public Value(int val, int index1, int index2){ 38 this.val = val; 39 this.index1 = index1; 40 this.index2 = index2; 41 } 42 }
Math
1. Add Strings - Not Bug Free. 对string,char[] API不熟悉
Given two non-negative integers num1 and num2 represented as string, return the sum of num1 and num2.
class Solution { public String addStrings(String nums1, String nums2) { char[] str1 = nums1.toCharArray(); char[] str2 = nums2.toCharArray(); reverse(str1); reverse(str2); int len = str1.length > str2.length ? str1.length : str2.length; char[] result = new char[len]; int carry = 0; int i = 0; while (i < str1.length || i < str2.length || carry > 0) { if (i < str1.length) { carry += Character.getNumericValue(str1[i]); } if (i < str2.length) { carry += Character.getNumericValue(str2[i]); } int digit = carry%10; carry = carry/10; if (i == len) { reverse(result); return String.valueOf((char)(digit + 48)) + new String(result); } else { result[i++] = (char)(digit + 48); } } reverse(result); return new String(result); } public void reverse(char[] str) { int i = 0; int j = str.length - 1; while (i < j) { char tmp = str[i]; str[i++] = str[j]; str[j--] = tmp; } } }
坑:
class Solution { public String addStrings(String num1, String num2) { //TODO empty strings char[] arr1 = num1.toCharArray(); char[] arr2 = num2.toCharArray(); reverse(arr1); reverse(arr2); int carry = 0; // 可以用int[] array 代替,其长度最多为max(arr1, arr2) + 1, int[] 比 List<Integer>好用 List<Integer> ans = new ArrayList<>(); int i = 0; int j = 0; // 加上 || carry > 0 之后不需要下面两个循环 while (i < arr1.length || j < arr2.length) { if (i < arr1.length) { carry += Character.getNumericValue(arr1[i++]); } if (j < arr2.length) { carry += Character.getNumericValue(arr2[j++]); } int digit = carry%10; carry /= 10; ans.add(digit); } while (i < arr1.length) { carry += Character.getNumericValue(arr1[i++]); int digit = carry%10; carry /= 10; ans.add(digit); } while (j < arr2.length) { carry += Character.getNumericValue(arr2[j++]); int digit = carry%10; carry /= 10; ans.add(digit); } if (carry > 0) { ans.add(carry); } reverse(ans); String str = ""; for (int m : ans) { str += String.valueOf(m); } return str; } public void reverse(List<Integer> ans) { int i = 0; int j = ans.size() - 1; while (i < j) { int tmp = ans.get(i); ans.set(i++, ans.get(j)); ans.set(j--, tmp); } } public void reverse(char[] str) { int i = 0; int j = str.length - 1; while (i < j) { char tmp = str[i]; str[i++] = str[j]; str[j--] = tmp; } } }
2. Arranging Coins - Not Bug Free.
思路:二分法;注意防止int溢出
public class Solution { public int arrangeCoins(int n) { int start = 0; int end = n; int mid = 0; while (start <= end){ mid = start + (end - start)/2; if (0.5 * mid * (mid + 1) <= n){ start = mid + 1; } else { end = mid - 1; } } return start - 1; } }
3. Self Dividing Numbers
class Solution { public List<Integer> selfDividingNumbers(int left, int right) { List<Integer> result = new ArrayList<>(); for (int i = left; i <= right; i++) { int tmp = i; result.add(tmp); while (tmp > 0) { int digit = tmp%10; if (digit == 0 || i%digit != 0) { result.remove(result.size() - 1); break; } tmp = tmp/10; } } return result; } }
4. Palindrome Number - To be visited
自己的版本.
class Solution { public boolean isPalindrome(int x) { if (x < 0) { return false; } if (x < 10 && x >= 0) { return true; } int tmp = x; int len = 0; while (tmp > 0) { len++; tmp = tmp/10; } int left = x; int right = x; int lStart = len - 1; for (int i = 0; i <= len/2; i++) { int first = (int)(left/Math.pow(10, lStart)); left = (int)(left%Math.pow(10, lStart--)); int last = (int)(right%10); right = (int)(right/10); if (first != last) { return false; } } return true; } }
改进的版本
class Solution { public boolean isPalindrome(int x) { if (x < 0 || (x != 0 && x%10 == 0)) { return false; } int rt = 0; while (rt < x) { rt = rt * 10 + x % 10; x /= 10; } return (rt == x) || (rt / 10 == x); } }
5. Set Mismatch - To be visited
思路:所有已知从[a, b]的找missing的都可以用这个思路。本质是排序。
class Solution { public int[] findErrorNums(int[] nums) { int[] result = new int[2]; for(int i = 0; i < nums.length; i++) { while (i+1 != nums[i] && nums[i] - 1 < nums.length && nums[i] != nums[nums[i] - 1]) { swap(nums, i, nums[i] - 1); } } for (int i = 0; i < nums.length; i++) { if (nums[i] != i + 1) { result[0] = nums[i]; result[1] = i + 1; break; } } return result; } public void swap(int[] nums, int i, int j) { int tmp = nums[i]; nums[i] = nums[j]; nums[j] = tmp; } }
Bit Operations
1. Exchange two integers without using extra variable. - New
思路:异或的使用
public static void swap(int a, int b) { a = a ^ b; b = a ^ b; a = a ^ b; }
2. Return the larger integer without comparing them. - New
思路:利用a-b,考虑a-b是否会溢出. 注意判断a, b是否同符号的代码.
public static int larger(int a, int b) { int c = a - b; int signA = sign(a); int signB = sign(b); int signC = sign(c); int signDif = signA ^ signB; int signSame = flip(signDif); int cofA = signDif * signA + signC * signSame; int cofB = flip(cofA); return cofA * a + cofB * b; } public static int sign(int a) { return flip((a >> 31) ^ 0); } public static int flip(int a) { return a ^ 1; }
3. Implement +, -, *, / using bit operations. - New
Add: (a&b) << 1 不为零一直循环下去.
minus: add(a, getNeg(b));
times: a*2*b0 + a*4*b1 + a*8*b2 ... - Not Bug Free
divide: ans = add((1 << i), ans)或者 and |= (1 << i)都可以, 注意正负值. 注意当a = Integer.MIN_VALUE; (a+1)/c + (a-bc)/b; - Not Bug Free
public static int add(int a, int b) { int c = 0; int d = 0; do { c = a ^ b; d = (a & b) << 1; a = c; b = d; }while (d != 0); return c; } public static int minus(int a, int b) { return add(a, getNeg(b)); } public static int times(int a, int b) { int ans = 0; while (b != 0) { if ((b & 1) != 0) { ans = add(ans, a); } a <<= 1; b >>= 1; } return ans; } public static int divide(int a, int b) { if (b == 0) { throw new RuntimeException("divisor is 0"); } if (a == Integer.MIN_VALUE && b == Integer.MIN_VALUE) { return 1; } else if (b == Integer.MIN_VALUE) { return 0; } else if (a == Integer.MIN_VALUE) { int c = divideHelper(add(a,1),b); return add(c, divideHelper(minus(a,times(c,b)),b)); } else { return divideHelper(a, b); } } public static int divideHelper(int a, int b) { a = a < 0 ? getNeg(a) : a; b = b < 0 ? getNeg(b) : b; int ans = 0; for (int i = 31; i >= 0; i--) { if ((a >> i) < b) { continue; } else { ans = add((1 << i), ans); a = minus(a, (b << i)); } } return (a < 0) ^ (b < 0) ? ans : getNeg(ans); } public static int numberOfOnes(int a) { int ans = 0; while (a != 0) { a &= (a-1); ans++; } return ans; } public static int getNeg(int a) { return add((~a), 1); }
4. How many 1s in an integer - Not Bug Free
思路:n & (n-1)
public static int numberOfOnes(int a) { int ans = 0; while (a != 0) { a &= (a-1); ans++; } return ans; }
5. Odd occurance - Not Bug Free
思路:n & (n-1)
a ^ 0 = a; a ^ a = 0; a ^ b = b ^ a
public static int OddOccurance(int[] nums) { int ans = 0; for (int i : nums) { ans ^= i; } return ans; }
Follow up question: two numbers have odd occurance. - Not Bug Free
思路:最后异或的结果a^b不为零,肯定有一位为1,找到那一位,然后和在那位为1的数去异或,最后得到的就是其中一个数。
public static int[] twoOccurance(int[] nums) { int e0 = 0; int e1 = 0; for (int i : nums) { e0 ^= i; } int one = e0 & (~e0 + 1); for (int i : nums) { if ((i & one) != 0) { e1 ^= i; } } int [] ans = new int[2]; ans[0] = e1; ans[1] = e0 ^ e1; return ans; }
6. Occure once among other K occurance. - Not Bug Free
In K-bit system, (a_1 ^ a_2 ^ a_3 ^ ... ^ a_k)%k = 0.
思路:定义int[] e0, nums里面每一个数转化为KSystem,然后加上e0,最后剩下的数就是odd occurance. 再换成为10进制.
public static int kOccurance(int[] nums, int k) { int[] e0 = new int[32]; for (int i = 0; i < nums.length; i++) { setExclusiveOr(e0, nums[i], k); } int ans = getNumFromKSystem(e0, k); return res; } public static void setExclusiveOr(int[] e0, int val, int k) { int[] curKSystem = getKSystemNumFromNum(val, k); for (int i = 0; i < e0.length; i++) { e0[i] = (e0[i] + curKSystem[i])%k; } } public static int getKSystemNumFromNum(int val, int k) { int[] curKSystem = new int[32]; int i = 0; while (val > 0) { curKSystem[i++] = val%k; val /= k; } return curKSystem; } public static int getNumFromKSystem(int[] e0, int k) { int ans = 0; for (int i = e0.length - 1; i >= 0; i--) { ans = ans*k + e0[i]; } return asn; }
7. Flip Bits
Determine the number of bits required to flip if you want to convert integer n to integer m.
思路:先异或,1bit为different的地方,然后再求1的个数
public class Solution { public int bitSwapRequired(int m, int n) { int c = m ^ n; int ans = 0; while (c != 0) { c &= (c-1); ans++; } return ans; } }
8. Power of 2
Using O(1) time to check whether an integer n is a power of 2.
思路:利用n&(n-1)
public class Solution { public boolean checkPowerOf2(int n) { // write your code here if (n < 1) { return false; } return (n & (n-1)) == 0; } }
9. Trailing Zeros - Not Bug Free
Write an algorithm which computes the number of trailing zeros in n factorial.
2*5 can make 10. It can be broekn into product of primes. The number of 2s is equal or greater than number of 5s. Count the number of 5s.
class Solution { public int trailingZeroes(int n) { int count = 0; while(n > 0) { n /= 5; count += n; } return count; } }
10. Update Bits - Not Bug Free
Given two 32-bit numbers, N and M, and two bit positions, i and j. Write a method to set all bits between i and j in N equal to M (e g , M becomes a substring of N located at i and starting at j).
Walk backwards.
public class Solution { public int updateBits(int n, int m, int i, int j) { // write your code here int max = ~0; int left = 0; int right = 0; if (j < 31) { left = (1 << (j+1)) - 1; } else { left = max; } left = max - left; right = (1 << i) - 1; int mask = left | right; return (mask & n) | (m << i); } }
11. Fast power - Not Bug Free
Calculate the a^^n % b where a, b and n are all 32bit integers.
(a*b)%c = (a%c * b%c)%c. When n is odd, be careful.
坑:mid要为long以防溢出.
public class Solution { public int fastPower(int a, int b, int n) { // write your code here if (n == 0) { return 1%b; } if (n == 1) { return a%b; } long mid = fastPower(a, b, n/2); long ans = (mid * mid)%b; if (n%2 ==1) { ans = (a%b * ans%b)%b; } return (int)ans; } }
12. Binary Representation - Not Bug Free
Given a (decimal - e.g. 3.72) number that is passed in as a string, return the binary representation that is passed in as a string. If the fractional part of the number can not be represented accurately in binary with at most 32 characters, return ERROR.
坑:正数部分,小数部分长度均为32;
double rightVal = Double.valueOf(strs[1])/(Math.pow(10, strs[1].length()));
当right为“”时,不要‘.";
当str为"81";
小数部分先乘以2再判断.
public class Solution { public String binaryRepresentation(String str) { // write your code here String[] strs = str.split("\\."); int leftVal = Integer.valueOf(strs[0]); String left = getBinaryFromLeft(leftVal, 31); if (strs.length == 1) { return left; } double rightVal = Double.valueOf(strs[1])/(Math.pow(10, strs[1].length())); String right = getBinaryFromRight(rightVal, 31); if (left.equals("ERROR") || right.equals("ERROR")) { return "ERROR"; } if (right.equals("")) { return left; } return left + "." + right; } public String getBinaryFromLeft(int val, int maxLen) { String ans = ""; if (val == 0) { return "0"; } while (val > 0 && maxLen >= 0) { ans = String.valueOf(val%2) + ans; val /= 2; maxLen--; } if (maxLen < 0) { return "ERROR"; } else { return ans; } } public String getBinaryFromRight(double val, int maxLen) { String ans = ""; if (val == 0) { return ans; } while (val != 0 && maxLen >= 0) { val *= 2; if (val < 1 && maxLen >= 0) { ans = ans + "0"; maxLen--; } if (val >= 1 && maxLen >= 0) { ans = ans + "1"; val -= 1; maxLen--; } } if (maxLen < 0) { return "ERROR"; } else { return ans; } } }
13. Reverse Bits - 1st Not Bug Free
思路:先向左移动一位,再 | 结尾 bit。
1 public class Solution { 2 // you need treat n as an unsigned value 3 public int reverseBits(int n) { 4 int res = 0; 5 for (int i = 0; i < 32; i++) { 6 res <<= 1; 7 res |= (n & 1); 8 n >>= 1; 9 } 10 return res; 11 } 12 }
14. Single Number II - 1st Not Bug Free
思路:我们可以建立一个32位的数字,来统计每一位上1出现的个数,我们知道如果某一位上为1的话,那么如果该整数出现了三次,对3去余为0,我们把每个数的对应位都加起来对3取余,最终剩下来的那个数就是单独的数字。
1 class Solution { 2 public int singleNumber(int[] nums) { 3 int res = 0; 4 for (int i = 0; i < 32; i++) { 5 int sum = 0; 6 for (int j = 0; j < nums.length; j++) { 7 sum += (nums[j] >> i) & 1; 8 } 9 res |= ((sum%3) << i); 10 } 11 return res; 12 } 13 }
15. Single Number III - 1st Not Bug Free
思路:Once again, we need to use XOR to solve this problem. But this time, we need to do it in two passes:
In the first pass, we XOR all elements in the array, and get the XOR of the two numbers we need to find. Note that since the two numbers are distinct, so there must be a set bit (that is, the bit with value '1') in the XOR result. Find out an arbitrary set bit (for example, the rightmost set bit).
In the second pass, we divide all numbers into two groups, one with the aforementioned bit set, another with the aforementinoed bit unset. Two different numbers we need to find must fall into thte two distrinct groups. XOR numbers in each group, we can find a number in either group.
1 class Solution { 2 public int[] singleNumber(int[] nums) { 3 int diff = 0; 4 for (int i : nums) { 5 diff ^= i; 6 } 7 // find the rightmost 1-bit, which represents the different bit 8 diff = diff & (-diff); 9 int[] res = new int[2]; 10 for (int i : nums) { 11 if ((i & diff) == 0) { 12 res[0] ^= i; 13 } else { 14 res[1] ^= i; 15 } 16 } 17 return res; 18 } 19 }
16. Combination - 1st Not Bug Free
思路:比如有4个数,可以看成是1,0,1,0 代表只要第一个和第三个。bit 来做,看每一位是0还是1.
再加入对应的元素。
1 class Solution { 2 public List<List<Integer>> subsets(int[] nums) { 3 List<List<Integer>> res = new ArrayList<>(); 4 for (int i = 0; i < (1 << nums.length); i++) { 5 res.add(helper(nums, i)); 6 } 7 return res; 8 } 9 10 public List<Integer> helper(int[] nums, int index) { 11 List<Integer> items = new ArrayList<>(); 12 for (int i = 0; i < nums.length; i++) { 13 if ((1 & index) == 1) { 14 items.add(nums[i]); 15 } 16 index >>= 1; 17 } 18 return items; 19 } 20 }

浙公网安备 33010602011771号