diff --git a/code/LeetCode/src/AddTwoNumbers.java b/code/LeetCode/src/AddTwoNumbers.java index 3177ecde..e155f0f0 100644 --- a/code/LeetCode/src/AddTwoNumbers.java +++ b/code/LeetCode/src/AddTwoNumbers.java @@ -1,3 +1,5 @@ +import common.ListNode; + public class AddTwoNumbers { /* Add Two Numbers diff --git a/code/LeetCode/src/ListNode.java b/code/LeetCode/src/ListNode.java deleted file mode 100644 index a6eb17f1..00000000 --- a/code/LeetCode/src/ListNode.java +++ /dev/null @@ -1,7 +0,0 @@ -public class ListNode { - int val; - ListNode next; - ListNode(int x) { - val = x; - } -} diff --git a/code/LeetCode/src/MergeKSortedLists.java b/code/LeetCode/src/MergeKSortedLists.java index 56b74bcd..aa4f8a94 100644 --- a/code/LeetCode/src/MergeKSortedLists.java +++ b/code/LeetCode/src/MergeKSortedLists.java @@ -1,3 +1,5 @@ +import common.ListNode; + import java.util.Comparator; import java.util.PriorityQueue; diff --git a/code/LeetCode/src/RemoveNthNodeFromEndOfList.java b/code/LeetCode/src/RemoveNthNodeFromEndOfList.java index f7c5757c..799a126c 100644 --- a/code/LeetCode/src/RemoveNthNodeFromEndOfList.java +++ b/code/LeetCode/src/RemoveNthNodeFromEndOfList.java @@ -1,4 +1,4 @@ -import java.lang.reflect.Method; +import common.ListNode; public class RemoveNthNodeFromEndOfList { /* diff --git a/code/LeetCode/src/ReverseNodesInKGroup.java b/code/LeetCode/src/ReverseNodesInKGroup.java index 87054561..b8714359 100644 --- a/code/LeetCode/src/ReverseNodesInKGroup.java +++ b/code/LeetCode/src/ReverseNodesInKGroup.java @@ -1,3 +1,5 @@ +import common.ListNode; + public class ReverseNodesInKGroup { /* Reverse Nodes in k-Group diff --git a/code/LeetCode/src/SameTree.java b/code/LeetCode/src/SameTree.java index b064fdf5..c201104c 100644 --- a/code/LeetCode/src/SameTree.java +++ b/code/LeetCode/src/SameTree.java @@ -1,3 +1,6 @@ +import java.util.ArrayDeque; +import java.util.Deque; + public class SameTree { /* Same Tree @@ -51,11 +54,8 @@ public static class TreeNode { } public static boolean isSameTree(TreeNode p, TreeNode q) { - if (p == null && q == null) { - return true; - } if (p == null || q == null) { - return false; + return p == q; } if (p.val == q.val) { return isSameTree(p.left, q.left) && isSameTree(p.right, q.right); @@ -64,6 +64,54 @@ public static boolean isSameTree(TreeNode p, TreeNode q) { return false; } + public static boolean checkTreeNode(TreeNode p, TreeNode q) { + if (p == null || q == null) { + return p == q; + } + if (p.val != q.val) { + return false; + } + + return true; + } + + public static boolean isSameTreeWithIterate(TreeNode p, TreeNode q) { + if (!checkTreeNode(p, q)) { + return false; + } + Deque dequeP = new ArrayDeque<>(); + Deque dequeQ = new ArrayDeque<>(); + if (p != null) { + dequeP.push(p); + dequeQ.push(q); + } + TreeNode firstP; + TreeNode firstQ; + while (!dequeP.isEmpty()) { + firstP = dequeP.removeFirst(); + firstQ = dequeQ.removeFirst(); + if (!checkTreeNode(firstP, firstQ)) { + return false; + } + if (!checkTreeNode(firstP.left, firstQ.left)) { + return false; + } + if (firstP.left != null) { + dequeP.push(firstP.left); + dequeQ.push(firstQ.left); + } + if (!checkTreeNode(firstP.right, firstQ.right)) { + return false; + } + if (firstP.right != null) { + dequeP.push(firstP.right); + dequeQ.push(firstQ.right); + } + } + + return true; + } + diff --git a/code/LeetCode/src/String/ExcelSheetColumnNumber.java b/code/LeetCode/src/String/ExcelSheetColumnNumber.java new file mode 100644 index 00000000..18e8d3e7 --- /dev/null +++ b/code/LeetCode/src/String/ExcelSheetColumnNumber.java @@ -0,0 +1,36 @@ +package String; + +// https://leetcode.com/problems/excel-sheet-column-number/ +public class ExcelSheetColumnNumber { + + public static int titleToNumber(String s) { + int sum = 0; + char current; + int num; + int carry = 1; + int len = s.length(); + for (int i = len - 1; i >= 0; i--) { + current = s.charAt(i); + num = current - 'A' + 1; + sum = sum + num * carry; + carry *= 26; + } + + return sum; + } + + public static int titleToNumberAsc(String s) { + int result = 0; + for (int i = 0; i < s.length(); i++) { + result = result * 26 + (s.charAt(i) - 'A' + 1); + } + + return result; + } + + public static void main(String[] args) { + int sum = titleToNumberAsc("AA"); + System.out.println("sum: " + sum); + } + +} diff --git a/code/LeetCode/src/String/FirstUniqueCharacterInAString.java b/code/LeetCode/src/String/FirstUniqueCharacterInAString.java new file mode 100644 index 00000000..077b1675 --- /dev/null +++ b/code/LeetCode/src/String/FirstUniqueCharacterInAString.java @@ -0,0 +1,30 @@ +package String; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +// https://leetcode.com/problems/first-unique-character-in-a-string/ +public class FirstUniqueCharacterInAString { + + public int firstUniqChar(String s) { + // order map + HashMap map = new HashMap<>(); + int n = s.length(); + // iterate s + for (int i = 0; i < n; i++) { + Character c = s.charAt(i); + // if no repeat is 1; else count++ + map.put(c, map.getOrDefault(c, 0) + 1); + } + + for (int j = 0; j < n; j++) { + // if no repeat is 1 + if (map.get(s.charAt(j)) == 1) { + return j; + } + } + + return -1; + } +} diff --git a/code/LeetCode/src/String/ImplementStrStr.java b/code/LeetCode/src/String/ImplementStrStr.java new file mode 100644 index 00000000..cb01526e --- /dev/null +++ b/code/LeetCode/src/String/ImplementStrStr.java @@ -0,0 +1,62 @@ +package String; + +// https://leetcode.com/problems/implement-strstr/ +public class ImplementStrStr { + + public int strStr(String haystack, String needle) { + if (haystack.length() == 0 && needle.length() == 0) { + return 0; + } + if (haystack.length() == 0 || needle.length() == 0 || haystack.length() < needle.length()) { + return -1; + } + + for (int i = 0; i <= haystack.length() - needle.length(); i++) { + for (int k = 0; k < needle.length(); k++) { + if (haystack.charAt(i + k) != needle.charAt(k)) { + break; + } + + if (k == needle.length() - 1) { + return i; + } + } + } + + return -1; + } + + public int strStrWithEqual(String haystack, String needle) { + int hayLen = haystack.length(); + int needleLen = needle.length(); + if (needleLen == 0) { + return 0; + } else if (hayLen < needleLen) { + return -1; + } + int zoom = hayLen - needleLen; + for (int i = 0; i <= zoom; i++) { + if (haystack.substring(i, i + needleLen).equals(needle)) { + return i; + } + } + + return -1; + } + + public int strStrElegant(String haystack, String needle) { + for (int i = 0; ; i++) { + for (int k = 0; ; k++) { + if (k == needle.length()) { + return i; + } + if (i + k == haystack.length()) { + return -1; + } + if (haystack.charAt(i + k) != needle.charAt(k)) { + break; + } + } + } + } +} diff --git a/code/LeetCode/src/String/LetterCombinationsOfAPhoneNumber.java b/code/LeetCode/src/String/LetterCombinationsOfAPhoneNumber.java new file mode 100644 index 00000000..e4d3bcca --- /dev/null +++ b/code/LeetCode/src/String/LetterCombinationsOfAPhoneNumber.java @@ -0,0 +1,111 @@ +package String; + +import java.util.*; + +// https://leetcode.com/problems/letter-combinations-of-a-phone-number/ +public class LetterCombinationsOfAPhoneNumber { + + Map phone = new HashMap() {{ + put('2', "abc"); + put('3', "def"); + put('4', "ghi"); + put('5', "jkl"); + put('6', "mno"); + put('7', "pqrs"); + put('8', "tuv"); + put('9', "wxyz"); + }}; + + public static void main(String[] args) { + LetterCombinationsOfAPhoneNumber obj = new LetterCombinationsOfAPhoneNumber(); + obj.letterCombinationWithIterate("23"); + } + + public List letterCombinationWithIterate(String digits) { + List result = new ArrayList<>(); + if (digits == null || digits.length() == 0) { + return result; + } + + char[][] map = new char[8][]; + map[0] = "abc".toCharArray(); + map[1] = "def".toCharArray(); + map[2] = "ghi".toCharArray(); + map[3] = "jkl".toCharArray(); + map[4] = "mno".toCharArray(); + map[5] = "pqrs".toCharArray(); + map[6] = "tuv".toCharArray(); + map[7] = "wxyz".toCharArray(); + + result.add(""); + for (char digit: digits.toCharArray()) { + result = append(result, map[digit - '2']); + } + + System.out.println("result > " + Arrays.toString(result.toArray())); + + return result; + } + + private List append(List lastList, char[] charArray) { + List nextList = new ArrayList<>(); + for (String s: lastList) { + for (char c: charArray) { + nextList.add(s + c); + } + } + + return nextList; + } + + private List resultList = new ArrayList<>(); + + public List letterCombinationsWithBacktrack(String digits) { + if (digits == null || digits.length() == 0) { + return resultList; + } + backTrack("", digits); + + return resultList; + } + + public void backTrack(String combination, String nextDigits) { + if (nextDigits == null || nextDigits.length() == 0) { + resultList.add(combination); + return; + } + char c = nextDigits.charAt(0); + for (char item: phone.get(c).toCharArray()) { + backTrack(combination + item, nextDigits.substring(1)); + } + } + + + public List letterCombinations(String digits) { + // result queue + List queue = new ArrayList<>(); + if (digits == null || digits.length() == 0) { + return queue; + } + // first + queue.add(""); + int gap; + int size; + String charString; + for (char c: digits.toCharArray()) { + charString = phone.get(c); + size = queue.size(); + // iterate exist queue + for (int i = 0; i < size; i++) { + String s = queue.remove(0); + // append char + for (char phoneChar: charString.toCharArray()) { + String result = s + phoneChar; + queue.add(result); + } + } + } + + return queue; + } +} diff --git a/code/LeetCode/src/String/LongestSubstringWithoutRepeatingCharacters.java b/code/LeetCode/src/String/LongestSubstringWithoutRepeatingCharacters.java new file mode 100644 index 00000000..64a5d6e0 --- /dev/null +++ b/code/LeetCode/src/String/LongestSubstringWithoutRepeatingCharacters.java @@ -0,0 +1,84 @@ +package String; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +// https://leetcode.com/problems/longest-substring-without-repeating-characters/ +public class LongestSubstringWithoutRepeatingCharacters { + + public int lengthOfLongestSubstringWithArray(String s) { + int max = 0; + int[] array = new int[128]; + char c; + for (int i = 0, j = 0; j < s.length(); j++) { + c = s.charAt(j); + i = Math.max(array[c], i); + max = Math.max(max, (j - i + 1)); + array[c] = j + 1; + } + + return max; + } + + public int lengthOfLongestSubstringWithMap(String s) { + Map map = new HashMap<>(); + int max = 0; + char c; + for (int i = 0, j = 0; j < s.length(); j++) { + c = s.charAt(j); + if (map.containsKey(c)) { + i = Math.max(i, map.get(c)); + } + + max = Math.max(max, (j - i + 1)); + map.put(c, j + 1); + } + + return max; + } + + public int lengthOfLongestSubstringWithSet(String s) { + Set set = new HashSet<>(); + int max = 0; + int left = 0; + int right = 0; + char c; + while (right < s.length()) { + c = s.charAt(right); + if (!set.contains(c)) { + // not contain, add to set, replace max, right++ + set.add(c); + max = Math.max(max, (right - left + 1)); + right++; + } else { + // remove left item, left++ + set.remove(s.charAt(left)); + left++; + } + } + + return max; + } + + public int lengthOfLongestSubstring(String s) { + int longest = 0; + String current = ""; + for (char c : s.toCharArray()) { + if (current.indexOf(c) == -1) { + current += c; + if (current.length() > longest) { + longest = current.length(); + } + continue; + } + + int index = current.indexOf(c); + current += c; + current = current.substring(index + 1); + } + + return longest; + } +} diff --git a/code/LeetCode/src/String/ReverseString.java b/code/LeetCode/src/String/ReverseString.java new file mode 100644 index 00000000..aa8634d6 --- /dev/null +++ b/code/LeetCode/src/String/ReverseString.java @@ -0,0 +1,34 @@ +package String; + +// https://leetcode.com/problems/reverse-string/ +public class ReverseString { + public static void reverseString(char[] s) { + char c; + int len = s.length; + for (int i = 0; i < len >> 1; i++) { + c = s[i]; + s[i] = s[len - 1 - i]; + s[len - 1 - i] = c; + } + } + + public static void reverseStringWithWhile(char[] s) { + char c; + int leftIndex = 0; + int rightIndex = s.length - 1; + while (leftIndex < rightIndex) { + c = s[leftIndex]; + s[leftIndex] = s[rightIndex]; + s[rightIndex] = c; + leftIndex++; + rightIndex--; + } + } + + public static void main(String[] args) { + char[] s = {'h','e','l','l','o'}; + System.out.println(s); + reverseString(s); + System.out.println(s); + } +} diff --git a/code/LeetCode/src/String/RomanToInteger.java b/code/LeetCode/src/String/RomanToInteger.java new file mode 100644 index 00000000..607eda2b --- /dev/null +++ b/code/LeetCode/src/String/RomanToInteger.java @@ -0,0 +1,111 @@ +package String; + +import java.util.HashMap; +import java.util.Map; + +// https://leetcode.com/problems/roman-to-integer/ +public class RomanToInteger { + + public static void main(String[] args) { + String input = "IV"; + romanToInt(input); + } + + public int romanToIntWithMap(String s) { + Map charMap = new HashMap<>(); + charMap.put('I', 1); + charMap.put('V', 5); + charMap.put('X', 10); + charMap.put('L', 50); + charMap.put('C', 100); + charMap.put('D', 500); + charMap.put('M', 1000); + int pre = 0; + int sum = 0; + int current; + for (int i = s.length() - 1; i >= 0; i--) { + current = charMap.get(s.charAt(i)); + if (current >= pre) { + sum += current; + } else { + sum -= current; + } + pre = current; + } + + return sum; + } + + + public int romanToIntReverseOrder(String s) { + if (s == null || s.length() == 0) { + return -1; + } + int sum = 0; + for (int i = s.length() - 1; i >= 0; i--) { + switch (s.charAt(i)) { + case 'I': { + sum += (sum >= 5 ? -1 : 1); + break; + } + case 'V': { + sum += 5; + break; + } + case 'X': { + sum += 10 * (sum >= 50 ? -1 : 1); + break; + } + case 'L': { + sum += 50; + break; + } + case 'C': { + sum += 100 * (sum >= 500 ? -1 : 1); + break; + } + case 'D': { + sum += 500; + break; + } + case 'M': { + sum += 1000; + break; + } + } + } + + return sum; + } + + public static int romanToInt(String s) { + Map doubleMap = new HashMap<>(); + doubleMap.put("IV", 4); + doubleMap.put("IX", 9); + doubleMap.put("XL", 40); + doubleMap.put("XC", 90); + doubleMap.put("CD", 400); + doubleMap.put("CM", 900); + int sum = 0; + for (String item: doubleMap.keySet()) { + if (s.contains(item)) { + sum += doubleMap.get(item); + s = s.replace(item, ""); + } + } + + Map charMap = new HashMap<>(); + charMap.put('I', 1); + charMap.put('V', 5); + charMap.put('X', 10); + charMap.put('L', 50); + charMap.put('C', 100); + charMap.put('D', 500); + charMap.put('M', 1000); + for (char c: s.toCharArray()) { + sum += charMap.get(c); + } + + return sum; + } +} diff --git a/code/LeetCode/src/String/StringToIntegerAtoi.java b/code/LeetCode/src/String/StringToIntegerAtoi.java new file mode 100644 index 00000000..84e0c6b5 --- /dev/null +++ b/code/LeetCode/src/String/StringToIntegerAtoi.java @@ -0,0 +1,53 @@ +package String; + +// https://leetcode.com/problems/string-to-integer-atoi/ +public class StringToIntegerAtoi { + + public int myAtoi(String str) { + if (str == null || str.length() == 0) { + return 0; + } + char[] chars = str.toCharArray(); + int flag = 1; + int result = 0; + int i = 0; + int len = chars.length; + while (i < len && chars[i] == ' ') { + i++; + } + if (i < len && chars[i] == '-') { + flag = -1; + i++; + } else if (i < len && chars[i] == '+') { + flag = 1; + i++; + } + + if (i < len) { + int gap = chars[i] - '0'; + if (gap < 0 || gap > 9) { + return 0; + } + } + + int maxDevideTen = Integer.MAX_VALUE / 10; + int gap; + for (; i < len; i++) { + gap = chars[i] - '0'; + if (gap < 0 || gap > 9) { + break; + } + + if (flag == 1 && (result > maxDevideTen || (result == maxDevideTen && gap > 7))) { + return Integer.MAX_VALUE; + } else if (flag == -1 && (result > maxDevideTen || (result == maxDevideTen && gap > 8))) { + return Integer.MIN_VALUE; + } + + result = result * 10 + gap; + } + + return flag * result; + } + +} diff --git a/code/LeetCode/src/String/ValidAnagram.java b/code/LeetCode/src/String/ValidAnagram.java new file mode 100644 index 00000000..85cb76cb --- /dev/null +++ b/code/LeetCode/src/String/ValidAnagram.java @@ -0,0 +1,60 @@ +package String; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +// https://leetcode.com/problems/valid-anagram/ +public class ValidAnagram { + public boolean isAnagram(String s, String t) { + if (s.length() != t.length()) { + return false; + } + int count = 0; + Map map = new HashMap<>(); + for (char c : s.toCharArray()) { + map.put(c, map.getOrDefault(c, 0) + 1); + count++; + } + for (char c : t.toCharArray()) { + if (map.containsKey(c) && map.get(c) > 0) { + map.put(c, map.get(c) - 1); + } else { + return false; + } + count--; + } + + return count == 0; + } + + public boolean isAnagramWithSort(String s, String t) { + if (s.length() != t.length()) { + return false; + } + char[] sChars = s.toCharArray(); + char[] tChars = t.toCharArray(); + Arrays.sort(sChars); + Arrays.sort(tChars); + + return Arrays.equals(sChars, tChars); + } + + public boolean isAnagramWithChar(String s, String t) { + if (s.length() != t.length()) { + return false; + } + int[] count = new int[26]; + for (int i = 0; i < s.length(); i++) { + count[s.charAt(i) - 'a']++; + count[t.charAt(i) - 'a']--; + } + for (int i = 0; i < 26; i++) { + if (count[i] != 0) { + return false; + } + } + + return true; + } +} diff --git a/code/LeetCode/src/String/ValidPalindrome.java b/code/LeetCode/src/String/ValidPalindrome.java new file mode 100644 index 00000000..51d1d13c --- /dev/null +++ b/code/LeetCode/src/String/ValidPalindrome.java @@ -0,0 +1,41 @@ +package String; + +// https://leetcode.com/problems/valid-palindrome/ +public class ValidPalindrome { + + public static boolean isPalindrome(String s) { + if (s.isEmpty()) { + return true; + } + int head = 0, tail = s.length() - 1; + char cHead, cTail; + while(head <= tail) { + cHead = s.charAt(head); + cTail = s.charAt(tail); + if (!Character.isLetterOrDigit(cHead)) { + head++; + } else if(!Character.isLetterOrDigit(cTail)) { + tail--; + } else { + if (Character.toLowerCase(cHead) != Character.toLowerCase(cTail)) { + return false; + } + head++; + tail--; + } + } + + return true; + } + + public static boolean isPalindromeWithReverse(String s) { + String lower = s.replaceAll("[^A-Za-z0-9]", "").toLowerCase(); + String reverse = new StringBuilder(lower).reverse().toString(); + return lower.equals(reverse); + } + + + public static void main(String[] args) { + System.out.println("result: " + isPalindrome("0P")); + } +} diff --git a/code/LeetCode/src/StringToIntegerAtoi.java b/code/LeetCode/src/StringToIntegerAtoi.java index 78eae6a3..3217ca2b 100644 --- a/code/LeetCode/src/StringToIntegerAtoi.java +++ b/code/LeetCode/src/StringToIntegerAtoi.java @@ -82,30 +82,9 @@ public int myAtoni(String str) { public static void main(String[] args) { StringToIntegerAtoi obj = new StringToIntegerAtoi(); -// String input = "42"; -// int output = obj.myAtoni(input); -// String input1 = " -42"; -// int output1 = obj.myAtoni(input1); -// String input2 = "4193 with words"; -// int output2 = obj.myAtoni(input2); -// String input3 = "words and 987"; -// int output3 = obj.myAtoni(input3); -// String input4 = "-91283472332"; -// int output4 = obj.myAtoni(input4); String input5 = "-3924x8fc"; int output5 = obj.myAtoni(input5); -// String input6 = "42"; -// int output6 = obj.myAtoni(input); -// String input7 = "42"; -// int output7 = obj.myAtoni(input); -// System.out.println("input: " + input + " output: " + output); -// System.out.println("input: " + input1 + " output: " + output1); -// System.out.println("input: " + input2 + " output: " + output2); -// System.out.println("input: " + input3 + " output: " + output3); -// System.out.println("input: " + input4 + " output: " + output4); System.out.println("input: " + input5 + " output: " + output5); -// System.out.println("input: " + input6 + " output: " + output6); -// System.out.println("input: " + input7 + " output: " + output7); } diff --git a/code/LeetCode/src/SwapNodesInPairs.java b/code/LeetCode/src/SwapNodesInPairs.java index efc68cba..30f9afd3 100644 --- a/code/LeetCode/src/SwapNodesInPairs.java +++ b/code/LeetCode/src/SwapNodesInPairs.java @@ -1,3 +1,5 @@ +import common.ListNode; + public class SwapNodesInPairs { /* Swap Nodes in Pairs diff --git a/code/LeetCode/src/SymmetricTree.java b/code/LeetCode/src/SymmetricTree.java index 9e6862a2..f385abc8 100644 --- a/code/LeetCode/src/SymmetricTree.java +++ b/code/LeetCode/src/SymmetricTree.java @@ -40,10 +40,8 @@ public boolean symmetricHelper(TreeNode leftNode, TreeNode rightNode) { if (leftNode == null || rightNode == null) { return leftNode == rightNode; } - if (leftNode.val != rightNode.val) { - return false; - } - return symmetricHelper(leftNode.left, rightNode.right) && symmetricHelper(leftNode.right, rightNode.left); + + return leftNode.val == rightNode.val && symmetricHelper(leftNode.left, rightNode.right) && symmetricHelper(leftNode.right, rightNode.left); } diff --git a/code/LeetCode/src/array/ContainerWithMostWater.java b/code/LeetCode/src/array/ContainerWithMostWater.java new file mode 100644 index 00000000..f35fd95e --- /dev/null +++ b/code/LeetCode/src/array/ContainerWithMostWater.java @@ -0,0 +1,38 @@ +package array; + +import sun.security.util.Length; + +// https://leetcode.com/problems/container-with-most-water/ +public class ContainerWithMostWater { + + public int maxAreaWithTwoPointer(int[] height) { + int left = 0; + int right = height.length - 1; + int result = 0; + while (left < right) { + result = Math.max(result, Math.min(height[left], height[right]) * (right - left)); + if (height[left] < height[right]) { + left++; + } else { + right--; + } + } + + return result; + } + + public int maxArea(int[] height) { + int current; + int result = 0; + for (int i = 0; i < height.length; i++) { + for (int k = height.length - 1; k > i; k--) { + current = (k - i) * Math.min(height[k], height[i]); + if (current > result) { + result = current; + } + } + } + + return result; + } +} diff --git a/code/LeetCode/src/array/CountAndSay.java b/code/LeetCode/src/array/CountAndSay.java new file mode 100644 index 00000000..67e9a772 --- /dev/null +++ b/code/LeetCode/src/array/CountAndSay.java @@ -0,0 +1,87 @@ +package array; + +import java.awt.*; +import java.util.LinkedList; +import java.util.Queue; + +// https://leetcode.com/problems/count-and-say/ +public class CountAndSay { + public String countAndSay(int n) { + if (n == 0) { + return "1"; + } + Queue queue = new LinkedList<>(); + queue.add(1); + int size; + Integer pre = null; + int count = 1; + Integer current; + for (int i = 2; i <= n; i++) { + size = queue.size(); + for (int k = 0; k < size; k++) { + current = queue.poll(); + if (pre == current) { + count++; + } else { + if (pre != null) { + queue.add(count); + queue.add(pre); + } + + // reset date + pre = current; + count = 1; + } + } + // add last + queue.add(count); + queue.add(pre); + + // reset pre && count + pre = null; + count = 1; + } + + int l; + StringBuilder sb = new StringBuilder(); + while (!queue.isEmpty()) { + l = queue.poll(); + sb.append(Integer.toString(l)); + } + + return sb.toString(); + } + + public String countAndSayWithRecursive(int n) { + String s = "1"; + for (int i = 1; i < n; i++) { + s = countIdx(s); + } + + return s; + } + + public String countIdx(String s) { + StringBuilder sb = new StringBuilder(); + char c = s.charAt(0); + int count = 1; + for (int i = 1; i < s.length(); i++) { + if (s.charAt(i) == c) { + count++; + } else { + sb.append(count); + sb.append(c); + + c = s.charAt(i); + count = 1; + } + } + + sb.append(count); + sb.append(c); + return sb.toString(); + } + + + +} diff --git a/code/LeetCode/src/array/HouseRobber.java b/code/LeetCode/src/array/HouseRobber.java new file mode 100644 index 00000000..a128fad4 --- /dev/null +++ b/code/LeetCode/src/array/HouseRobber.java @@ -0,0 +1,108 @@ +package array; + +import java.util.Arrays; + +// https://leetcode.com/problems/house-robber/ +public class HouseRobber { + public static int rob(int[] nums) { + // back tracking + return subRob(nums, 0); + + } + + public static int subRob(int[] nums, int index) { + if (index >= nums.length) { + return 0; + } + // if select current + int sum1 = nums[index] + subRob(nums,index + 2); + // if not select current + int sum2 = subRob(nums, index + 1); + return Math.max(sum1, sum2); + } + + public static int robReverse(int[] nums) { + return subRobReverse(nums, nums.length - 1); + } + + public static int subRobReverse(int[] nums, int index) { + if (index < 0) { + return 0; + } + return Math.max(subRobReverse(nums, index - 2) + nums[index], subRobReverse(nums, index - 1)); + } + + static int[] memo; + + public static int robReverseWithMemo(int[] nums) { + memo = new int[nums.length]; + Arrays.fill(memo, -1); + + return subRobReverseWithMemo(nums, nums.length - 1); + } + + public static int subRobReverseWithMemo(int[] nums, int index) { + if (index < 0) { + return 0; + } + if (memo[index] != -1) { + return memo[index]; + } + memo[index] = Math.max(subRobReverseWithMemo(nums, index - 2) + nums[index], subRobReverseWithMemo(nums, index - 1)); + + return memo[index]; + } + + public static int robIterate(int[] nums) { + if (nums.length <= 0) { + return 0; + } + int[] memory = new int[nums.length + 1]; + memory[0] = 0; + memory[1] = nums[0]; + for (int i = 1; i < nums.length; i++) { + memory[i + 1] = Math.max(memory[i], memory[i - 1] + nums[i]); + } + + return memory[nums.length]; + } + + public static int robDP(int[] nums) { + if (nums.length <= 0) { + return 0; + } + int notRobPre = 0; + int robPre = nums[0]; + int temp; + for (int i = 1; i < nums.length; i++) { + temp = Math.max(robPre, notRobPre + nums[i]); + notRobPre = robPre; + robPre = temp; + } + + return robPre; + } + + public static int robDPStatus(int[] nums) { + int[][] dp = new int[nums.length + 1][2]; + for (int i = 1; i <= nums.length; i++) { + dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1]); + dp[i][1] = nums[i - 1] + dp[i - 1][0]; + } + + return Math.max(dp[nums.length][0], dp[nums.length][1]); + } + + public static void main(String[] args) { + int[] input = {1, 2, 3, 1}; + int result; + result = robDPStatus(input); + System.out.println("result: " + result); + input = new int[]{2, 7, 9, 3, 1}; + result = robDPStatus(input); + System.out.println("result: " + result); + input = new int[]{2, 1, 1, 2}; + result = robDPStatus(input); + System.out.println("result: " + result); + } +} diff --git a/code/LeetCode/src/array/IntersectionOfTwoArraysII.java b/code/LeetCode/src/array/IntersectionOfTwoArraysII.java new file mode 100644 index 00000000..5eab8c64 --- /dev/null +++ b/code/LeetCode/src/array/IntersectionOfTwoArraysII.java @@ -0,0 +1,32 @@ +package array; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class IntersectionOfTwoArraysII { + + public int[] intersect(int[] nums1, int[] nums2) { + Map map = new HashMap<>(); + List list = new ArrayList<>(); + for (Integer i: nums1) { + map.put(i, map.getOrDefault(i, 0) + 1); + } + + for (Integer j: nums2) { + if (map.containsKey(j) && map.get(j) > 0) { + list.add(j); + map.put(j , (map.get(j) - 1)); + } + } + + + int[] result = new int[list.size()]; + for (int i = 0; i < list.size(); i++) { + result[i] = list.get(i); + } + + return result; + } +} diff --git a/code/LeetCode/src/array/LongestCommonPrefix.java b/code/LeetCode/src/array/LongestCommonPrefix.java new file mode 100644 index 00000000..5381ed7b --- /dev/null +++ b/code/LeetCode/src/array/LongestCommonPrefix.java @@ -0,0 +1,146 @@ +package array; + +// https://leetcode.com/problems/longest-common-prefix/ +public class LongestCommonPrefix { + + public String longestCommonPrefix(String[] strs) { + // edge trecking + if (strs.length == 0) { + return ""; + } else if (strs.length == 1) { + return strs[0]; + } + // find short string + String shortString = strs[0]; + for (int i = 1; i < strs.length; i++) { + if (strs[i].length() < shortString.length()) { + shortString = strs[i]; + } + } + + StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < shortString.length(); i++) { + char c = shortString.charAt(i); + for (int k = 0; k < strs.length; k++) { + if (c != strs[k].charAt(i)) { + return sb.toString(); + } + + if (k == strs.length - 1) { + sb.append(c); + } + } + } + + return sb.toString(); + } + + public static void main(String[] args) { + String[] strs = {"flower","flow","flight"}; + longestCommonPrefixWithBinarySearch(strs); + } + + public static String longestCommonPrefixWithBinarySearch(String[] strs) { + if (strs == null || strs.length == 0) { + return ""; + } else if(strs.length == 1) { + return strs[0]; + } + int minLen = strs[0].length(); + for (int i = 1; i < strs.length; i++) { + if (strs[i].length() < minLen) { + minLen = strs[i].length(); + } + } + int left = 1; + int right = minLen; + int mid; + while (left <= right) { + mid = left + ((right - left) >> 1); + if (isCommonPre(strs, mid)) { + left = mid + 1; + } else { + right = mid - 1; + } + } + + return strs[0].substring(0, (left + ((right - left) >> 1) )); + } + + public static boolean isCommonPre(String[] strs, int len) { + String preString = strs[0].substring(0, len); + for (int i = 1; i < strs.length; i++) { + if (strs[i].indexOf(preString) != 0) { + return false; + } + } + + return true; + } + + public String longestCommonPrefixWithDivideConque(String[] strs) { + if (strs.length == 0) { + return ""; + } + + return longestCommonPrefixWithDivideConque(strs, 0, strs.length - 1); + } + + public String longestCommonPrefixWithDivideConque(String[] strs, int left, int right) { + if (left == right) { + return strs[left]; + } + + int mid = left + ((right - left) >> 1); + String commonLeft = longestCommonPrefixWithDivideConque(strs, left, mid); + String commonRight = longestCommonPrefixWithDivideConque(strs, mid + 1, right); + + return commonBetweenTwoString(commonLeft, commonRight); + } + + public String commonBetweenTwoString(String s1, String s2) { + int minLen = Math.min(s1.length(), s2.length()); + for (int i = 0; i < minLen; i++) { + if (s1.charAt(i) != s2.charAt(i)) { + return s1.substring(0, i); + } + } + + return s1.substring(0, minLen); + } + + + public String longestCommonPrefixWithVerticalScan(String[] strs) { + if (strs.length == 0) { + return ""; + } + for (int i = 0; i < strs[0].length(); i++) { + char c = strs[0].charAt(i); + for (int k = 1; k < strs.length; k++) { + if (i == strs[k].length() || c != strs[k].charAt(i)) { + return strs[0].substring(0, i); + } + } + } + + return strs[0]; + } + + public String longestCommonPrefixWithHorizontalScan(String[] strs) { + if (strs.length == 0) { + return ""; + } + String pre = strs[0]; + for (int i = 1; i < strs.length; i++) { + while (strs[i].indexOf(pre) != 0) { + pre = pre.substring(0, pre.length() - 1); + if (pre.isEmpty()) { + return ""; + } + } + } + + return pre; + } +} diff --git a/code/LeetCode/src/array/MajorityElement.java b/code/LeetCode/src/array/MajorityElement.java new file mode 100644 index 00000000..1b492754 --- /dev/null +++ b/code/LeetCode/src/array/MajorityElement.java @@ -0,0 +1,41 @@ +package array; + +import java.util.HashMap; +import java.util.Map; + +// https://leetcode.com/problems/majority-element/ +public class MajorityElement { + public static int majorityElement(int[] nums) { + Map map = new HashMap<>(); + int half = nums.length >> 1; + for (int n: nums) { + map.put(n, map.getOrDefault(n, 0) + 1); + if (map.get(n) > half) { + return n; + } + } + + return -1; + } + + public static int majorityElementWithBoyerMoorVoting(int[] nums) { + int count = 0; + // default is invalid + int candidate = -1; + for (int n: nums) { + if (count == 0) { + candidate = n; + } + count += (candidate == n ? 1 : -1); + } + + return candidate; + } + + + + public static void main(String[] args) { + int result = majorityElementWithBoyerMoorVoting(new int[]{6, 5, 5}); + System.out.println(result); + } +} diff --git a/code/LeetCode/src/array/MaximumSubarray.java b/code/LeetCode/src/array/MaximumSubarray.java new file mode 100644 index 00000000..f85a778a --- /dev/null +++ b/code/LeetCode/src/array/MaximumSubarray.java @@ -0,0 +1,33 @@ +package array; + +// https://leetcode.com/problems/maximum-subarray/ +public class MaximumSubarray { + + public int maxSubArrayWithDP(int[] nums) { + int[] dp = new int[nums.length + 1]; + dp[0] = nums[0]; + int max = dp[0]; + for (int i = 1; i < nums.length; i++) { + dp[i] = dp[i - 1] > 0 ? dp[i - 1] + nums[i] : nums[i]; + max = dp[i] > max ? dp[i] : max; + } + + return max; + } + + public int maxSubArray(int[] nums) { + if (nums.length <= 0) { + return 0; + } + int sum = 0; + int max = nums[0]; + for (int i = 0; i < nums.length; i++) { + sum = sum > 0 ? sum + nums[i] : nums[i]; + if (sum > max) { + max = sum; + } + } + + return max; + } +} diff --git a/code/LeetCode/src/array/MergeSortedArray.java b/code/LeetCode/src/array/MergeSortedArray.java new file mode 100644 index 00000000..5eddb526 --- /dev/null +++ b/code/LeetCode/src/array/MergeSortedArray.java @@ -0,0 +1,25 @@ +package array; + +// https://leetcode.com/problems/merge-sorted-array/ +public class MergeSortedArray { + public static void merge(int[] nums1, int m, int[] nums2, int n) { + int index = n + m - 1; + int oneIndex = m - 1; + int twoIndex = n - 1; + // big --> small, descending + while (oneIndex >= 0 && twoIndex >= 0) { + nums1[index--] = nums1[oneIndex] > nums2[twoIndex] ? nums1[oneIndex--] : nums2[twoIndex--]; + } + // nums2 is not empty, need to fill in; nums1 is content itself, no need to change + while (twoIndex >= 0) { + nums1[index--] = nums2[twoIndex--]; + } + } + + public static void main(String[] args) { + int[] nums1 = {2, 0}; + int[] nums2 = {1}; + + merge(nums1, 1, nums2, 1); + } +} diff --git a/code/LeetCode/src/array/MoveZeroes.java b/code/LeetCode/src/array/MoveZeroes.java new file mode 100644 index 00000000..905a77fb --- /dev/null +++ b/code/LeetCode/src/array/MoveZeroes.java @@ -0,0 +1,53 @@ +package array; + +public class MoveZeroes { + public void moveZeroes(int[] nums) { + int zeroCount = 0; + int len = nums.length; + int current; + for(int i = 0; i > generate(int numRows) { + List> result = new ArrayList<>(); + for (int i = 1; i <= numRows; i++) { + // current list + List current = new ArrayList<>(); + // pre list + List pre = i == 1 ? null : result.get(i - 1 - 1); + for (int k = 0; k < i; k++) { + if (k == 0 || k == i - 1) { + current.add(1); + } else { + current.add(pre.get(k - 1) + pre.get(k)); + } + } + + // add current list to result + result.add(current); + } + + return result; + } +} diff --git a/code/LeetCode/src/array/PlusOne.java b/code/LeetCode/src/array/PlusOne.java new file mode 100644 index 00000000..70502f77 --- /dev/null +++ b/code/LeetCode/src/array/PlusOne.java @@ -0,0 +1,53 @@ +package array; + +import java.util.ArrayList; +import java.util.List; + +// https://leetcode.com/problems/plus-one/ +public class PlusOne { + + public int[] plusOneChangeSource(int[] digits) { + int len = digits.length; + for (int i = len - 1; i >= 0; i--) { + if (digits[i] < 9) { + digits[i]++; + return digits; + } + + digits[i] = 0; + } + + int[] result = new int[len + 1]; + result[0] = 1; + + return result; + } + + public int[] plusOne(int[] digits) { + List list = new ArrayList<>(); + int carry = 1; + int sum; + for (int i = digits.length - 1; i >= 0; i--) { + if (carry == 0) { + list.add(0, digits[i]); + continue; + } + + sum = digits[i] + carry; + carry = sum / 10; + digits[i] = sum % 10; + list.add(0, digits[i]); + } + // carry is 1, add one in the first + if (carry == 1) { + list.add(0, 1); + } + + int[] result = new int[list.size()]; + for (int i = 0; i < list.size(); i++) { + result[i] = list.get(i); + } + + return result; + } +} diff --git a/code/LeetCode/src/array/RemoveDuplicatesFromSortedArray.java b/code/LeetCode/src/array/RemoveDuplicatesFromSortedArray.java new file mode 100644 index 00000000..c51a7b05 --- /dev/null +++ b/code/LeetCode/src/array/RemoveDuplicatesFromSortedArray.java @@ -0,0 +1,22 @@ +package array; + +// https://leetcode.com/problems/remove-duplicates-from-sorted-array/ +public class RemoveDuplicatesFromSortedArray { + public int removeDuplicates(int[] nums) { + if (nums.length == 0) { + return 0; + } + int current = nums[0]; + int count = 1; + + for (int i = 1; i < nums.length; i++) { + if (current != nums[i]) { + nums[count] = nums[i]; + current = nums[i]; + count++; + } + } + + return count; + } +} diff --git a/code/LeetCode/src/array/RotateArray.java b/code/LeetCode/src/array/RotateArray.java new file mode 100644 index 00000000..ea0c797b --- /dev/null +++ b/code/LeetCode/src/array/RotateArray.java @@ -0,0 +1,94 @@ +package array; + +import java.util.Arrays; + +// https://leetcode.com/problems/rotate-array/ +public class RotateArray { + public static void rotate(int[] nums, int k) { + int first; + for (int i = 0; i < k; i++) { + if (nums.length <= 0) { + return; + } + first = nums[nums.length - 1]; + for (int n = nums.length - 1; n >= 0; n--) { + nums[n] = n == 0 ? first : nums[n - 1]; + } + } + } + + public static void rotateWithStep(int[] nums, int k) { + int len = nums.length; + if (len <= 0 || k <= 0) { + return; + } + k = k % len; + int[] tempArray = new int[k]; + for (int i = 0; i < k; i++) { + tempArray[k - 1 - i] = nums[len - 1 - i]; + } + for (int n = len - 1; n > k - 1; n--) { + nums[n] = nums[n - k]; + } + for (int n = k - 1; n >= 0; n--) { + nums[n] = tempArray[n]; + } + + } + + public static void rotateWithCyclicReplacement(int[] nums, int k) { + int count = 0; + int len = nums.length; + // edge juge + if (len <= 0 || k <= 0) { + return; + } + // reduce k bigger than len; + k = k % len; + + // start nums index + for (int i = 0; count < len; i++) { + int start = i; + int prev = nums[start]; + // while step replace cycle + do { + int current = (start + k) % len; + int next = nums[current]; + nums[current] = prev; + prev = next; + start = current; + count++; + } while (start != i); + } + } + + public static void rotateWithReverse(int[] nums, int k) { + int len = nums.length; + // edge juge + if (len <= 0 || k <= 0) { + return; + } + // reduce k bigger than len; + k = k % len; + subRotateWithReverse(nums, 0, nums.length - 1); + subRotateWithReverse(nums, 0, k - 1); + subRotateWithReverse(nums, k, nums.length - 1); + } + + public static void subRotateWithReverse(int[] nums, int begin, int end) { + while (begin < end) { + int temp = nums[begin]; + nums[begin] = nums[end]; + nums[end] = temp; + begin++; + end--; + } + } + + public static void main(String[] args) { + int[] input = new int[]{1,2,3,4,5,6,7}; + System.out.println(Arrays.toString(input)); + rotateWithReverse(input, 3); + System.out.println(Arrays.toString(input)); + } +} diff --git a/code/LeetCode/src/array/RotateImage.java b/code/LeetCode/src/array/RotateImage.java new file mode 100644 index 00000000..e25677eb --- /dev/null +++ b/code/LeetCode/src/array/RotateImage.java @@ -0,0 +1,81 @@ +package array; + +// https://leetcode.com/problems/rotate-image/ +public class RotateImage { + + /** + * Given input matrix = + * [ + * [1,2,3], + * [4,5,6], + * [7,8,9] + * ], + * + * rotate the input matrix in-place such that it becomes: + * [ + * [7,4,1], + * [8,5,2], + * [9,6,3] + * ] + */ + public void rotate(int[][] matrix) { + + /* + * clockwise rotate + * first reverse up to down, then swap the symmetry + * 1 2 3 7 8 9 7 4 1 + * 4 5 6 => 4 5 6 => 8 5 2 + * 7 8 9 1 2 3 9 6 3 + */ + + // check edge + if (matrix == null || matrix.length <= 1) { + return; + } + + // step 1 > reverse up to down: i < len 2; row[i] <-> row[len - i -1] + + /* 7,8,9 + 4,5,6 + 1,2,3 + */ + int len = matrix.length; + for (int row = 0; row < len / 2; row++) { + int[] temp = matrix[row]; + int downIndex = len - 1 - row; + matrix[row]= matrix[downIndex]; + matrix[downIndex] = temp; + } + + // step 2 > swap the symmetry: row[0,len - 1], col[row, len - 1] + + /* 7,4,1 + 8,5,2 + 9,6,3 + */ + for (int row = 0; row < len; row++) { + for (int col = row + 1; col < len; col++) { + int temp = matrix[row][col]; + matrix[row][col] = matrix[col][row]; + matrix[col][row] = temp; + } + } + + } + + public void rotateWithFourPoint(int[][] matrix) { + if (matrix == null || matrix.length <= 1) { + return; + } + int len = matrix.length; + for (int row = 0; row < len / 2; row++) { + for (int col = row; col < len - 1 - row; col++) { + int temp = matrix[row][col]; + matrix[row][col] = matrix[len - 1 - col][row]; + matrix[len - 1 - col][row] = matrix[len - 1 - row][len - 1 - col]; + matrix[len - 1 - row][len - 1 - col] = matrix[col][len - 1 - row]; + matrix[col][len - 1 - row] = temp; + } + } + } +} diff --git a/code/LeetCode/src/array/SingleNumber.java b/code/LeetCode/src/array/SingleNumber.java new file mode 100644 index 00000000..b65ed79f --- /dev/null +++ b/code/LeetCode/src/array/SingleNumber.java @@ -0,0 +1,31 @@ +package array; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +// https://leetcode.com/problems/single-number/ +public class SingleNumber { + public int singleNumber(int[] nums) { + Set set = new HashSet<>(); + for (int n: nums) { + if (set.contains(n)) { + set.remove(n); + } else { + set.add(n); + } + } + + return (int)set.toArray()[0]; + } + + public int singleNumberWithBit(int[] nums) { + int result = 0; + for (int n: nums) { + result ^= n; + } + + return result; + } +} diff --git a/code/LeetCode/src/array/ThreeSum.java b/code/LeetCode/src/array/ThreeSum.java new file mode 100644 index 00000000..ae5fd592 --- /dev/null +++ b/code/LeetCode/src/array/ThreeSum.java @@ -0,0 +1,65 @@ +package array; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +// https://leetcode.com/problems/3sum/ +public class ThreeSum { + + public static void main(String[] args) { + int[] nums = {0, 0, 0, 0}; + threeSum(nums); + } + + public static List> threeSum(int[] nums) { + List> result = new ArrayList<>(); + Arrays.sort(nums); + // edge condition track + if (nums == null || nums.length < 3 || nums[0] > 0 || nums[nums.length - 1] < 0) { + return result; + } + int l, r; + int len = nums.length; + // pivot i + int i = 0; + // increase the min one + while (i < len - 2 && nums[i]+ nums[len - 1] * 2 < 0) { + i++; + } + int rightMax = len - 1; + // decrease the max one + while (i < rightMax && nums[i] * 2 + nums[rightMax] > 0) { + rightMax--; + } + + int remain; + for (; i < rightMax; i++) { + if (i - 1 >= 0 && nums[i] == nums[i - 1]) { + continue; + } + l = i + 1; + r = rightMax; + remain = 0 - nums[i]; + // shrink between l and r + while (l < r) { + if (nums[l] + nums[r] == remain) { + result.add(Arrays.asList(nums[i], nums[l], nums[r])); + while (l < r && nums[l] == nums[++l]) { + } + while (l < r && nums[r] == nums[--r]) { + } + } + while (l < r && nums[l] + nums[r] < remain) { + l++; + } + while (l < r && nums[l] + nums[r] > remain) { + r--; + } + } + + } + + return result; + } +} diff --git a/code/LeetCode/src/backtracking/AddPlusSymbol.java b/code/LeetCode/src/backtracking/AddPlusSymbol.java new file mode 100644 index 00000000..d90e0a49 --- /dev/null +++ b/code/LeetCode/src/backtracking/AddPlusSymbol.java @@ -0,0 +1,50 @@ +package backtracking; + +import java.util.ArrayList; +import java.util.List; + +public class AddPlusSymbol { + + public static void main(String[] args) { + AddPlusSymbol obj = new AddPlusSymbol(); + String input1 = "125"; + Long result1 = obj.addPlus(input1); + System.out.println("input > " + input1 + " ; result > " + result1); + String input2 = "9999999999"; + Long result2 = obj.addPlus(input2); + System.out.println("input > " + input2 + " ; result > " + result2); + } + + public long addPlus(String input) { + if (input == null || input.length() == 0) { + return 0; + } + + long result = 0; + List resultList = new ArrayList(); + char[] chars = input.toCharArray(); + // dfs + dfs(chars, resultList, "", 0); + + // loop list sum + for (String s: resultList) { + String[] nums = s.split("\\+"); + for (String n: nums) { + result += Long.parseLong(n); + } + } + + return result; + } + + private void dfs(char[] chars, List resultList, String s, int start) { + // exit + if (start == chars.length - 1) { + resultList.add(s + chars[chars.length - 1]); + return; + } + s += chars[start]; + dfs(chars, resultList, s + '+', start + 1); + dfs(chars, resultList, s, start + 1); + } +} diff --git a/code/LeetCode/src/backtracking/CombinationSum.java b/code/LeetCode/src/backtracking/CombinationSum.java new file mode 100644 index 00000000..6202aa6b --- /dev/null +++ b/code/LeetCode/src/backtracking/CombinationSum.java @@ -0,0 +1,37 @@ +package backtracking; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +// https://leetcode.com/problems/combination-sum/ +public class CombinationSum { + + public static void main(String[] args) { + CombinationSum obj = new CombinationSum(); + int[] candicates = {2, 3, 6, 7}; + int target = 7; + List> resultList = obj.combinationSum(candicates, target); + System.out.println(Arrays.toString(resultList.toArray())); + } + + public List> combinationSum(int[] candidates, int target) { + List> resultList = new ArrayList<>(); + Arrays.sort(candidates); + recursive(candidates, target, 0, new ArrayList<>(), resultList); + + return resultList; + } + + public void recursive(int[] candidates, int target, int start, List list, List> resultList) { + if (target > 0) { + for (int i = start; i < candidates.length && target >= candidates[i]; i++) { + list.add(candidates[i]); + recursive(candidates, target - candidates[i], i, list, resultList); + list.remove(list.size() - 1); + } + } else if (target == 0) { + resultList.add(new ArrayList<>(list)); + } + } +} diff --git a/code/LeetCode/src/backtracking/CombinationSumII.java b/code/LeetCode/src/backtracking/CombinationSumII.java new file mode 100644 index 00000000..c65f4bd7 --- /dev/null +++ b/code/LeetCode/src/backtracking/CombinationSumII.java @@ -0,0 +1,43 @@ +package backtracking; + +import java.util.*; + +// https://leetcode.com/problems/combination-sum-ii/ +public class CombinationSumII { + + public static void main(String[] args) { + CombinationSumII obj = new CombinationSumII(); + int[] candidates = {10,1,2,7,6,1,5}; + int target = 8; + List> resultList = obj.combinationSum2(candidates, target); + System.out.println("resultList >> " + Arrays.toString(resultList.toArray())); + } + + public List> combinationSum2(int[] candidates, int target) { + List> resultList = new ArrayList<>(); + Arrays.sort(candidates); + recursive(candidates, target, resultList, new ArrayList(), 0); + + return resultList; + } + + public void recursive(int[] candidates, int target, List> resultList, List list, int start) { + if (target == 0) { + List newList = new ArrayList(list); + + resultList.add(newList); + } else if (target > 0) { + for (int i = start; i < candidates.length && target >= candidates[i]; i++) { + /* 表示第一个数字不能跟以前相同,比如这里有两个1,那么[1, 2, 5], [1,7],就会有两个。 + * 第一次以1开头,那么第二个就要以2开头。这里需要调试就能找到规律。 + */ + if (i > start && candidates[i] == candidates[i - 1]) { + continue; + } + list.add(candidates[i]); + recursive(candidates, target - candidates[i], resultList, list, i + 1); + list.remove(list.size() - 1); + } + } + } +} diff --git a/code/LeetCode/src/backtracking/CombinationSumIII.java b/code/LeetCode/src/backtracking/CombinationSumIII.java new file mode 100644 index 00000000..b0f351da --- /dev/null +++ b/code/LeetCode/src/backtracking/CombinationSumIII.java @@ -0,0 +1,44 @@ +package backtracking; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +// https://leetcode.com/problems/combination-sum-iii/ +public class CombinationSumIII { + + public static void main(String[] args) { + int k = 3; + int n = 9; + CombinationSumIII obj = new CombinationSumIII(); + List> resultList = obj.combinationSum3(k ,n); + System.out.println(Arrays.toString(resultList.toArray())); + } + + public List> combinationSum3(int k, int n) { + List> resultList = new ArrayList>(); + // dfs + dfs(resultList, new ArrayList(), k, n, 1); + + return resultList; + } + + private void dfs(List> resultList, List list, int k, int sum, int start) { + if (sum == 0 && k == 0) { + resultList.add(new ArrayList(list)); + return; + } + if (sum < 0) { + return; + } + for (int i = start; i <= 9; i++) { + // add num + list.add(i); + dfs(resultList, list, k - 1, sum - i, i + 1); + + // not add num + list.remove(list.size() - 1); + } + } + +} diff --git a/code/LeetCode/src/backtracking/Combinations.java b/code/LeetCode/src/backtracking/Combinations.java new file mode 100644 index 00000000..526eb336 --- /dev/null +++ b/code/LeetCode/src/backtracking/Combinations.java @@ -0,0 +1,67 @@ +package backtracking; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +// https://leetcode.com/problems/combinations/ +public class Combinations { + + public static void main(String[] args) { + Combinations obj = new Combinations(); + int n = 4; + int k = 2; + List> resultList = obj.combineBaseOnFormular(n , k); + System.out.println("resultList > " + Arrays.toString(resultList.toArray())); + } + + public List> combine(int n, int k) { + List> resultList = new ArrayList>(); + if (n == 0 || k == 0) { + return resultList; + } + + // dfs + dfs(n, k, resultList, new ArrayList(), 1); + + return resultList; + } + + public void dfs(int n, int k, List> resultList, List list, int start) { + if (k == 0) { + resultList.add(new ArrayList(list)); + return; + } + + for (int i = start; i <= n - k + 1; i++) { + // [1, 2], [1, 3], [1, 4] + // [2, 3], [2, 4] + // [3, 4] + list.add(i); + dfs(n, k - 1, resultList, list, i + 1); + list.remove(list.size() - 1); + } + } + + // based on C(n,k)=C(n-1,k-1)+C(n-1,k) + public List> combineBaseOnFormular(int n, int k) { + List> resultList = new LinkedList>(); + if (n < k || k == 0) { + return resultList; + } + resultList = combineBaseOnFormular(n - 1, k - 1); + // if at this point resultList is empty, it can only be that k - 1 == 0, + // n - 1 < k - 1 is not possible since n >= k (if n < k, the function would have already returned at an early point) + if (resultList.isEmpty()) { + resultList.add(new LinkedList()); + } + for (List list: resultList) { + list.add(n); + } + + resultList.addAll(combineBaseOnFormular(n - 1, k)); + + return resultList; + } +} diff --git a/code/LeetCode/src/backtracking/EightQueens.java b/code/LeetCode/src/backtracking/EightQueens.java new file mode 100644 index 00000000..2ac79c7c --- /dev/null +++ b/code/LeetCode/src/backtracking/EightQueens.java @@ -0,0 +1,51 @@ +package backtracking; + +public class EightQueens { + + public static void main(String[] args) { + EightQueens obj = new EightQueens(); + obj.cal8queens(0); + } + + int count = 0; + int[] result = new int[8];//全局或成员变量,下标表示行,值表示queen存储在哪一列 + public void cal8queens(int row) { // 调用方式:cal8queens(0); + if (row == 8) { // 8个棋子都放置好了,打印结果 + printQueens(result); + return; // 8行棋子都放好了,已经没法再往下递归了,所以就return + } + for (int column = 0; column < 8; ++column) { // 每一行都有8中放法 + if (isOk(row, column)) { // 有些放法不满足要求 + result[row] = column; // 第row行的棋子放到了column列 + cal8queens(row+1); // 考察下一行 + } + } + } + + private boolean isOk(int row, int column) {//判断row行column列放置是否合适 + int leftup = column - 1, rightup = column + 1; + for (int i = row-1; i >= 0; --i) { // 逐行往上考察每一行 + if (result[i] == column) return false; // 第i行的column列有棋子吗? + if (leftup >= 0) { // 考察左上对角线:第i行leftup列有棋子吗? + if (result[i] == leftup) return false; + } + if (rightup < 8) { // 考察右上对角线:第i行rightup列有棋子吗? + if (result[i] == rightup) return false; + } + --leftup; ++rightup; + } + return true; + } + + private void printQueens(int[] result) { // 打印出一个二维矩阵 + System.out.println(">>>>>> solution " + (++count) + " <<<<<<<<"); + for (int row = 0; row < 8; ++row) { + for (int column = 0; column < 8; ++column) { + if (result[row] == column) System.out.print("Q "); + else System.out.print("* "); + } + System.out.println(); + } + System.out.println(); + } +} diff --git a/code/LeetCode/src/backtracking/FactorCombinations.java b/code/LeetCode/src/backtracking/FactorCombinations.java new file mode 100644 index 00000000..e4fe0f47 --- /dev/null +++ b/code/LeetCode/src/backtracking/FactorCombinations.java @@ -0,0 +1,74 @@ +package backtracking; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +// https://leetcode.com/problems/factor-combinations/ +public class FactorCombinations { + + public static void main(String[] args) { + FactorCombinations obj = new FactorCombinations(); + int n = 12; + List> resultList = obj.getFactors(12); + System.out.println(Arrays.toString(resultList.toArray())); + } + + public List> getFactors(int n) { + List> resultList = new ArrayList>(); + // DFS + //dfs(resultList, new ArrayList(), n, 2); + //dfs1(resultList, new ArrayList(), n, 2); + dfs2(resultList, new ArrayList(), n, 2); + + return resultList; + } + + private void dfs(List> resultList, List list, int n, int start) { + // exit + if (n == 1) { + if (list.size() > 1) { + resultList.add(new ArrayList(list)); + } + + return; + } + + for (int i = start; i <= n; i++) { + if (n % i == 0) { + list.add(i); + dfs(resultList, list, n / i, i); + + list.remove(list.size() - 1); + } + } + } + + + private void dfs1(List> resultList, List list, int n, int start) { + for (int i = start; i * i < n; i++) { + if (n % i == 0) { + List newList = new ArrayList(list); + newList.add(i); + dfs1(resultList, newList, n / i, i); + + newList.add(n / i); + resultList.add(newList); + } + } + } + + private void dfs2(List> resultList, List list, int n, int start) { + for (int i = start; i * i < n; i++) { + if (n % i == 0) { + list.add(i); + dfs2(resultList, list, n / i, i); + + list.add(n / i); + resultList.add(new ArrayList(list)); + list.remove(list.size() - 1); + list.remove(list.size() - 1); + } + } + } +} diff --git a/code/LeetCode/src/backtracking/GenerateParentheses.java b/code/LeetCode/src/backtracking/GenerateParentheses.java new file mode 100644 index 00000000..4549c31c --- /dev/null +++ b/code/LeetCode/src/backtracking/GenerateParentheses.java @@ -0,0 +1,41 @@ +package backtracking; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +// https://leetcode.com/problems/generate-parentheses/ +public class GenerateParentheses { + + public static void main(String[] args) { + GenerateParentheses obj = new GenerateParentheses(); + List result = obj.generateParenthesis(3); + System.out.println("result > " + Arrays.toString(result.toArray())); + } + + public List generateParenthesis(int n) { + List result = new ArrayList<>(); + if (n <= 0) { + return result; + } + + helper(result, "", n, n); + + return result; + } + + public void helper(List result, String combine, int left, int right) { + //exit + if (left == 0 && right == 0) { + result.add(combine); + return; + } + + if (left > 0) { + helper(result, combine + '(', left - 1, right); + } + if (right > left) { + helper(result, combine + ')', left, right - 1); + } + } +} diff --git a/code/LeetCode/src/backtracking/GrayCode.java b/code/LeetCode/src/backtracking/GrayCode.java new file mode 100644 index 00000000..f6005355 --- /dev/null +++ b/code/LeetCode/src/backtracking/GrayCode.java @@ -0,0 +1,24 @@ +package backtracking; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +// https://leetcode.com/problems/gray-code/ +public class GrayCode { + + public static void main(String[] args) { + GrayCode obj = new GrayCode(); + List result = obj.grayCode(2); + System.out.println(Arrays.toString(result.toArray())); + } + + public List grayCode(int n) { + List result = new ArrayList<>(); + for (int i = 0; i < (1<> 1)); + } + + return result; + } +} diff --git a/code/LeetCode/src/backtracking/LetterCombinationsOfAPhoneNumber.java b/code/LeetCode/src/backtracking/LetterCombinationsOfAPhoneNumber.java new file mode 100644 index 00000000..fbf0062b --- /dev/null +++ b/code/LeetCode/src/backtracking/LetterCombinationsOfAPhoneNumber.java @@ -0,0 +1,111 @@ +package backtracking; + +import java.util.*; + +// https://leetcode.com/problems/letter-combinations-of-a-phone-number/ +public class LetterCombinationsOfAPhoneNumber { + + Map phone = new HashMap() {{ + put('2', "abc"); + put('3', "def"); + put('4', "ghi"); + put('5', "jkl"); + put('6', "mno"); + put('7', "pqrs"); + put('8', "tuv"); + put('9', "wxyz"); + }}; + + public static void main(String[] args) { + LetterCombinationsOfAPhoneNumber obj = new LetterCombinationsOfAPhoneNumber(); + obj.letterCombinationWithIterate("23"); + } + + public List letterCombinationWithIterate(String digits) { + List result = new ArrayList<>(); + if (digits == null || digits.length() == 0) { + return result; + } + + char[][] map = new char[8][]; + map[0] = "abc".toCharArray(); + map[1] = "def".toCharArray(); + map[2] = "ghi".toCharArray(); + map[3] = "jkl".toCharArray(); + map[4] = "mno".toCharArray(); + map[5] = "pqrs".toCharArray(); + map[6] = "tuv".toCharArray(); + map[7] = "wxyz".toCharArray(); + + result.add(""); + for (char digit: digits.toCharArray()) { + result = append(result, map[digit - '2']); + } + + System.out.println("result > " + Arrays.toString(result.toArray())); + + return result; + } + + private List append(List lastList, char[] charArray) { + List nextList = new ArrayList<>(); + for (String s: lastList) { + for (char c: charArray) { + nextList.add(s + c); + } + } + + return nextList; + } + + private List resultList = new ArrayList<>(); + + public List letterCombinationsWithBacktrack(String digits) { + if (digits == null || digits.length() == 0) { + return resultList; + } + backTrack("", digits); + + return resultList; + } + + public void backTrack(String combination, String nextDigits) { + if (nextDigits == null || nextDigits.length() == 0) { + resultList.add(combination); + return; + } + char c = nextDigits.charAt(0); + for (char item: phone.get(c).toCharArray()) { + backTrack(combination + item, nextDigits.substring(1)); + } + } + + + public List letterCombinations(String digits) { + // result queue + List queue = new ArrayList<>(); + if (digits == null || digits.length() == 0) { + return queue; + } + // first + queue.add(""); + int gap; + int size; + String charString; + for (char c: digits.toCharArray()) { + charString = phone.get(c); + size = queue.size(); + // iterate exist queue + for (int i = 0; i < size; i++) { + String s = queue.remove(0); + // append char + for (char phoneChar: charString.toCharArray()) { + String result = s + phoneChar; + queue.add(result); + } + } + } + + return queue; + } +} diff --git a/code/LeetCode/src/backtracking/Package0to1.java b/code/LeetCode/src/backtracking/Package0to1.java new file mode 100644 index 00000000..41a19c53 --- /dev/null +++ b/code/LeetCode/src/backtracking/Package0to1.java @@ -0,0 +1,30 @@ +package backtracking; + +public class Package0to1 { + public int maxW = Integer.MIN_VALUE; //存储背包中物品总重量的最大值 + + public static void main(String[] args) { + Package0to1 obj = new Package0to1(); + obj.maxW = Integer.MIN_VALUE; + int[] items = {1, 10, 12, 20, 5, 6, 8, 2, 15, 16, 18}; + obj.f(0, 0, items, 10, 100); + System.out.println("max weight is " + obj.maxW); + } + + // cw表示当前已经装进去的物品的重量和;i表示考察到哪个物品了; +// w背包重量;items表示每个物品的重量;n表示物品个数 +// 假设背包可承受重量100,物品个数10,物品重量存储在数组a中,那可以这样调用函数: +// f(0, 0, a, 10, 100) + public void f(int i, int cw, int[] items, int n, int w) { + if (cw == w || i == n) { // cw==w表示装满了;i==n表示已经考察完所有的物品 + if (cw > maxW) maxW = cw; + return; + } + f(i+1, cw, items, n, w); + if (cw + items[i] <= w) {// 已经超过可以背包承受的重量的时候,就不要再装了 + f(i+1,cw + items[i], items, n, w); + } + } + + +} diff --git a/code/LeetCode/src/backtracking/PalindromePartitioning.java b/code/LeetCode/src/backtracking/PalindromePartitioning.java new file mode 100644 index 00000000..594bcbca --- /dev/null +++ b/code/LeetCode/src/backtracking/PalindromePartitioning.java @@ -0,0 +1,81 @@ +package backtracking; + +import java.util.*; + +// https://leetcode.com/problems/palindrome-partitioning/ +public class PalindromePartitioning { + + public static void main(String[] args) { + String s = "aab"; + PalindromePartitioning obj = new PalindromePartitioning(); + //List> resultList = obj.partition(s); + List> resultList = obj.partitionWithDP(s); + System.out.println(Arrays.toString(resultList.toArray())); + } + + public List> partition(String s) { + List> resultList = new ArrayList>(); + // dfs + dfs(s, 0, resultList, new ArrayList()); + + return resultList; + } + + private void dfs(String s, int start, List> resultList, List list) { + // exit + if (start >= s.length()) { + resultList.add(new ArrayList(list)); + return; + } + + // for + for (int i = start; i < s.length(); i++) { + + // isPalindrome + if (isPal(s, start, i)) { + // add + list.add(s.substring(start, i + 1)); + dfs(s, i + 1, resultList, list); + + // not add + list.remove(list.size() - 1); + } + } + } + + private boolean isPal(String s, int l, int r) { + while (l < r) { + if (s.charAt(l++) != s.charAt(r--)) { + return false; + } + } + + return true; + } + + public List> partitionWithDP(String s) { + int len = s.length(); + List>[] results = new List[len + 1]; + results[0] = new ArrayList>(); + results[0].add(new ArrayList()); + + boolean[][] pair = new boolean[len][len]; + for (int i = 0; i < len; i++) { + results[i + 1] = new ArrayList>(); + for (int left = 0; left <= i; left++) { + if (s.charAt(left) == s.charAt(i) && (i-left <= 1 || pair[left + 1][i - 1])) { + pair[left][i] = true; + String sub = s.substring(left, i + 1); + for (List list: results[left]) { + List newList = new ArrayList(list); + newList.add(sub); + results[i + 1].add(newList); + } + } + } + + } + + return results[len]; + } +} diff --git a/code/LeetCode/src/backtracking/Pattern.java b/code/LeetCode/src/backtracking/Pattern.java new file mode 100644 index 00000000..ee4746d2 --- /dev/null +++ b/code/LeetCode/src/backtracking/Pattern.java @@ -0,0 +1,45 @@ +package backtracking; + + +public class Pattern { + public static void main(String[] args) { + Pattern obj = new Pattern("*aa?b".toCharArray(), 5); + boolean result = obj.match("bbaabbc".toCharArray(), 7); + boolean result1 = obj.match("bbaabb".toCharArray(), 6); + System.out.println("bbaabbc match *aa?b > " + result); + System.out.println("bbaabb match *aa?b > " + result1); + } + + private boolean matched = false; + private char[] pattern; // 正则表达式 + private int plen; // 正则表达式长度 + + public Pattern(char[] pattern, int plen) { + this.pattern = pattern; + this.plen = plen; + } + + public boolean match(char[] text, int tlen) { // 文本串及长度 + matched = false; + rmatch(0, 0, text, tlen); + return matched; + } + + private void rmatch(int ti, int pj, char[] text, int tlen) { + if (matched) return; // 如果已经匹配了,就不要继续递归了 + if (pj == plen) { // 正则表达式到结尾了 + if (ti == tlen) matched = true; // 文本串也到结尾了 + return; + } + if (pattern[pj] == '*') { // *匹配任意个字符 + for (int k = 0; k <= tlen-ti; ++k) { + rmatch(ti+k, pj+1, text, tlen); + } + } else if (pattern[pj] == '?') { // ?匹配0个或者1个字符 + rmatch(ti, pj+1, text, tlen); + rmatch(ti+1, pj+1, text, tlen); + } else if (ti < tlen && pattern[pj] == text[ti]) { // 纯字符匹配才行 + rmatch(ti+1, pj+1, text, tlen); + } + } +} diff --git a/code/LeetCode/src/backtracking/PermutationSequence.java b/code/LeetCode/src/backtracking/PermutationSequence.java new file mode 100644 index 00000000..7b1714ba --- /dev/null +++ b/code/LeetCode/src/backtracking/PermutationSequence.java @@ -0,0 +1,50 @@ +package backtracking; + +import java.util.ArrayList; +import java.util.List; + +// https://leetcode.com/problems/permutation-sequence/ +public class PermutationSequence { + + public static void main(String[] args) { + PermutationSequence obj = new PermutationSequence(); + String result = obj.getPermutation(4, 9); + System.out.println("result > " + result); + } + + public String getPermutation(int n, int k) { + // factorial + int[] factorial = new int[n + 1]; + factorial[0] = 1; + int sum = 1; + + // create an array of factorial lookup + for (int i = 1; i <= n; i++) { + sum *= i; + // factorial[] = {1, 1, 2, 6, 24, ..., n!} + factorial[i] = sum; + } + + // create a list of numbers to get indices + List items = new ArrayList(); + for (int i = 1; i <= n; i++) { + // numbers = {1, 2, 3, 4} + items.add(i); + } + + // i from 0, so k - 1 + k--; + + StringBuilder sb = new StringBuilder(); + // calculate + for (int i = 1; i <= n; i++) { + int index = k / factorial[n - i]; + int item = items.get(index); + sb.append(String.valueOf(item)); + items.remove(index); + k -= index * factorial[n - i]; + } + + return sb.toString(); + } +} diff --git a/code/LeetCode/src/backtracking/Permutations.java b/code/LeetCode/src/backtracking/Permutations.java new file mode 100644 index 00000000..61c10190 --- /dev/null +++ b/code/LeetCode/src/backtracking/Permutations.java @@ -0,0 +1,87 @@ +package backtracking; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +// https://leetcode.com/problems/permutations/ +public class Permutations { + + public static void main(String[] args) { + Permutations obj = new Permutations(); + obj.permuteWithIterate(new int[]{1, 2, 3}); + } + + public List> permuteWithIterate(int[] nums) { + LinkedList> result = new LinkedList<>(); + result.add(new ArrayList()); + int size; + for (int n: nums) { + size = result.size(); + for (; size > 0; size--) { + List resultItem = result.pollFirst(); + for (int i = 0; i <= resultItem.size(); i++) { + List newList = new ArrayList<>(resultItem); + newList.add(i, n); + result.add(newList); + } + } + + } + + return result; + } + + public List> permute(int[] nums) { + List> result = new ArrayList>(); + if (nums == null || nums.length == 0) { + return result; + } + + // backtracking + addItemInAllPosition(nums, 0, new ArrayList(), result); + + return result; + } + + private void addItemInAllPosition(int[] nums, int start, List list, List> result) { + if (list.size() == nums.length) { + result.add(list); + return; + } + + for (int i = 0; i <= list.size(); i++) { + List newList = new ArrayList<>(list); + newList.add(i, nums[start]); + addItemInAllPosition(nums, start + 1, newList, result); + } + } + + + public List> permuteWithPickupOrNo(int[] nums) { + List> resultList = new ArrayList>(); + if (nums == null || nums.length == 0) { + return resultList; + } + + recursive(nums, new ArrayList(), resultList); + + return resultList; + } + + public void recursive(int[] nums, List list, List> resultList) { + if (list.size() == nums.length) { + resultList.add(new ArrayList(list)); + return; + } + + for(int item: nums) { + if (list.contains(item)) { + continue; + } + list.add(item); + recursive(nums, list, resultList); + list.remove(list.size() - 1); + } + } +} diff --git a/code/LeetCode/src/backtracking/PermutationsII.java b/code/LeetCode/src/backtracking/PermutationsII.java new file mode 100644 index 00000000..05f29a7e --- /dev/null +++ b/code/LeetCode/src/backtracking/PermutationsII.java @@ -0,0 +1,49 @@ +package backtracking; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +// https://leetcode.com/problems/permutations-ii/ +public class PermutationsII { + + public static void main(String[] args) { + PermutationsII obj = new PermutationsII(); + int[] input = {1,1,2}; + List> resultList = obj.permuteUnique(input); + System.out.println(Arrays.toString(resultList.toArray())); + } + + public List> permuteUnique(int[] nums) { + List> resultList = new ArrayList>(); + Arrays.sort(nums); + boolean[] used = new boolean[nums.length]; + if (nums == null || nums.length == 0) { + return resultList; + } + dfs(nums, resultList, new ArrayList(), used); + + return resultList; + } + + private void dfs(int[] nums, List> resultList, List list, boolean[] used) { + if (list.size() == nums.length) { + resultList.add(new ArrayList(list)); + return; + } + for (int i = 0; i < nums.length; i++) { + if (used[i]) { + continue; + } + if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1]) { + continue; + } + used[i] = true; + list.add(nums[i]); + dfs(nums, resultList, list, used); + used[i] = false; + list.remove(list.size() - 1); + } + } +} diff --git a/code/LeetCode/src/backtracking/PickupCards.java b/code/LeetCode/src/backtracking/PickupCards.java new file mode 100644 index 00000000..c141b2c8 --- /dev/null +++ b/code/LeetCode/src/backtracking/PickupCards.java @@ -0,0 +1,56 @@ +package backtracking; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +// https://ac.nowcoder.com/acm/contest/3286/D +public class PickupCards { + + public static void main(String[] args) { + PickupCards obj = new PickupCards(); + //int[] inputs = {7, 9, 8, 9}; + //int target = 8; + int[] inputs = {3, 6, 2, 8, 7, 6, 5, 9}; + int target = 5; + int result = obj.pickupCards(inputs, target); + + System.out.println("result > " + result); + } + + public int pickupCards(int[] inputs, int target) { + // check edges + if (inputs == null || inputs.length == 0) { + return 0; + } + List> resultList = new ArrayList>(); + Arrays.sort(inputs); + List list = new ArrayList(); + //dfs + dfs(inputs, resultList, list, 0, target); + + return resultList.size(); + } + + private void dfs(int[] inputs, List> resultList, List list, int start, int target) { + // exit condition + long sum = 0; + for (int item: list) { + sum += item; + } + if (list.size() != 0 && sum / list.size() == target && sum % list.size() == 0) { + System.out.println(Arrays.toString(list.toArray())); + resultList.add(new ArrayList(list)); + return; + } + + if (start >= inputs.length) { + return; + } + + list.add(inputs[start]); + dfs(inputs, resultList, list, start + 1, target); + list.remove(list.size() - 1); + dfs(inputs, resultList, list, start + 1, target); + } +} diff --git a/code/LeetCode/src/backtracking/RestoreIPAddress.java b/code/LeetCode/src/backtracking/RestoreIPAddress.java new file mode 100644 index 00000000..2e2ed377 --- /dev/null +++ b/code/LeetCode/src/backtracking/RestoreIPAddress.java @@ -0,0 +1,90 @@ +package backtracking; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +// https://leetcode.com/problems/restore-ip-addresses/ +public class RestoreIPAddress { + + public static void main(String[] args) { + RestoreIPAddress obj = new RestoreIPAddress(); + String s = "25525511135"; + //List resultList = obj.restoreIpAddresses(s); + List resultList = obj.restoreIpAddressesWithIterate(s); + System.out.println(Arrays.toString(resultList.toArray())); + } + + public List restoreIpAddresses(String s) { + List resultList = new ArrayList(); + if (s == null || s.length() < 4) { + return resultList; + } + + // DFS + dfs(resultList, s, 0, "", 0); + + return resultList; + } + + private void dfs(List resultList, String s, int start, String stored, int count) { + //exit + if (start == s.length() && count == 4) { + resultList.add(stored); + } + + if (start >= s.length() || count == 4) { + return; + } + + for (int i = 1; i < 4; i++) { + if (start + i > s.length()) { + break; + } + String part = s.substring(start, start + i); + if ((part.startsWith("0") && part.length() > 1) || (i == 3 && Integer.valueOf(part) > 255)) { + continue; + } + dfs(resultList, s, start + i, stored + part + (count == 3 ? "" : "."), count + 1); + } + } + + + public List restoreIpAddressesWithIterate(String s) { + List resultList = new ArrayList(); + if (s == null || s.length() < 4) { + return resultList; + } + + int len = s.length(); + String splitS = "."; + // iterate + for (int fisrt = 1; fisrt < 4 && fisrt < len - 2; fisrt++) { + for (int second = fisrt + 1; second < fisrt + 4 && second < len - 1; second++) { + for (int third = second + 1; third < second + 4 && third < len; third++) { + String part1 = s.substring(0, fisrt); + String part2 = s.substring(fisrt, second); + String part3 = s.substring(second, third); + String part4 = s.substring(third); + if (valideIP(part1) && valideIP(part2) && valideIP(part3) && valideIP(part4)) { + String result = part1 + splitS + part2 + splitS + part3 + splitS + part4; + resultList.add(result); + } + } + } + + } + + return resultList; + } + + private Boolean valideIP(String part) { + if (part.length() == 0 || part.length() > 3 + || (part.startsWith("0") && part.length() != 1) + || (part.length() == 3 && Integer.valueOf(part) > 255 )) { + return false; + } + + return true; + } +} diff --git a/code/LeetCode/src/backtracking/Subsets.java b/code/LeetCode/src/backtracking/Subsets.java new file mode 100644 index 00000000..c5a57aad --- /dev/null +++ b/code/LeetCode/src/backtracking/Subsets.java @@ -0,0 +1,110 @@ +package backtracking; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +// https://leetcode.com/problems/subsets/ +public class Subsets { + + public static void main(String[] args) { + int[] nums = new int[]{1,2,3}; + Subsets obj = new Subsets(); + //List> resultList = obj.subsets(nums); + //List> resultList = obj.subsetsWithRecursion(nums); + //List> resultList = obj.subsetsWithBacktrack(nums); + List> resultList = obj.subsetsWithBinarySorted(nums); + System.out.println(Arrays.toString(resultList.toArray())); + } + + public List> subsets(int[] nums) { + List> resultList = new ArrayList>(); + // dfs + dfs(nums, resultList, new ArrayList(), 0); + + return resultList; + } + + private void dfs(int[] nums, List> resultList, List list, int index) { + // exit + if (nums == null || index == nums.length) { + resultList.add(new ArrayList(list)); + return; + } + + // add item + list.add(nums[index]); + dfs(nums, resultList, list, index + 1); + + // not add item + list.remove(list.size() - 1); + dfs(nums, resultList, list, index + 1); + } + + + public List> subsetsWithRecursion(int[] nums) { + List> outputList = new ArrayList>(); + outputList.add(new ArrayList()); + for (int num: nums) { + List> newList = new ArrayList>(); + for (List list: outputList) { + newList.add(new ArrayList(list) {{ add(num); }}); + } + + for (List list: newList) { + outputList.add(list); + } + } + + return outputList; + } + + public List> subsetsWithBacktrack(int[] nums) { + List> resultList = new ArrayList>(); + for (int len = 0; len <= nums.length; len++) { + // backtrack + backtrack(nums, resultList, new ArrayList(), 0, len); + } + + return resultList; + } + + private void backtrack(int[] nums, List> resultList, List list, int first, int len) { + // exit + if (list.size() == len) { + resultList.add(new ArrayList(list)); + return; + } + + if (first == nums.length) { + return; + } + list.add(nums[first]); + backtrack(nums, resultList, list, first + 1, len); + list.remove(list.size() - 1); + backtrack(nums, resultList, list, first + 1, len); + } + + public List> subsetsWithBinarySorted(int[] nums) { + List> resultList = new ArrayList>(); + int n = nums.length; + + for (int i = (int)Math.pow(2, n); i < (int)Math.pow(2, n + 1); i++) { + // generate bitmask, from 0..00 to 1..11 + String bitmask = Integer.toBinaryString(i).substring(1); + + // append subset corresponding to that bitmask + List list = new ArrayList(); + for (int k = 0; k < n; k++) { + if (bitmask.charAt(k) == '1') { + list.add(nums[k]); + } + } + + resultList.add(list); + } + + return resultList; + } +} diff --git a/code/LeetCode/src/backtracking/SubsetsII.java b/code/LeetCode/src/backtracking/SubsetsII.java new file mode 100644 index 00000000..875ae60b --- /dev/null +++ b/code/LeetCode/src/backtracking/SubsetsII.java @@ -0,0 +1,93 @@ +package backtracking; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +// https://leetcode.com/problems/subsets-ii/ +public class SubsetsII { + + public static void main(String[] args) { + int[] nums = {1,2,2}; + SubsetsII obj = new SubsetsII(); + //List> resultList = obj.subsetsWithDup(nums); + List> resultList = obj.subsetsWithDupIterate(nums); + System.out.println(Arrays.toString(resultList.toArray())); + } + + public List> subsetsWithDup(int[] nums) { + Arrays.sort(nums); + List> resultList = new ArrayList>(); + // dfs + //dfs(nums, resultList, new ArrayList(), 0); + dfsWithFor(nums, resultList, new ArrayList(), 0); + //subsetsWithDupHelper(nums, resultList, new ArrayList(), 0); + + return resultList; + } + + private void dfs(int[] nums, List> resultList, List list, int start) { + if (start <= nums.length) { + resultList.add(list); + } + int i = start; + while (i < nums.length) { + list.add(nums[i]); + dfs(nums, resultList, new ArrayList(list), i + 1); + + list.remove(list.size() - 1); + i++; + while (i < nums.length && nums[i] == nums[i - 1]) { + i++; + } + } + + } + + private void dfsWithFor(int[] nums, List> resultList, List list, int start) { + // exit + if (start <= nums.length) { + resultList.add(new ArrayList<>(list)); + } + + for (int i = start; i < nums.length; i++) { + // duplicate case + if (i > start && nums[i] == nums[i - 1]) { + continue; + } + + // pick up + list.add(nums[i]); + dfsWithFor(nums, resultList, list, i + 1); + + // not pick up + list.remove(list.size() - 1); + } + } + + public List> subsetsWithDupIterate(int[] nums) { + Arrays.sort(nums); + List> resultList = new ArrayList>(); + List list = new ArrayList(); + resultList.add(list); + + int duplicateStart = 0; + for (int i = 0; i < nums.length; i++) { + int begin = 0; + int size = resultList.size(); + if (i > 0 && nums[i] == nums[i - 1]) { + begin = duplicateStart; + } + + for (int k = begin; k < size; k++) { + List newList = new ArrayList(resultList.get(k)); + newList.add(nums[i]); + resultList.add(newList); + } + + duplicateStart = size; + } + + return resultList; + } +} diff --git a/code/LeetCode/src/backtracking/WordDictionary.java b/code/LeetCode/src/backtracking/WordDictionary.java new file mode 100644 index 00000000..3bd1b2e9 --- /dev/null +++ b/code/LeetCode/src/backtracking/WordDictionary.java @@ -0,0 +1,100 @@ +package backtracking; + +// https://leetcode.com/problems/add-and-search-word-data-structure-design/ + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * Your WordDictionary object will be instantiated and called as such: + * WordDictionary obj = new WordDictionary(); + * obj.addWord(word); + * boolean param_2 = obj.search(word); + */ +public class WordDictionary { + + private class TrieNode { + private boolean isWord; + private Map childMap; + + public TrieNode() { + isWord = false; + childMap = new HashMap(); + } + + } + + private TrieNode root; + + /** Initialize your data structure here. */ + public WordDictionary() { + root = new TrieNode(); + } + + /** Adds a word into the data structure. */ + public void addWord(String word) { + TrieNode curr = root; + for (char c: word.toCharArray()) { + if (!curr.childMap.containsKey(c)) { + curr.childMap.put(c, new TrieNode()); + } + curr = curr.childMap.get(c); + } + + curr.isWord = true; + } + + /** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */ + public boolean search(String word) { + return dfs(word,0, root); + } + + public boolean dfs(String word, int pos, TrieNode node) { + // if the word has all been scanned, return + if (pos == word.length()) { + return node.isWord; + } + // reach the leaf before finishing scanning the word + if (node.childMap.size() == 0) { + return false; + } + + Character c = word.charAt(pos); + // if the character at current position is '.', + // recursive check whether the remaining word is in the trie + if (c == '.') { + for (char item: node.childMap.keySet()) { + if (dfs(word, pos + 1, node.childMap.get(item))) { + return true; + } + } + } + + // if character at position 'pos' is neither equal to the node nor '.', return false + if (!node.childMap.containsKey(c)) { + return false; + } + + // if character at current position matches the node, + // recursively search the remaining word + return dfs(word, pos + 1, node.childMap.get(c)); + } + + public static void main(String[] args) { + WordDictionary obj = new WordDictionary(); + obj.addWord("bad"); + obj.addWord("dad"); + obj.addWord("mad"); + obj.addWord("a"); + System.out.println(obj.search("pad")); + System.out.println(obj.search("bad")); + System.out.println(obj.search(".ad")); + System.out.println(obj.search("b..")); + //obj.search("pad") -> false + //obj.search("bad") -> true + //obj.search(".ad") -> true + //obj.search("b..") -> true + } +} diff --git a/code/LeetCode/src/backtracking/WordSearch.java b/code/LeetCode/src/backtracking/WordSearch.java new file mode 100644 index 00000000..5f2eae00 --- /dev/null +++ b/code/LeetCode/src/backtracking/WordSearch.java @@ -0,0 +1,65 @@ +package backtracking; + +// https://leetcode.com/problems/word-search/ +public class WordSearch { + + public static void main(String[] args) { + WordSearch obj = new WordSearch(); + char[][] board = {{'A','B','C','E'}, + {'S','F','C','S'}, + {'A','D','E','E'}}; + //String word = "ABCCED"; + //String word = "SEE"; + String word = "ABCB"; + boolean result = obj.exist(board, word); + System.out.println("result > " + result); + } + + public boolean exist(char[][] board, String word) { + // check edge + if (word == null || word.length() == 0) { + return true; + } + if (board == null || board.length == 0 || board[0].length == 0) { + return false; + } + // used boolean + boolean[][] used = new boolean[board.length][board[0].length]; + + // dfs + for (int row = 0; row < board.length; row++) { + for (int col = 0; col < board[row].length; col++) { + if (dfs(board, word, used, row, col, 0)) { + return true; + } + } + } + + + return false; + } + + private boolean dfs(char[][] board, String word, boolean[][] used, int row, int col, int wordIndex) { + if (word == null || wordIndex == word.length()) { + return true; + } + char currentChar = word.charAt(wordIndex); + if (row < 0 || col < 0 + || row >= board.length || col >= board[row].length + || currentChar != board[row][col] || used[row][col]) + { + return false; + } + // mark use + used[row][col] = true; + boolean result = dfs(board, word, used, row + 1, col, wordIndex + 1) + || dfs(board, word, used, row - 1, col, wordIndex + 1) + || dfs(board, word, used, row, col + 1, wordIndex + 1) + || dfs(board, word, used, row, col - 1, wordIndex + 1); + + // mark not use + used[row][col] = false; + + return result; + } +} diff --git a/code/LeetCode/src/binarysearch/DivideTwoIntegers.java b/code/LeetCode/src/binarysearch/DivideTwoIntegers.java new file mode 100644 index 00000000..32ca2091 --- /dev/null +++ b/code/LeetCode/src/binarysearch/DivideTwoIntegers.java @@ -0,0 +1,102 @@ +package binarysearch; + +// https://leetcode.com/problems/divide-two-integers/ +public class DivideTwoIntegers { + + //int maxOfHalf = Integer.MAX_VALUE >> 1; + // + //public static void main(String[] args) { + // DivideTwoIntegers obj = new DivideTwoIntegers(); + // int result = obj.divide(-2147483648, -1); + // System.out.println("result > " + result); + //} + // + //public int divide(int dividend, int divisor) { + // // Reduce the problem to positive long integer to make it easier. + // // Use long to avoid integer overflow case. + // int sign = -1; + // if ((dividend > 0 && divisor > 0) || (dividend < 0 && divisor < 0)) { + // sign = 1; + // } + // long ldividend = Math.abs((long)dividend); + // long ldivisor = Math.abs((long)divisor); + // + // // Take care the edge cases. + // if (ldivisor == 0) return Integer.MAX_VALUE; + // if ((ldividend == 0 || (ldividend < ldivisor))) return 0; + // + // long lans = ldivide(ldividend, ldivisor); + // + // int ans; + // if (lans > Integer.MAX_VALUE) { + // // Handle overflow. + // ans = (sign == 1) ? Integer.MAX_VALUE : Integer.MIN_VALUE; + // } else { + // ans = (int)((sign == 1) ? lans : -lans); + // } + // + // return ans; + //} + // + //private long ldivide(long ldividend, long ldivisor) { + // // Recursion exit condition + // if (ldividend < ldivisor) { + // return 0; + // } + // + // // Find the largest multiple so that (divisor * multiple <= dividend), + // // whereas we are moving with stride 1, 2, 4, 8, 16...2^n for performance reason. + // // Think this as a binary search. + // long sum = ldivisor; + // long multiple = 1; + // while ((sum << 1) <= ldividend) { + // multiple <<= 1; + // sum <<= 1; + // } + // + // // Look for additional value for the multiple from the reminder (dividend - sum) recursively. + // return multiple + ldivide(ldividend - sum, ldivisor); + //} + + public int divide(int dividend, int divisor) { + //sign + int sign = 1; + if ((dividend > 0 && divisor < 0) || (dividend < 0 && divisor > 0)) { + sign = -1; + } + // long type + long ldividend = Math.abs((long)dividend); + long ldivisor = Math.abs((long)divisor); + // edge + if (ldivisor == 0) { + return (sign == 1) ? Integer.MAX_VALUE : Integer.MIN_VALUE; + } + if (ldividend < ldivisor) { + return 0; + } + long result = ldivide(ldividend, ldivisor); + + if (result > Integer.MAX_VALUE) { + return (sign == 1) ? Integer.MAX_VALUE : Integer.MIN_VALUE; + } + + int intResult = (int)result; + return (sign == 1) ? intResult : - intResult; + } + + public long ldivide(long ldividend, long ldivisor) { + // exit condition + if (ldividend < ldivisor) { + return 0; + } + long multiple = 1; + long sum = ldivisor; + while ((sum << 1) <= ldividend) { + sum <<= 1; + multiple <<= 1; + } + + return multiple + ldivide(ldividend - sum, ldivisor); + } + +} diff --git a/code/LeetCode/src/binarysearch/FindFirstAndLastPositionOfElementInSortedArray.java b/code/LeetCode/src/binarysearch/FindFirstAndLastPositionOfElementInSortedArray.java new file mode 100644 index 00000000..320308f0 --- /dev/null +++ b/code/LeetCode/src/binarysearch/FindFirstAndLastPositionOfElementInSortedArray.java @@ -0,0 +1,156 @@ +package binarysearch; + +import java.util.Arrays; + +// https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/ +public class FindFirstAndLastPositionOfElementInSortedArray { + + public static void main(String[] args) { + int[] nums = {2, 2}; + int target = 2; + FindFirstAndLastPositionOfElementInSortedArray obj = new FindFirstAndLastPositionOfElementInSortedArray(); + int[] result = obj.searchRangeWithFirstGreatEqual(nums, target); + System.out.println(Arrays.toString(result)); + } + + public int[] searchRangeWithFirstGreatEqual(int[] nums, int target) { + int[] result = new int[]{-1, -1}; + // edge check + if (nums == null || nums.length == 0) { + return result; + } + int find = findFirstGreatEqual(nums, target); + if (find >= nums.length || nums[find] != target) { + return result; + } + result[0] = find; + result[1] = findFirstGreatEqual(nums, target + 1) - 1; + + return result; + } + + //find the first number that is greater than or equal to target. + //could return A.length if target is greater than A[A.length-1]. + private int findFirstGreatEqual(int[] nums, int target) { + int low = 0; + int high = nums.length; + while (low < high) { + int mid = low + ((high - low) >> 1); + //low <= mid < high + if (nums[mid] < target) { + low = mid + 1; + } else { + //should not be mid-1 when A[mid]==target. + //could be mid even if A[mid]>target because mid> 1); + if (nums[mid] >= target) { + right = mid - 1; + } else { + left = mid + 1; + } + if (nums[mid] == target) { + result = mid; + } + } + + return result; + } + + private int findLast(int[] nums, int target) { + int result = -1; + int left = 0; + int right = nums.length - 1; + while (left <= right) { + int mid = left + ((right - left) >> 1); + if (nums[mid] <= target) { + left = mid + 1; + } else { + right = mid - 1; + } + if (nums[mid] == target) { + result = mid; + } + } + + + return result; + } + + public int[] searchRange(int[] nums, int target) { + int[] result = new int[]{-1, -1}; + // edge check + if (nums == null || nums.length == 0) { + return result; + } + + int left = 0; + int right = nums.length - 1; + int find = -1; + while (left <= right && find == -1) { + int mid = left + ((right - left) >> 1); + if (nums[mid] == target) { + find = mid; + break; + } else if (nums[mid] < target) { + left = mid + 1; + } else { + right = mid - 1; + } + } + + // no found return + if (find == -1) { + return result; + } + + int findMinRight = find; + while (left <= findMinRight) { + int mid = left + ((findMinRight - left) >> 1); + if (nums[mid] == target) { + result[0] = mid; + findMinRight = mid - 1; + } else { + // less than target + left = mid + 1; + } + } + + int findMaxLeft = find; + while (findMaxLeft <= right) { + int mid = findMaxLeft + ((right - findMaxLeft) >> 1); + if (nums[mid] == target) { + result[1] = mid; + findMaxLeft = mid + 1; + } else { + // more than target + right = mid - 1; + } + } + + return result; + } +} diff --git a/code/LeetCode/src/binarysearch/Powxn.java b/code/LeetCode/src/binarysearch/Powxn.java new file mode 100644 index 00000000..4eb75585 --- /dev/null +++ b/code/LeetCode/src/binarysearch/Powxn.java @@ -0,0 +1,60 @@ +package binarysearch; + +public class Powxn { + + public static void main(String[] args) { + Powxn obj = new Powxn(); + System.out.println("Input:2.000, -2147483648 >> " + obj.myPow(2.000, -2147483648) ); + System.out.println("Input:2.000, -2 >> " + obj.myPow(2.000, -2) ); + System.out.println("Input:2.000, 10 >> " + obj.myPow(2.000, 10) ); + System.out.println("Input:2.1, 3 >> " + obj.myPow(2.1, 3) ); + + System.out.println("========================="); + + System.out.println("Input:2.000, -2147483648 >> " + obj.myPowWithIterate(2.000, -2147483648) ); + System.out.println("Input:2.000, -2 >> " + obj.myPowWithIterate(2.000, -2) ); + System.out.println("Input:2.000, 10 >> " + obj.myPowWithIterate(2.000, 10) ); + System.out.println("Input:2.1, 3 >> " + obj.myPowWithIterate(2.1, 3) ); + } + + public double myPow(double x, int n) { + if (n < 0) { + // consider -n overflow + return 1/x * myPow(1/x, -(n + 1)); + } + if (n == 0) { + return 1; + } + if (n == 1) { + return x; + } + + int halfN = n >> 1; + return (n%2 == 0) ? myPow(x * x, halfN) : myPow( x * x, halfN) * x; + } + + + public double myPowWithIterate(double x, int n) { + double result = 1; + if (n < 0) { + // consider -n overflow + x = 1/x; + n = -(n + 1); + result = x; + } + + while (n != 0) { + if (n % 2 == 1) { + result *= x; + if (n == 1) { + break; + } + } + + x = x * x; + n = n >> 1; + } + + return result; + } +} diff --git a/code/LeetCode/src/binarysearch/SearchInRotatedSortedArray.java b/code/LeetCode/src/binarysearch/SearchInRotatedSortedArray.java new file mode 100644 index 00000000..1d89765e --- /dev/null +++ b/code/LeetCode/src/binarysearch/SearchInRotatedSortedArray.java @@ -0,0 +1,54 @@ +package binarysearch; + +// https://leetcode.com/problems/search-in-rotated-sorted-array/ +public class SearchInRotatedSortedArray { + + public static void main(String[] args) { + SearchInRotatedSortedArray obj = new SearchInRotatedSortedArray(); + int[] nums = {1, 3}; + obj.search(nums, 3); + } + + public int search(int[] nums, int target) { + // check edge + if (nums == null || nums.length == 0) { + return -1; + } + // find the divide index + int divideIndex = findDividIndex(nums); + if (target == nums[divideIndex]) { + return divideIndex; + } + int lastIndex = nums.length - 1; + int beginIndex = target > nums[lastIndex] ? 0 : divideIndex; + int endIndex = target > nums[lastIndex] ? divideIndex : lastIndex; + while (beginIndex <= endIndex) { + int midIndex = beginIndex + ((endIndex - beginIndex) >> 1); + if (target == nums[midIndex]) { + return midIndex; + } else if (target > nums[midIndex]) { + beginIndex = midIndex + 1; + } else { + endIndex = midIndex - 1; + } + } + + return -1; + } + + private int findDividIndex(int[] nums) { + int from = 0; + int to = nums.length - 1; + while (from < to) { + int mid = from + ((to - from) >> 1); + if (nums[mid] > nums[to]) { + from = mid + 1; + } else { + to = mid; + } + } + + return from; + } + +} diff --git a/code/LeetCode/src/binarysearch/Sqrtx.java b/code/LeetCode/src/binarysearch/Sqrtx.java new file mode 100644 index 00000000..117ba496 --- /dev/null +++ b/code/LeetCode/src/binarysearch/Sqrtx.java @@ -0,0 +1,31 @@ +package binarysearch; + +// https://leetcode.com/problems/sqrtx/ +public class Sqrtx { + + public static int mySqrt(int x) { + if (x == 1 || x == 0) { + return x; + } + int left = 0; + int right = x; + int mid; + while (left < right) { + mid = left + ((right - left) >> 1); + if (mid > x / mid) { + right = mid - 1; + } else { + if ((mid + 1) > x / (mid + 1)) { + return mid; + } + left = mid + 1; + } + } + + return left; + } + + public static void main(String[] args) { + mySqrt(10); + } +} diff --git a/code/LeetCode/src/bitwise/NumberOfOneBits.java b/code/LeetCode/src/bitwise/NumberOfOneBits.java new file mode 100644 index 00000000..d87c3c6c --- /dev/null +++ b/code/LeetCode/src/bitwise/NumberOfOneBits.java @@ -0,0 +1,32 @@ +package bitwise; + +// https://leetcode.com/problems/number-of-1-bits/ +public class NumberOfOneBits { + // you need to treat n as an unsigned value + public static int hanmmingWeight(int n) { + int count = 0; + while (n != 0) { + n = n & (n - 1); + count++; + } + + return count; + } + + public static int hanmmingWeightVerbose(int n) { + int count = 0; + int mask = 1; + for (int i = 1; i <= 32; i++) { + if ((n & mask) != 0) { + count++; + } + mask <<= 1; + } + + return count; + } + + public static void main(String[] args) { + System.out.println(hanmmingWeightVerbose(11)); + } +} diff --git a/code/LeetCode/src/bitwise/ReverseBits.java b/code/LeetCode/src/bitwise/ReverseBits.java new file mode 100644 index 00000000..e7f4270e --- /dev/null +++ b/code/LeetCode/src/bitwise/ReverseBits.java @@ -0,0 +1,21 @@ +package bitwise; + +// https://leetcode.com/problems/reverse-bits/ +public class ReverseBits { + // you need treat n as an unsigned value + public int reverseBits(int n) { + int mask = 1; + int result = 0; + int appendInt; + for (int i = 1; i <= 32; i++) { + appendInt = 0; + if ((mask & n) != 0) { + appendInt = 1; + } + result = (result << 1) + appendInt; + mask <<= 1; + } + + return result; + } +} diff --git a/code/LeetCode/src/bitwise/SumOfTwoIntegers.java b/code/LeetCode/src/bitwise/SumOfTwoIntegers.java new file mode 100644 index 00000000..b8852097 --- /dev/null +++ b/code/LeetCode/src/bitwise/SumOfTwoIntegers.java @@ -0,0 +1,29 @@ +package bitwise; + +// https://leetcode.com/problems/sum-of-two-integers/ +// solution --> +// https://leetcode.com/problems/sum-of-two-integers/discuss/132479/Simple-explanation-on-how-to-arrive-at-the-solution +public class SumOfTwoIntegers { + public static int getSum(int a, int b) { + if (a == 0) { + return b; + } + if (b == 0) { + return a; + } + while (b != 0) { + int carry = a & b; + a = a ^ b; + b = carry << 1; + } + + return a; + } + + public static void main(String[] args) { + int result = getSum(1 ,2); + int result1 = getSum(-2, 3); + System.out.println("a = 1, b = 2, c = " + result); + System.out.println("a = -2, b = 3, c = " + result1); + } +} diff --git a/code/LeetCode/src/common/ListNode.java b/code/LeetCode/src/common/ListNode.java new file mode 100644 index 00000000..6bf38476 --- /dev/null +++ b/code/LeetCode/src/common/ListNode.java @@ -0,0 +1,42 @@ +package common; + +public class ListNode { + public int val; + public ListNode next; + public ListNode(int val) { + this.val = val; + } + + static public ListNode listNodeWithIntArray(int[] input) { + ListNode head = new ListNode(0); + ListNode node = head; + + for (int i: input) { + ListNode newNode = new ListNode(i); + node.next = newNode; + node = node.next; + } + + return head.next; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + ListNode node = this; + while (node != null) { + sb.append(node.val).append("-->"); + node = node.next; + } + return sb.append("Null").toString(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + return false; + } +} diff --git a/code/LeetCode/src/common/TreeNode.java b/code/LeetCode/src/common/TreeNode.java new file mode 100644 index 00000000..d89ee75f --- /dev/null +++ b/code/LeetCode/src/common/TreeNode.java @@ -0,0 +1,91 @@ +package common; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +public class TreeNode { + public int val; + public TreeNode left; + public TreeNode right; + public TreeNode() { } + public TreeNode(int val) { + this.val = val; + } + + public TreeNode(int val, TreeNode left, TreeNode right) { + this.val = val; + this.left = left; + this.right = right; + } + + @Override + public String toString() { + if (this == null) { + return "null"; + } + + String result = ""; + List row = null; + List> list = new ArrayList>(); + + LinkedList rowNode = new LinkedList<>(); + rowNode.add(this); + while (!rowNode.isEmpty()) { + int rowSize = rowNode.size(); + row = new ArrayList(); + + int rowCount = rowSize; + int nullCount = 0; + while (rowSize > 0) { + TreeNode current = rowNode.pop(); + if (current == null) { + row.add("null"); + nullCount++; + } else { + row.add(Integer.toString(current.val)); + } + + if (current == null || current.left == null) { + rowNode.add(null); + } else { + rowNode.add(current.left); + } + if (current == null || current.right == null) { + rowNode.add(null); + } else { + rowNode.add(current.right); + } + + rowSize--; + } + + if (nullCount == rowCount) { + break; + } + + list.add(row); + } + + // print data + String blank = " "; + for (int i = 0; i < list.size(); i ++) { + for (int j = i; j < list.size(); j++) { + // print blank + System.out.print(blank); + } + List rowList = list.get(i); + for (int k = 0; k < rowList.size(); k++) { + System.out.print(rowList.get(k)); + System.out.print(blank); + } + + System.out.println(); + } + + + //return Arrays.toString(list.toArray()); + + return super.toString(); + } +} diff --git a/code/LeetCode/src/contest/Contest.java b/code/LeetCode/src/contest/Contest.java new file mode 100644 index 00000000..7a17c4c1 --- /dev/null +++ b/code/LeetCode/src/contest/Contest.java @@ -0,0 +1,95 @@ +package contest; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +public class Contest { + + public static void main(String[] args) { + + //test1(); + + //test2(); + + //test3(); + //help(); + + int k = 8; + int[] inputs = {7, 9, 8, 9}; + List aList = new ArrayList<>(); + for (int i: inputs) { + aList.add(i); + } + + + } + + static long count = 0; + + public static void help(int index, int k, List aList, long[] result) { + //Arrays.fill(result, 0); + if (index == aList.size()) { + long sum = 0; + for (long l: result) { + sum += l; + } + if (sum == k) { + count++; + } + return; + } + + result[index] = 0; + help(index + 1, k, aList, result); + result[index] = aList.get(index); + //help(index + 1, k, aList, result); + } + + + + public static void test3() { + String s = "125"; + long result = Long.parseLong(s); + int len = s.length(); + long[] longArray = new long[s.length()]; + for (int i = 1; i < s.length() - 1; i++) { + Arrays.fill(longArray, 0); + for (int j = 0; j < s.length(); j++) { + + } + } + } + + + public static void test2() { + long minX = 0; + long minY = 0; + int x = 1; + int y = 2; + + if (x > minX && y > minY) { + minX = x; + minY = y; + } else { + double mulX = 1; + double mulY = 1; + if (x > 0) { + mulX = Math.ceil(1.0 * minX / x); + } + if (y > 0) { + mulY = Math.ceil(1.0 * minY / y); + } + long mulMax = (long) Math.max(mulX, mulY); + minX = x * mulMax; + minY = y * mulMax; + } + + long result = minX + minY; + System.out.print(result); + } + + + +} diff --git a/code/LeetCode/src/dp/BestTimeToBuyAndSellStock.java b/code/LeetCode/src/dp/BestTimeToBuyAndSellStock.java new file mode 100644 index 00000000..0569530b --- /dev/null +++ b/code/LeetCode/src/dp/BestTimeToBuyAndSellStock.java @@ -0,0 +1,39 @@ +package dp; + +// https://leetcode.com/problems/best-time-to-buy-and-sell-stock/ +public class BestTimeToBuyAndSellStock { + public int maxProfit(int[] prices) { + int max = 0; + int profit; + for (int i = 0; i < prices.length; i++) { + for (int k = i + 1; k < prices.length; k++) { + profit = prices[k] - prices[i]; + if (profit > max) { + max = profit; + } + } + } + + return max; + } + + public int maxProfitWithOnePass(int[] prices) { + if (prices.length <= 0) { + return 0; + } + int max = 0; + int valley = prices[0]; + int gap; + for (int p: prices) { + if (valley > p) { + valley = p; + } + gap = p - valley; + if (max < gap) { + max = gap; + } + } + + return max; + } +} diff --git a/code/LeetCode/src/dp/BestTimeToBuyAndSellStockII.java b/code/LeetCode/src/dp/BestTimeToBuyAndSellStockII.java new file mode 100644 index 00000000..466e106b --- /dev/null +++ b/code/LeetCode/src/dp/BestTimeToBuyAndSellStockII.java @@ -0,0 +1,79 @@ +package dp; + +// https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/ +public class BestTimeToBuyAndSellStockII { + public int maxProfit(int[] prices) { + int profit = 0; + for (int i = 1; i < prices.length; i++) { + if (prices[i] > prices[i - 1]) { + profit += prices[i] - prices[i - 1]; + } + } + + return profit; + } + + public static int maxProfitWithBruteForce(int[] prices) { + return calculate(prices, 0); + } + + public static int calculate(int[] prices, int start) { + if (start >= prices.length) { + return 0; + } + // max profit + int max = 0; + // loop from start + for (int i = start; i < prices.length; i++) { + // current max; + int maxProfit = 0; + + // loop after start + for (int k = i + 1; k < prices.length; k++) { + // current > start ,then two way: sell stock or keep + if (prices[k] > prices[i]) { + int profit = prices[k] - prices[i] + calculate(prices, k + 1); + if (profit > maxProfit) { + maxProfit = profit; + } + } + } + + if (maxProfit > max) { + max = maxProfit; + } + } + + return max; + } + + public static int maxProfitWithValleyAndPeak(int[] prices) { + if (prices.length <= 0) { + return 0; + } + int max = 0; + int valley; + int peak; + int i = 0; + while (i < prices.length - 1) { + // find the valley index + while (i < prices.length - 1 && prices[i] >= prices[i + 1]) { + i++; + } + valley = prices[i]; + // find the peak index + while (i < prices.length - 1 && prices[i] <= prices[i + 1]) { + i++; + } + peak = prices[i]; + max += peak - valley; + } + + return max; + } + + public static void main(String[] args) { + int result = maxProfitWithValleyAndPeak(new int[]{1,2,3,4,5}); + System.out.println("result: " + result); + } +} diff --git a/code/LeetCode/src/dp/ClimbingStairs.java b/code/LeetCode/src/dp/ClimbingStairs.java new file mode 100644 index 00000000..ce4cc78d --- /dev/null +++ b/code/LeetCode/src/dp/ClimbingStairs.java @@ -0,0 +1,57 @@ +package dp; + +import java.util.Arrays; + +// https://leetcode.com/problems/climbing-stairs/ +public class ClimbingStairs { + + int[] memo = null; + // recursive : problem > Time Limit Exceeded + public int climbStairs(int n) { + if (memo == null) { + memo = new int[n + 1]; + Arrays.fill(memo, -1); + } + if (n == 1 || n == 0) { + return 1; + } + + if (memo[n] != -1) { + return memo[n]; + } + memo[n] = climbStairs(n - 1) + climbStairs(n - 2); + return memo[n]; + } + + // Fibonacci + public int climbStairsWithFibonacci(int n) { + if (n == 0 || n == 1) { + return 1; + } + int pre = 1; + int current = 1; + int temp; + for (int i = 2; i <= n; i++) { + temp = pre + current; + pre = current; + current = temp; + } + + return current; + } + + // dynamic program + public int climbStairsWithDP(int n) { + if (n == 1 || n == 0) { + return 1; + } + int[] dp = new int[n + 1]; + dp[0] = 1; + dp[1] = 1; + for (int i = 2; i <= n; i++) { + dp[i] = dp[i - 1] + dp[i - 2]; + } + + return dp[n]; + } +} diff --git a/code/LeetCode/src/dp/LongestPalindromicSubstrins.java b/code/LeetCode/src/dp/LongestPalindromicSubstrins.java new file mode 100644 index 00000000..2f9a9088 --- /dev/null +++ b/code/LeetCode/src/dp/LongestPalindromicSubstrins.java @@ -0,0 +1,149 @@ +package dp; + +// https://leetcode.com/problems/longest-palindromic-substring/ +public class LongestPalindromicSubstrins { + + public String longestPalindromeWithdp(String s) { + if (s == null || s.length() == 0) { + return ""; + } + boolean[][] dp = new boolean[s.length()][s.length()]; + String result = ""; + for (int i = s.length() - 1; i >= 0; i--) { + for (int k = i; k < s.length(); k++) { + dp[i][k] = (s.charAt(i) == s.charAt(k) && (k - i < 3 || dp[i + 1][k - 1])); + + if (dp[i][k] && k - i + 1 > result.length()) { + result = s.substring(i, k + 1); + } + } + } + + return result; + } + + public String longestPalindromeRecursive(String s) { + if (s == null || s.length() == 0) { + return ""; + } + + char[] chars = s.toCharArray(); + int max = 0; + int start = 0; + int end = 0; + for (int i = 0; i < chars.length; i++) { + if (validPalindrome(chars, i - max - 1, i)) { + start = i - max - 1; + end = i; + max += 2; + } else if (validPalindrome(chars, i - max, i)) { + start = i - max; + end = i; + max += 1; + } + } + + return s.substring(start, end + 1); + } + + public boolean validPalindrome(char[] chars, int start, int end) { + if (start < 0) { + return false; + } + while (start < end) { + if (chars[start++] != chars[end--]) { + return false; + } + } + + return true; + } + + public static String longestPalindromeSynchronize(String s) { + // edge case + if (s == null || s.length() == 0) { + return ""; + } + int max = 1; + String result = s.substring(0, 1); + for (int i = 0; i < s.length(); i++) { + int len1 = expandPalindrom(s, i, i); + int len2 = expandPalindrom(s, i, i + 1); + int len = Math.max(len1, len2); + if (max < len) { + max = len; + int left = i - (len - 1) / 2; + int right = i + len / 2; + result = s.substring(left, right + 1); + } + } + + return result; + } + + public static int expandPalindrom(String s, int left, int right) { + while (left >= 0 && right < s.length()) { + if (s.charAt(left) != s.charAt(right)) { + break; + } + + left--; + right++; + } + + return right - left - 1; + } + + public static void main(String[] args) { + String result = longestPalindromeSynchronize("bb"); + System.out.println(result); + } + + public static String longestPalindrome(String s) { + if (s == null || s.length() == 0) { + return ""; + } + int max = 1; + String result = s.substring(0, 1); + String current; + for (int i = 1; i < s.length(); i++) { + // assume the left string is palindrome, if its length is less than max, can break; + int dreamMax = Math.min(i, s.length() - i - 1) * 2 + 1; + if (max > dreamMax) { + break; + } + + // i is pivot center, such as 0i0 + current = helper(s, i - 1, i + 1); + if (max < current.length()) { + max = current.length(); + result = current; + } + + // i & i - 1 is pivot center, such as 0ii0 + if (s.charAt(i) != s.charAt(i - 1)) { + continue; + } + current = helper(s, i - 2, i + 1); + if (max < current.length()) { + max = current.length(); + result = current; + } + } + + return result; + } + + public static String helper(String s, int left, int right) { + while (left >= 0 && right < s.length()) { + if (s.charAt(left) != s.charAt(right)) { + break; + } + + left--; + right++; + } + + return right - left == 2 ? "" : s.substring(left + 1, right); + } +} diff --git a/code/LeetCode/src/hashtable/GroupAnagrams.java b/code/LeetCode/src/hashtable/GroupAnagrams.java new file mode 100644 index 00000000..b798032c --- /dev/null +++ b/code/LeetCode/src/hashtable/GroupAnagrams.java @@ -0,0 +1,94 @@ +package hashtable; + +import java.util.*; + +// https://leetcode.com/problems/group-anagrams/ +public class GroupAnagrams { + + public static void main(String[] args) { + String[] inputs = {"eat","tea","tan","ate","nat","bat"}; + GroupAnagrams obj = new GroupAnagrams(); + obj.groupAnagrams(inputs); + } + + public List> groupAnagramsWithCharCount(String[] strs) { + // edge check + if (strs == null || strs.length == 0) { + return null; + } + Map> map = new HashMap<>(); + int[] charCountArray = new int[26]; + // build map + for (String s: strs) { + Arrays.fill(charCountArray, 0); + for (char c: s.toCharArray()) { + charCountArray[(c - 'a')]++; + } + StringBuilder sb = new StringBuilder(); + for (int i: charCountArray) { + sb.append('#'); + sb.append(i); + } + + String sortItem = sb.toString(); + if (!map.containsKey(sortItem)) { + map.put(sortItem, new ArrayList()); + } + + map.get(sortItem).add(s); + } + + return new ArrayList<>(map.values()); + + } + + + private String sort(String input) { + char[] chars = input.toCharArray(); + Arrays.sort(chars); + return new String(chars); + } + + public List> groupAnagramsWithMap(String[] strs) { + // edge check + if (strs == null || strs.length == 0) { + return null; + } + Map> map = new HashMap<>(); + // build map + for (String s: strs) { + String sortItem = sort(s); + if (!map.containsKey(sortItem)) { + map.put(sortItem, new ArrayList()); + } + + map.get(sortItem).add(s); + } + + return new ArrayList<>(map.values()); + } + + public List> groupAnagrams(String[] strs) { + List> result = new ArrayList<>(); + + for (String s: strs) { + String sortString = sort(s); + boolean isSame = false; + for (List list: result) { + String item = list.get(0); + if (sortString.length() == item.length() && sort(item).equals(sortString)) { + list.add(s); + isSame = true; + break; + } + } + + if (isSame == false) { + result.add(new ArrayList<>(Arrays.asList(s))); + } + + } + + return result; + } +} diff --git a/code/LeetCode/src/hashtable/ValidSudoku.java b/code/LeetCode/src/hashtable/ValidSudoku.java new file mode 100644 index 00000000..cf5364df --- /dev/null +++ b/code/LeetCode/src/hashtable/ValidSudoku.java @@ -0,0 +1,119 @@ +package hashtable; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +// https://leetcode.com/problems/valid-sudoku/ +public class ValidSudoku { + + public static void main(String[] args) { + Map map = new HashMap<>(); + System.out.println("map coantins 0 > " + map.get(0) + " > validate bolean :" + map.containsKey(0)); + } + + public boolean isValidSudokuWithOneHashset(char[][] board) { + HashSet set = new HashSet<>(); + char item; + for (int i = 0; i < 9; i++) { + for (int j = 0; j < 9; j++) { + item = board[i][j]; + if (item == '.') { + continue; + } + if (!set.add(item + "row" + i)) { + return false; + } + if (!set.add(item + "col" + j)) { + return false; + } + if (!set.add(item + "block" + i/3 + "_" + j/3)) { + return false; + } + } + } + + return true; + } + + public boolean isValidSudokuWithHashset(char[][] board) { + + for (int i = 0; i < 9; i++) { + HashSet rowSet = new HashSet<>(); + HashSet colSet = new HashSet<>(); + HashSet blockSet = new HashSet<>(); + for (int j = 0; j < 9; j++) { + if (board[i][j] != '.' && !rowSet.add(board[i][j])) { + return false; + } + if (board[j][i] != '.' && !colSet.add(board[j][i])) { + return false; + } + int row = 3 * (i / 3); + int col = 3 * (i % 3); + int rowIndex = row + j / 3; + int colIndex = col + j % 3; + if (board[rowIndex][colIndex] != '.' && !blockSet.add(board[rowIndex][colIndex])) { + return false; + } + + } + } + + return true; + } + + public boolean isValidSudoku(char[][] board) { + // init data + Map> containMap = new HashMap<>(); + String rowPre = "row_"; + String columnPre = "col_"; + String blockConnect = "_"; + // row & column map + for (int i = 0; i < 9; i++) { + // row key : row_index + containMap.put(rowPre + i, new HashMap()); + // column key: clo_index + containMap.put(columnPre + i, new HashMap()); + } + // block map, key style: rowIndex_colIndex + for (int i = 0; i < 3; i++) { + for (int k = 0; k < 3; k++) { + containMap.put(i + blockConnect + k, new HashMap()); + } + } + + for (int r = 0; r < 9; r++) { + for (int c = 0; c < 9; c++) { + if (board[r][c] == '.') { + continue; + } + // row char + if (containMap.get(rowPre + r).containsKey(board[r][c])) { + return false; + } else { + containMap.get(rowPre + r).put(board[r][c], c); + } + // column char + if (containMap.get(columnPre + c).containsKey(board[r][c])) { + return false; + } else { + containMap.get(columnPre + c).put(board[r][c], r); + } + + // block + int blockRow = r / 3; + int blockColumn = c / 3; + String blockKey = blockRow+blockConnect+blockColumn; + if (containMap.get(blockKey).containsKey(board[r][c])) { + return false; + } else { + containMap.get(blockKey).put(board[r][c], c); + } + } + + } + + return true; + } +} diff --git a/code/LeetCode/src/linkedlist/MiddleOfTheLinkedList.java b/code/LeetCode/src/linkedlist/MiddleOfTheLinkedList.java new file mode 100644 index 00000000..453de9c8 --- /dev/null +++ b/code/LeetCode/src/linkedlist/MiddleOfTheLinkedList.java @@ -0,0 +1,25 @@ +package linkedlist; + +import common.ListNode; + +public class MiddleOfTheLinkedList { + + public ListNode middleNode(ListNode head) { + ListNode slow = head; + ListNode fast = head; + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + } + + return slow; + } + + public static void main(String[] args) { + int[] intArray = {1, 2, 3, 4, 5}; + ListNode head = ListNode.listNodeWithIntArray(intArray); + MiddleOfTheLinkedList obj = new MiddleOfTheLinkedList(); + ListNode middleNode = obj.middleNode(head); + System.out.println(middleNode.toString()); + } +} diff --git a/code/LeetCode/src/linkedlist/RemoveLinkedListElements.java b/code/LeetCode/src/linkedlist/RemoveLinkedListElements.java new file mode 100644 index 00000000..23d937b9 --- /dev/null +++ b/code/LeetCode/src/linkedlist/RemoveLinkedListElements.java @@ -0,0 +1,93 @@ +package linkedlist; + +// https://leetcode.com/problems/remove-linked-list-elements/ + + +import common.ListNode; + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +public class RemoveLinkedListElements { + + public ListNode removeElements(ListNode head, int val) { + ListNode result = head; + ListNode preNode = null; + boolean isFirstNode = true; + while (head != null) { + // the first one + if (isFirstNode == true) { + if (head.val == val) { + // if the first one equal to the remove value, then the element still first + head = head.next; + result = head; + } else { + isFirstNode = false; + preNode = head; + head = head.next; + } + + continue; + } + + // middle section + if (head.val == val) { + preNode.next = head.next; + head = head.next; + } else { + preNode = head; + head = head.next; + } + + // the last one, the same as middle section + + } + + return result; + } + + public ListNode removeElementsWithRecursive(ListNode head, int val) { + // exit condition + if (head == null) return null; + // recursive from tail to head. + head.next = removeElementsWithRecursive(head.next, val); + return head.val == val ? head.next : head; + } + + public ListNode removeElementWithFakeHead(ListNode head, int val) { + ListNode fakeHead = new ListNode(-1); + fakeHead.next = head; + ListNode pre = fakeHead; + while (head != null) { + if (head.val == val) { + pre.next = head.next; + } else { + pre = head; + } + + head = head.next; + } + + return fakeHead.next; + } + + public static void main(String[] args) { + RemoveLinkedListElements obj = new RemoveLinkedListElements(); + int[] originArray = {1, 2, 6, 3, 4, 5, 6}; + ListNode head = ListNode.listNodeWithIntArray(originArray); + System.out.println(head.toString()); + //ListNode result = obj.removeElements(head, 6); + //ListNode result = obj.removeElementsWithRecursive(head, 6); + ListNode result = obj.removeElementWithFakeHead(head, 6); + System.out.println(result.toString()); + + } + +} diff --git a/code/LeetCode/src/loop/FizzBuzz.java b/code/LeetCode/src/loop/FizzBuzz.java new file mode 100644 index 00000000..15f94c74 --- /dev/null +++ b/code/LeetCode/src/loop/FizzBuzz.java @@ -0,0 +1,48 @@ +package loop; + +import java.util.ArrayList; +import java.util.List; + +public class FizzBuzz { + public List fizzBuzz(int n) { + List list = new ArrayList<>(); + for (int i = 1; i <= n; i++) { + if (i % 15 == 0) { + list.add("FizzBuzz"); + } else if (i % 5 == 0) { + list.add("Buzz"); + } else if (i % 3 == 0) { + list.add("Fizz"); + } else { + list.add(Integer.toString(i)); + } + } + + return list; + } + + public List fizzBuzzWithPlus(int n) { + List list = new ArrayList<>(); + int fizz = 0; + int buzz = 0; + for (int i = 1; i <= n; i++) { + fizz++; + buzz++; + if (fizz == 3 && buzz == 5) { + list.add("FizzBuzz"); + fizz = 0; + buzz = 0; + } else if (fizz == 3) { + list.add("Fizz"); + fizz = 0; + } else if (buzz == 5) { + list.add("Buzz"); + buzz = 0; + } else { + list.add(Integer.toString(i)); + } + } + + return list; + } +} diff --git a/code/LeetCode/src/node/AddTwoNumbers.java b/code/LeetCode/src/node/AddTwoNumbers.java new file mode 100644 index 00000000..eb47bee0 --- /dev/null +++ b/code/LeetCode/src/node/AddTwoNumbers.java @@ -0,0 +1,64 @@ +package node; + +import common.ListNode; + +// https://leetcode.com/problems/add-two-numbers/ +public class AddTwoNumbers { + public ListNode addTwoNumbersWithTidyStyle(ListNode l1, ListNode l2) { + ListNode dummyHead = new ListNode(0); + ListNode current = dummyHead; + int carry = 0; + int sum; + while (l1 != null || l2 != null) { + sum = (l1 != null ? l1.val : 0) + (l2 != null ? l2.val : 0) + carry; + current.next = new ListNode(sum % 10); + carry = sum / 10; + l1 = l1 != null ? l1.next : l1; + l2 = l2 != null ? l2.next : l2; + current = current.next; + } + if (carry == 1) { + current.next = new ListNode(1); + } + + return dummyHead.next; + } + + public ListNode addTwoNumbers(ListNode l1, ListNode l2) { + ListNode head = new ListNode(0); + ListNode result = head; + int carry = 0; + int sum; + // sum for every two Node's value, mark carry + while (l1 != null && l2 != null) { + sum = l1.val + l2.val + carry; + head.next = new ListNode(sum % 10); + carry = sum / 10; + l1 = l1.next; + l2 = l2.next; + head = head.next; + } + + // add carry for left item + ListNode leftListNode = l1 != null ? l1 : l2; + while (leftListNode != null) { + if (carry == 0) { + head.next = leftListNode; + break; + } + sum = leftListNode.val + carry; + head.next = new ListNode(sum % 10); + carry = sum / 10; + leftListNode = leftListNode.next; + head = head.next; + } + + // consider the last item still have carry, add new one + if (carry == 1) { + head.next = new ListNode(1); + head = head.next; + } + + return result.next; + } +} diff --git a/code/LeetCode/src/node/DeleteNodeInALinkedList.java b/code/LeetCode/src/node/DeleteNodeInALinkedList.java new file mode 100644 index 00000000..dc2df324 --- /dev/null +++ b/code/LeetCode/src/node/DeleteNodeInALinkedList.java @@ -0,0 +1,11 @@ +package node; + +import common.ListNode; + +// https://leetcode.com/problems/delete-node-in-a-linked-list/ +public class DeleteNodeInALinkedList { + public void deleteNode(ListNode node) { + node.val = node.next.val; + node.next = node.next.next; + } +} diff --git a/code/LeetCode/src/node/IntersectionOfTwoLinkedLists.java b/code/LeetCode/src/node/IntersectionOfTwoLinkedLists.java new file mode 100644 index 00000000..715f03d0 --- /dev/null +++ b/code/LeetCode/src/node/IntersectionOfTwoLinkedLists.java @@ -0,0 +1,54 @@ +package node; + +import common.ListNode; + +// https://leetcode.com/problems/intersection-of-two-linked-lists/ +public class IntersectionOfTwoLinkedLists { + + public static ListNode getIntersectionNodeWithLoopOtherHead(ListNode headA, ListNode headB) { + //boundary check + if(headA == null || headB == null) return null; + + ListNode a = headA; + ListNode b = headB; + + //if a & b have different len, then we will stop the loop after second iteration + while( a != b){ + //for the end of first iteration, we just reset the pointer to the head of another linkedlist + a = a == null? headB : a.next; + b = b == null? headA : b.next; + } + + return a; + } + + public static ListNode getIntersectionNodeWithClipToSameLength(ListNode headA, ListNode headB) { + int lenA = getNodeLength(headA); + int lenB = getNodeLength(headB); + while (lenA > lenB) { + lenA--; + headA = headA.next; + } + while (lenB > lenA) { + lenB--; + headB = headB.next; + } + while (headA != headB) { + headA = headA.next; + headB = headB.next; + } + + return headA; + } + + public static int getNodeLength(ListNode head) { + int len = 0; + while (head != null) { + len++; + head = head.next; + } + + return len; + } + +} diff --git a/code/LeetCode/src/node/LinkedListCycle.java b/code/LeetCode/src/node/LinkedListCycle.java new file mode 100644 index 00000000..aae1163e --- /dev/null +++ b/code/LeetCode/src/node/LinkedListCycle.java @@ -0,0 +1,37 @@ +package node; + +import common.ListNode; + +import java.util.HashSet; +import java.util.Set; + +// https://leetcode.com/problems/linked-list-cycle/ +public class LinkedListCycle { + + public boolean hasCycle(ListNode head) { + ListNode fast = head; + ListNode slow = head; + do { + if (fast == null || fast.next == null) { + return false; + } + fast = fast.next.next; + slow = slow.next; + } while (fast != slow); + + return true; + } + + public boolean hasCycleWithSet(ListNode head) { + Set set = new HashSet<>(); + while (head != null) { + if (set.contains(head)) { + return true; + } + set.add(head); + head = head.next; + } + + return false; + } +} diff --git a/code/LeetCode/src/node/MergeTwoSortedLists.java b/code/LeetCode/src/node/MergeTwoSortedLists.java new file mode 100644 index 00000000..1017af54 --- /dev/null +++ b/code/LeetCode/src/node/MergeTwoSortedLists.java @@ -0,0 +1,55 @@ +package node; + +import common.ListNode; + +// https://leetcode.com/problems/merge-two-sorted-lists/ +public class MergeTwoSortedLists { + + public ListNode mergeTwoLists(ListNode l1, ListNode l2) { + ListNode list = new ListNode(0); + ListNode head = list; + while (l1 != null && l2 != null) { + if (l1.val < l2.val) { + list.next = new ListNode(l1.val); + l1 = l1.next; + } else { + list.next = new ListNode(l2.val); + l2 = l2.next; + } + list = list.next; + + } + + while (l1 != null) { + list.next = new ListNode(l1.val); + list = list.next; + l1 = l1.next; + } + + while (l2 != null) { + list.next = new ListNode(l2.val); + list = list.next; + l2 = l2.next; + } + + return head.next; + } + + + public ListNode mergeTwoListsWithRecursive(ListNode l1, ListNode l2) { + if (l1 == null) { + return l2; + } + if (l2 == null) { + return l1; + } + if (l1.val < l2.val) { + l1.next = mergeTwoListsWithRecursive(l1.next, l2); + return l1; + } else { + l2.next = mergeTwoListsWithRecursive(l1, l2.next); + return l2; + } + } + +} diff --git a/code/LeetCode/src/node/PalindromeLinkedList.java b/code/LeetCode/src/node/PalindromeLinkedList.java new file mode 100644 index 00000000..efcc8c6e --- /dev/null +++ b/code/LeetCode/src/node/PalindromeLinkedList.java @@ -0,0 +1,69 @@ +package node; + +import common.ListNode; + +import java.util.Stack; + +// https://leetcode.com/problems/palindrome-linked-list/ +public class PalindromeLinkedList { + + public boolean isPalindrome(ListNode head) { + ListNode l1 = head; + Stack stack = new Stack<>(); + while (l1 != null) { + stack.push(l1.val); + l1 = l1.next; + } + + ListNode l2 = head; + int c; + int half = stack.size() >> 1; + int count = 0; + while (l2 != null && count < half) { + c = stack.pop(); + if (c != l2.val) { + return false; + } + l2 = l2.next; + count++; + } + + return true; + } + + public boolean isPalindromeWithSlowFastStep(ListNode head) { + ListNode slow = head, fast = head; + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + } + if (fast != null) { + slow = slow.next; + } + fast = head; + slow = reverse(slow); + while (slow != null) { + if (fast.val != slow.val) { + return false; + } + slow = slow.next; + fast = fast.next; + } + + return true; + } + + private ListNode reverse(ListNode slow) { + ListNode pre = null; + ListNode next; + while (slow != null) { + next = slow.next; + slow.next = pre; + pre = slow; + slow = next; + } + + return pre; + } + +} diff --git a/code/LeetCode/src/node/RemoveNthNodeFromEndOfList.java b/code/LeetCode/src/node/RemoveNthNodeFromEndOfList.java new file mode 100644 index 00000000..0cb93a6c --- /dev/null +++ b/code/LeetCode/src/node/RemoveNthNodeFromEndOfList.java @@ -0,0 +1,32 @@ +package node; + +import common.ListNode; + +// https://leetcode.com/problems/remove-nth-node-from-end-of-list/ +public class RemoveNthNodeFromEndOfList { + + public static void main(String[] args) { + RemoveNthNodeFromEndOfList obj = new RemoveNthNodeFromEndOfList(); + int[] intArray = {1, 2, 3, 4, 5}; + ListNode node = ListNode.listNodeWithIntArray(intArray); + obj.removeNthFromEnd(node, 2); + } + + public ListNode removeNthFromEnd(ListNode head, int n) { + ListNode slow = new ListNode(0); + slow.next = head; + ListNode slowHead = slow; + ListNode fast = slow; + // add one more head Node, so need one step forward + for (int i = 0; i <= n; i++) { + fast = fast.next; + } + while (fast != null) { + slow = slow.next; + fast = fast.next; + } + slow.next = slow.next.next; + + return slowHead.next; + } +} diff --git a/code/LeetCode/src/node/ReverseLinkedList.java b/code/LeetCode/src/node/ReverseLinkedList.java new file mode 100644 index 00000000..9f6ec70e --- /dev/null +++ b/code/LeetCode/src/node/ReverseLinkedList.java @@ -0,0 +1,48 @@ +package node; + +import common.ListNode; + +// https://leetcode.com/problems/reverse-linked-list/ +public class ReverseLinkedList { + + public ListNode reverseList(ListNode head) { + ListNode node = head; + ListNode pre = null; + ListNode next; + while (node != null) { + next = node.next; + node.next = pre; + pre = node; + node = next; + } + + return pre; + } + + public ListNode reverseListWithRecursive(ListNode head) { + return helperReverseListWithRecursive(head, null); + } + + private ListNode helperReverseListWithRecursive(ListNode current, ListNode pre) { + // terminate condition + if (current == null) { + return pre; + } + ListNode next = current.next; + current.next = pre; + pre = current; + current = next; + return helperReverseListWithRecursive(current, pre); + } + + // reverse direct: node.next.next = node + public ListNode reverseListWithRecursiveTricky(ListNode head) { + if (head == null || head.next == null) { + return head; + } + ListNode p = reverseListWithRecursiveTricky(head.next); + head.next.next = head; + head.next = null; + return p; + } +} diff --git a/code/LeetCode/src/number/ContainsDuplicate.java b/code/LeetCode/src/number/ContainsDuplicate.java new file mode 100644 index 00000000..47269723 --- /dev/null +++ b/code/LeetCode/src/number/ContainsDuplicate.java @@ -0,0 +1,19 @@ +package number; + +import java.util.HashSet; +import java.util.Set; + +// https://leetcode.com/problems/contains-duplicate/ +public class ContainsDuplicate { + public boolean containsDuplicate(int[] nums) { + Set set = new HashSet<>(); + for (int i : nums) { + if (set.contains(i)) { + return true; + } + set.add(i); + } + + return false; + } +} diff --git a/code/LeetCode/src/number/CountPrime.java b/code/LeetCode/src/number/CountPrime.java new file mode 100644 index 00000000..ebfa7159 --- /dev/null +++ b/code/LeetCode/src/number/CountPrime.java @@ -0,0 +1,67 @@ +package number; + +import java.util.ArrayList; +import java.util.List; + +public class CountPrime { + public static int countPrimes(int n) { + List list = new ArrayList<>(); + if (n > 2) { + list.add(2); + } + for (int i = 3; i < n; i++) { + for (int k: list) { + if (i % k == 0) { + break; + } + if (k > i / k) { + list.add(i); + break; + } + } + } + + System.out.println(list); + return list.size(); + } + + public int countPrimesWithBoolArray(int n) { + if (n < 3) { + return 0; + } + boolean[] array = new boolean[n]; + int count = 0; + for (int i = 2; i < n; i++) { + if (array[i] == false) { + count++; + for (int k = 2; i * k < n; k++) { + array[i * k] = true; + } + } + } + + return count; + } + + public int countPrimesWithReduseEven(int n){ + if (n < 3) { + return 0; + } + boolean[] evenArray = new boolean[n]; + // Arrays.fill(evenArray, true); boolean[] are initialed as false by default + int count = n / 2; + for (int i = 3; i * i < n; i += 2) { + if (evenArray[i]) { + continue; + } + for(int k = i * i; k < n; k = k + i * 2) { + if (evenArray[k] == false) { + evenArray[k] = true; + count--; + } + } + } + + return count; + } +} diff --git a/code/LeetCode/src/number/FactorialTrailingZeroes.java b/code/LeetCode/src/number/FactorialTrailingZeroes.java new file mode 100644 index 00000000..35820394 --- /dev/null +++ b/code/LeetCode/src/number/FactorialTrailingZeroes.java @@ -0,0 +1,18 @@ +package number; + +// https://leetcode.com/problems/factorial-trailing-zeroes/ +public class FactorialTrailingZeroes { + public int trailingZeroes(int n) { + int count = 0; + while (n > 0) { + n = n / 5; + count += n; + } + + return count; + } + + public int trailingZeroesWithRecursive(int n) { + return n == 0 ? 0 : n / 5 + trailingZeroesWithRecursive(n / 5); + } +} diff --git a/code/LeetCode/src/number/HappyNumber.java b/code/LeetCode/src/number/HappyNumber.java new file mode 100644 index 00000000..fd641e0b --- /dev/null +++ b/code/LeetCode/src/number/HappyNumber.java @@ -0,0 +1,90 @@ +package number; + +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Queue; +import java.util.Set; + +// https://leetcode.com/problems/happy-number/ +public class HappyNumber { + public boolean isHappy(int n) { + // record pass number, validate whether is cycle + Set set = new HashSet<>(); + // current number + Queue queue = new LinkedList<>(); + set.add(n); + queue.add(n); + // sum + int sum; + int current; + int remainder; + while (!queue.isEmpty()) { + current = queue.poll(); + sum = 0; + while (current != 0) { + remainder = current % 10; + sum += remainder * remainder; + current = current / 10; + } + if (sum == 1) { + return true; + } + if (set.contains(sum)) { + return false; + } + queue.add(sum); + set.add(sum); + } + + return false; + } + + public boolean isHappyWithSet(int n) { + // valid whether is loop + Set isLoopSet = new HashSet<>(); + int current = n; + int sum; + int remainder; + while (isLoopSet.add(current)) { + sum = 0; + while (current != 0) { + remainder = current % 10; + sum += remainder * remainder; + current = current / 10; + } + if (sum == 1) { + return true; + } + current = sum; + } + + return false; + } + + public boolean isHappyWithoutSet(int n) { + int slow = n; + int fast = n; + int maxCount = Integer.MAX_VALUE; + + do { + slow = calculateHappy(slow); + fast = calculateHappy(fast); + fast = calculateHappy(fast); + maxCount--; + } while (slow != fast && maxCount > 0); + + return slow == 1; + } + + public int calculateHappy(int current) { + int sum = 0; + int remainder; + while (current != 0) { + remainder = current % 10; + sum += remainder * remainder; + current = current / 10; + } + + return sum; + } +} diff --git a/code/LeetCode/src/number/MissingNumber.java b/code/LeetCode/src/number/MissingNumber.java new file mode 100644 index 00000000..b97ff91c --- /dev/null +++ b/code/LeetCode/src/number/MissingNumber.java @@ -0,0 +1,99 @@ +package number; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +// https://leetcode.com/problems/missing-number/ +public class MissingNumber { + + public static int missingNumber(int[] nums) { + int left = 0; + int right = nums.length - 1; + Set set = new HashSet<>(); + while (left <= right) { + set.add(nums[left]); + set.add(nums[right]); + left++; + right--; + } + left = 0; + right = nums.length; + while (left <= right) { + if (!set.contains(left)) { + return left; + } + if (!set.contains(right)) { + return right; + } + left++; + right--; + } + + return nums.length; + } + + public static int missingNumberWithSet(int[] nums) { + Set set = new HashSet<>(); + for (int i: nums) { + set.add(i); + } + + for (int i = 0; i < nums.length; i++) { + if (!set.contains(i)) { + return i; + } + } + + return nums.length; + } + + public static int missingNumberWithSum(int[] nums) { + int len = nums.length; + int result = len; + for (int i = 0; i < len; i++) { + result = result - nums[i] + i; + } + + return result; + } + + public static int missingNumberWithSort(int[] nums) { + Arrays.sort(nums); + + int len = nums.length; + // Ensure that 0 is at the first index + if (nums[0] != 0) { + return 0; + } + // Ensure that n is at the last index + if (nums[len - 1] != len) { + return len; + } + + // If we get here, then the missing number is on the range (0 , n) + for (int i = 1; i < len; i++) { + if (i != nums[i]) { + return i; + } + } + + // Array was not missing any numbers + return -1; + } + + public static int missingNumberWithBit(int[] nums) { + int missing = nums.length; + for (int i = 0; i < nums.length; i++) { + missing ^= i ^ nums[i]; + } + + return missing; + } + + + public static void main(String[] args) { + int[] input = new int[]{3,0,1}; + int result = missingNumber(input); + } +} diff --git a/code/LeetCode/src/number/PowerOfThree.java b/code/LeetCode/src/number/PowerOfThree.java new file mode 100644 index 00000000..6e2a0ada --- /dev/null +++ b/code/LeetCode/src/number/PowerOfThree.java @@ -0,0 +1,15 @@ +package number; + +// https://leetcode.com/problems/power-of-three/ +public class PowerOfThree { + public boolean isPowerOfThree(int n) { + if (n <= 0) { + return false; + } + while (n % 3 == 0) { + n = n / 3; + } + + return n == 1; + } +} diff --git a/code/LeetCode/src/number/ReverseInteger.java b/code/LeetCode/src/number/ReverseInteger.java new file mode 100644 index 00000000..62dee99a --- /dev/null +++ b/code/LeetCode/src/number/ReverseInteger.java @@ -0,0 +1,25 @@ +package number; + +// https://leetcode.com/problems/reverse-integer/ +public class ReverseInteger { + public int reverse(int x) { + int result = 0; + int pop; + int maxIntDivideTen = Integer.MAX_VALUE / 10; + int minIntDevideTen = Integer.MIN_VALUE / 10; + while (x != 0 ) { + pop = x % 10; + // consider integer overflows, return -1 + if (result > maxIntDivideTen || (result == maxIntDivideTen && pop > 7)) { + return 0; + } else if (result < minIntDevideTen || (result == minIntDevideTen && pop < -8)) { + return 0; + } + + result = result * 10 + pop; + x = x / 10; + } + + return result; + } +} diff --git a/code/LeetCode/src/number/TwoSum.java b/code/LeetCode/src/number/TwoSum.java new file mode 100644 index 00000000..8ab71eba --- /dev/null +++ b/code/LeetCode/src/number/TwoSum.java @@ -0,0 +1,50 @@ +package number; + +import java.util.HashMap; +import java.util.Map; + +// https://leetcode.com/problems/two-sum/ +public class TwoSum { + public int[] twoSum(int[] nums, int target) { + for (int i = 0; i < nums.length; i++) { + for (int k = i + 1; k < nums.length; k++) { + if (nums[i] + nums[k] == target) { + return new int[]{nums[i], nums[k]}; + } + } + } + + return null; + } + + public int[] twoSumWithHashMap(int[] nums, int target) { + Map map = new HashMap<>(); + for (int i = 0; i < nums.length; i++) { + map.put(nums[i], i); + } + int remain; + for (int i = 0; i < nums.length; i++) { + remain = target - nums[i]; + if (map.containsKey(remain) && map.get(remain) != i) { + return new int[]{i, map.get(remain)}; + } + } + + throw new IllegalArgumentException("No two sum solution"); + } + + + public int[] twoSumWithMap(int[] nums, int target) { + Map map = new HashMap<>(); + int remain; + for (int i = 0; i < nums.length; i++) { + remain = target - nums[i]; + if (map.containsKey(nums[i])) { + return new int[]{map.get(nums[i]) , i}; + } + map.put(remain, i); + } + + throw new IllegalArgumentException("No two sum solution"); + } +} diff --git a/code/LeetCode/src/popular/CoinChange.java b/code/LeetCode/src/popular/CoinChange.java new file mode 100644 index 00000000..983e0cb1 --- /dev/null +++ b/code/LeetCode/src/popular/CoinChange.java @@ -0,0 +1,24 @@ +package popular; + +import java.util.Arrays; + +public class CoinChange { + + public static int coinChange(int[] coins, int amount) { + if (amount == 0) { + return 0; + } + int count = Integer.MAX_VALUE; + + if (count == Integer.MAX_VALUE) { + count = -1; + } + return count; + } + + public static void main(String[] args) { + int[] coins = new int[]{186, 419, 83, 408}; + int amount = 6249; + System.out.println("Output: " + coinChange(coins, amount)); + } +} diff --git a/code/LeetCode/src/popular/EightQueen.java b/code/LeetCode/src/popular/EightQueen.java new file mode 100644 index 00000000..80a407d9 --- /dev/null +++ b/code/LeetCode/src/popular/EightQueen.java @@ -0,0 +1,76 @@ +package popular; + +import java.util.Arrays; +import java.util.List; + +public class EightQueen { + + static int[] result = new int[8]; + static int count = 1; + static int step = 1; + public static void eightQueen(int row) { + // row == 8, print & return + if (row == 8) { + //print + printQueens(result); + System.out.println("------"+ count++ +"------"); + return; + } + + // for each column + for (int column = 0; column < 8; column++) { + + if (isOK(row, column)) { + result[row] = column; + System.out.println("result[" + row + "] = " + column); + eightQueen(row + 1); + } + } + + } + + public static boolean isOK(int row, int column) { + int leftUp = column - 1; + int rightUp = column + 1; + + while (--row >= 0) { + System.out.println("---step---" + step++); + // vertical direction duplicate + if (result[row] == column) { + return false; + } + // left diagonal duplicate + if (leftUp >= 0 && result[row] == leftUp) { + return false; + } + // right diagonal duplicate + if (rightUp < 8 && result[row] == rightUp) { + return false; + } + leftUp--; + rightUp++; + } + System.out.println("---step---" + step++); + + return true; + } + + public static void printQueens(int[] result) { + for (int row = 0; row < 8; row++) { + for (int column = 0; column < 8; column++) { + if (result[row] == column) { + System.out.print("Q "); + } else { + System.out.print("* "); + } + } + System.out.println(); + } + System.out.println(); + } + + public static void main(String[] args) { + //eightQueen(0); + int[] arr = {1, 2, 3, 5}; + } +} diff --git a/code/LeetCode/src/popular/InvertBinaryTree.java b/code/LeetCode/src/popular/InvertBinaryTree.java new file mode 100644 index 00000000..bafef23e --- /dev/null +++ b/code/LeetCode/src/popular/InvertBinaryTree.java @@ -0,0 +1,96 @@ +package popular; + +import java.util.LinkedList; +import java.util.Queue; + +class TreeNode { + int val; + TreeNode left; + TreeNode right; + TreeNode(int x) {val = x; } + + @Override + public String toString() { + Queue queue = new LinkedList<>(); + queue.add(this); + StringBuilder sb = new StringBuilder(); + sb.append("["); + while (!queue.isEmpty()) { + TreeNode current = queue.poll(); + sb.append(current.val).append(", "); + if (current.left != null) queue.add(current.left); + if (current.right != null) queue.add(current.right); + } + sb.append("]"); + + return sb.toString(); + } +} + +public class InvertBinaryTree { + + public TreeNode invertTree(TreeNode root) { + if (root == null) { + return root; + } + + TreeNode left = invertTree(root.left); + TreeNode right = invertTree(root.right); + root.left = right; + root.right = left; + + return root; + } + + public TreeNode invertTreeWithBreadthSearchFirst(TreeNode root) { + if (root == null) { + return root; + } + + Queue queue = new LinkedList<>(); + queue.add(root); + while (!queue.isEmpty()) { + TreeNode current = queue.poll(); + TreeNode temp =current.left; + current.left = current.right; + current.right = temp; + + if (current.left != null) queue.add(current.left); + if (current.right != null) queue.add(current.right); + } + + return root; + } + + public static TreeNode initData() { + int[] data = {4, 2, 7, 1, 3, 6, 9}; + TreeNode root = new TreeNode(4); + Queue queue = new LinkedList<>(); + queue.add(root); + for (int i = 1; i < data.length; ) { + TreeNode currentRoot = queue.poll(); + TreeNode left = new TreeNode(data[i]); + currentRoot.left = left; + queue.add(currentRoot.left); + if (i + 1 < data.length) { + TreeNode right = new TreeNode(data[++i]); + currentRoot.right = right; + queue.add(currentRoot.right); + } + i++; + } + + return root; + } + + public static void main(String[] args) { + TreeNode root = initData(); + System.out.println("Input: " + root.toString()); + InvertBinaryTree obj = new InvertBinaryTree(); + obj.invertTree(root); + System.out.println("Output: " + root.toString()); + obj.invertTreeWithBreadthSearchFirst(root); + System.out.println("Output back: " + root.toString()); + } + +} diff --git a/code/LeetCode/src/popular/JumpGame.java b/code/LeetCode/src/popular/JumpGame.java new file mode 100644 index 00000000..ad337fce --- /dev/null +++ b/code/LeetCode/src/popular/JumpGame.java @@ -0,0 +1,70 @@ +package popular; + +import java.util.Arrays; + +public class JumpGame { + + public static boolean canJump(int[] nums) { + // result memory, 1 is true; -1 is false; + int[] memo = new int[nums.length + 1]; + return helper(0, nums, memo); + } + + public static boolean helper(int position, int[] nums, int[] memo) { + if (memo[position] == 1 || position == nums.length - 1) { + return true; + } else if (memo[position] == -1) { + return false; + } + int maxPosition = Math.min(position + nums[position], nums.length - 1) ; + for(int i = maxPosition; i > position; i--) { + memo[i] = helper(i, nums, memo) ? 1 : -1; + if(memo[i] == 1) { + return true; + } + } + + return false; + } + + public static boolean canJumpWithBottomUp(int[] nums) { + // result memory, 1 is true; -1 is false; + int[] memo = new int[nums.length]; + // check if the length == 1 + memo[nums.length - 1] = 1; + + for(int i = nums.length -2; i >= 0; i--) { + int maxPosition = Math.min(i + nums[i], nums.length - 1); + for(int k = i + 1; k <= maxPosition; k++) { + if (k == nums.length - 1 || memo[k] == 1) { + memo[i] = 1; + break; + } + } + } + + return memo[0] == 1; + } + + public static boolean canJumpWithGreedy(int[] nums) { + int lastIndex = nums.length - 1; + for (int i = lastIndex - 1; i >=0 ; i--) { + if (i + nums[i] >= lastIndex) { + lastIndex = i; + } + } + + return lastIndex == 0; + } + + public static void main(String[] args) { + int[] input = {2,3,1,1,4}; + int[] input1 = {3,2,1,0,4}; + //System.out.println("intput: " + Arrays.toString(input) + '\n' + "output: " + canJump(input)); + //System.out.println("input1: " + Arrays.toString(input1) + '\n' + "output: " + canJump(input1)); + //System.out.println("intput: " + Arrays.toString(input) + '\n' + "output: " + canJumpWithBottomUp(input)); + //System.out.println("input1: " + Arrays.toString(input1) + '\n' + "output: " + canJumpWithBottomUp(input1)); + System.out.println("intput: " + Arrays.toString(input) + '\n' + "output: " + canJumpWithGreedy(input)); + System.out.println("input1: " + Arrays.toString(input1) + '\n' + "output: " + canJumpWithGreedy(input1)); + } +} diff --git a/code/LeetCode/src/popular/LinkedListCycle.java b/code/LeetCode/src/popular/LinkedListCycle.java index e3aaee12..5c5b91a1 100644 --- a/code/LeetCode/src/popular/LinkedListCycle.java +++ b/code/LeetCode/src/popular/LinkedListCycle.java @@ -1,5 +1,6 @@ package popular; + import java.util.HashSet; import java.util.Set; diff --git a/code/LeetCode/src/popular/LongestValidParentheses.java b/code/LeetCode/src/popular/LongestValidParentheses.java index 48bde804..e780ce2f 100644 --- a/code/LeetCode/src/popular/LongestValidParentheses.java +++ b/code/LeetCode/src/popular/LongestValidParentheses.java @@ -1,5 +1,6 @@ package popular; +import java.util.Arrays; import java.util.Stack; public class LongestValidParentheses { diff --git a/code/LeetCode/src/popular/MinimumPathSum.java b/code/LeetCode/src/popular/MinimumPathSum.java new file mode 100644 index 00000000..03fa4fc7 --- /dev/null +++ b/code/LeetCode/src/popular/MinimumPathSum.java @@ -0,0 +1,37 @@ +package popular; + +public class MinimumPathSum { + + public int minPathSum(int[][] grid) { + int rowLen = grid.length; + int columnLen = grid[0].length; + int[][] sumGrid = new int[rowLen][columnLen]; + + for (int row = 0; row < rowLen; row++) { + for (int column = 0; column < columnLen; column++) { + if (row == 0 && column == 0) { + // init first sum + sumGrid[0][0] = grid[0][0]; + } else if (row == 0 && column != 0) { + sumGrid[row][column] = grid[row][column] + sumGrid[row][column - 1]; + } else if (column == 0 && row != 0) { + sumGrid[row][column] = grid[row][column] + sumGrid[row - 1][column]; + } else { + sumGrid[row][column] = grid[row][column] + Math.min(sumGrid[row][column - 1], sumGrid[row - 1][column]); + } + } + } + + return sumGrid[rowLen - 1][columnLen - 1]; + } + + public static void main(String[] args) { + int[][] grid = { + {1,3,1}, + {1,5,1}, + {4,2,1} + }; + MinimumPathSum obj = new MinimumPathSum(); + System.out.println("Output: " + obj.minPathSum(grid)); + } +} diff --git a/code/LeetCode/src/popular/NQueens.java b/code/LeetCode/src/popular/NQueens.java new file mode 100644 index 00000000..150bd7b1 --- /dev/null +++ b/code/LeetCode/src/popular/NQueens.java @@ -0,0 +1,82 @@ +package popular; + +import java.util.ArrayList; +import java.util.List; + +public class NQueens { + + static int[] rowColumnArray; + + public static List> solveNQueens(int n) { + List> resultList = new ArrayList>(); + rowColumnArray = new int[n + 1]; + // from 0 to calculate + recursiveQueeen(0, n, resultList); + + return resultList; + } + + public static void recursiveQueeen(int row, int length, List> resultList) { + if (row == length) { + // print + resultList.add(addValidList(length)); + + return; + } + + for (int column = 0; column < length; column++) { + if (isOK(row, column, length)) { + rowColumnArray[row] = column; + recursiveQueeen(row + 1, length, resultList); + } + } + } + + public static boolean isOK(int row, int column, int length) { + int leftUp = column - 1; + int rightUp = column + 1; + while (--row >= 0) { + if (rowColumnArray[row] == column) { + return false; + } + if (leftUp >= 0 && rowColumnArray[row] == leftUp) { + return false; + } + if (rightUp < length && rowColumnArray[row] == rightUp) { + return false; + } + + leftUp--; + rightUp++; + } + + return true; + } + + public static List addValidList(int length) { + List list = new ArrayList<>(); + StringBuilder sb; + System.out.println(); + for (int row = 0; row < length; row++) { + sb = new StringBuilder(); + for (int column = 0; column < length; column++) { + if (rowColumnArray[row] == column) { + sb.append('Q'); + } else { + + sb.append('.'); + } + } + list.add(sb.toString()); + System.out.println(sb.toString()); + } + System.out.println(); + + return list; + } + + public static void main(String[] args) { + solveNQueens(4); + } + +} diff --git a/code/LeetCode/src/popular/NumberOfIslands.java b/code/LeetCode/src/popular/NumberOfIslands.java new file mode 100644 index 00000000..35f686a0 --- /dev/null +++ b/code/LeetCode/src/popular/NumberOfIslands.java @@ -0,0 +1,57 @@ +package popular; + +import java.util.Arrays; + +public class NumberOfIslands { + + public int numIslands(char[][] grid) { + if (grid == null || grid.length == 0 || grid[0].length == 0) { + return 0; + } + int count = 0; + int rowLen = grid.length; + int columnLen = grid[0].length; + boolean[][] visitArray = new boolean[rowLen][columnLen]; + for (int row = 0; row < rowLen; row++) { + for (int column = 0; column < columnLen; column++) { + if (grid[row][column] == '1' && visitArray[row][column] == false) { + markConnectIsland(grid, visitArray, row, column); + count++; + } + } + } + + return count; + } + + private void markConnectIsland(char[][] grid, boolean[][] visitArray, int row, int column) { + if (row < 0 || row >= grid.length) return; + if (column < 0 || column >= grid[0].length) return; + if (grid[row][column] != '1' || visitArray[row][column]) return; + + visitArray[row][column] = true; + + markConnectIsland(grid, visitArray, row + 1, column); + markConnectIsland(grid, visitArray, row - 1, column); + markConnectIsland(grid, visitArray, row, column + 1); + markConnectIsland(grid, visitArray, row, column - 1); + } + + public static void main(String[] args) { + //char[][] grid = { + // {'1', '1', '1', '1', '0'}, + // {'1', '1', '0', '1', '0'}, + // {'1', '1', '0', '0', '0'}, + // {'0', '0', '0', '0', '0'} + // }; + + char[][] grid = { + {'1', '1', '0', '0', '0'}, + {'1', '1', '0', '0', '0'}, + {'0', '0', '1', '0', '0'}, + {'0', '0', '0', '1', '1'} + }; + int count = new NumberOfIslands().numIslands(grid); + System.out.println("input: " + Arrays.toString(grid) + "\nOutput:" + count ); + } +} diff --git a/code/LeetCode/src/popular/README.md b/code/LeetCode/src/popular/README.md index 88f1e39d..d9218e48 100644 --- a/code/LeetCode/src/popular/README.md +++ b/code/LeetCode/src/popular/README.md @@ -9,6 +9,12 @@ | 239 | [Sliding Window Maximum(滑动窗口最大值)][239] | Deque, LinkedList| SlidingWindowMaximum | | 344 | [Reverse String(反转字符串)][344] | String| ReverseString | | 151 | [Reverse Words in a String(翻转字符串里的单词)][151] | String| ReverseWordsInAString | +| 226 | [Invert Binary Tree(翻转二叉树)][226] | BinaryTree| InvertBinaryTree | +| 98 | [Validate Binary Search Tree(验证二叉查找树)][98] | BinaryTree| ValidateBinarySearchTree | +| 200 | [Number of Islands(岛屿的个数)][200] | Graph| NumberOfIslands | +| 36 | [Valid Sudoku(有效的数独)][36] | Grap| ValidSudoku | +| 10 | [Regular Expression Matching(正则表达式匹配)][10] | Recursive, dynamic | RegularExpressionMatching | +| 64 | [Minimum Path Sum(最小路径和)][64] | Recursive, dynamic | MinimumPathSum | @@ -20,3 +26,9 @@ [239]:https://blog.csdn.net/zgpeace/article/details/88372784 [344]:https://blog.csdn.net/zgpeace/article/details/88414332 [151]:https://blog.csdn.net/zgpeace/article/details/88528127 +[226]:https://blog.csdn.net/zgpeace/article/details/88578011 +[98]:https://blog.csdn.net/zgpeace/article/details/88607678 +[200]:https://blog.csdn.net/zgpeace/article/details/88658439 +[36]:https://blog.csdn.net/zgpeace/article/details/88693835 +[10]:https://blog.csdn.net/zgpeace/article/details/88742935 +[64]:https://blog.csdn.net/zgpeace/article/details/88816726 diff --git a/code/LeetCode/src/popular/RegularExpressionMatching.java b/code/LeetCode/src/popular/RegularExpressionMatching.java new file mode 100644 index 00000000..f776290b --- /dev/null +++ b/code/LeetCode/src/popular/RegularExpressionMatching.java @@ -0,0 +1,84 @@ +package popular; + +enum Result { + TRUE, FALSE; +} + +public class RegularExpressionMatching { + + public boolean isMatch(String s, String p) { + // p is empty + if (p.isEmpty()) { + return s.isEmpty(); + } + // first char firstCharMatch : 1. string first char is == , 2. or p first string == '.' + boolean firstCharMatch = s.length() >= 1 && (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.'); + // p second char == '*', 1. then isMatch(s, p.substring(2)), 2. firstCharMatch && isMatch(s.substring(1), p) + if (p.length() >= 2 && p.charAt(1) == '*') { + return isMatch(s, p.substring(2)) || (firstCharMatch && isMatch(s.substring(1), p)); + } else { + // p second char != '*', then firstCharMatch && isMatch(s.substring(1), p.substring(1)) + return firstCharMatch && isMatch(s.substring(1), p.substring(1)); + } + } + + Result[][] memo; + + public boolean isMatchWithMemory(String s, String p) { + if (p.isEmpty()) { + return s.isEmpty(); + } + + memo = new Result[s.length() + 1][p.length() + 1]; + return subMatch(0, 0, s, p); + } + + public boolean subMatch(int textIndex, int patternIndex, String text, String pattern) { + if (memo[textIndex][patternIndex] != null) { + return memo[textIndex][patternIndex] == Result.TRUE; + } + boolean result = false; + if (patternIndex == pattern.length()) { + result = textIndex == text.length(); + } else { + boolean firstCharMatch = text.length() > textIndex && + (text.charAt(textIndex) == pattern.charAt(patternIndex) || pattern.charAt(patternIndex) == '.'); + if (patternIndex + 1 < pattern.length() && pattern.charAt(patternIndex + 1) == '*') { + result = subMatch(textIndex, patternIndex + 2, text, pattern) || + (firstCharMatch && subMatch(textIndex + 1, patternIndex, text, pattern)); + } else { + result = firstCharMatch && subMatch(textIndex + 1, patternIndex + 1, text, pattern); + } + } + + memo[textIndex][patternIndex] = result ? Result.TRUE : Result.FALSE; + + return result; + } + + + public static void main(String[] args) { + RegularExpressionMatching obj = new RegularExpressionMatching(); + String s = "aa"; + String p = "a"; + System.out.println("Output: " + obj.isMatch(s, p)); + System.out.println("isMatchWithMemory Output: " + obj.isMatchWithMemory(s, p)); + String s1 = "aa"; + String p1 = "a*"; + System.out.println("Output1: " + obj.isMatch(s1, p1)); + System.out.println("isMatchWithMemory Output1: " + obj.isMatchWithMemory(s1, p1)); + String s2 = "ab"; + String p2 = ".*"; + System.out.println("Output2: " + obj.isMatch(s2, p2)); + System.out.println("isMatchWithMemory Output2: " + obj.isMatchWithMemory(s2, p2)); + String s3 = "aab"; + String p3 = "c*a*b"; + System.out.println("Output3: " + obj.isMatch(s3, p3)); + System.out.println("isMatchWithMemory Output3: " + obj.isMatchWithMemory(s3, p3)); + String s4 = "mississippi"; + String p4 = "mis*is*p*."; + System.out.println("Output4: " + obj.isMatch(s4, p4)); + System.out.println("isMatchWithMemory Output4: " + obj.isMatchWithMemory(s4, p4)); + + } +} diff --git a/code/LeetCode/src/popular/ReverseLinkedList.java b/code/LeetCode/src/popular/ReverseLinkedList.java new file mode 100644 index 00000000..db87eae2 --- /dev/null +++ b/code/LeetCode/src/popular/ReverseLinkedList.java @@ -0,0 +1,56 @@ +package popular; + +import common.ListNode; + + +public class ReverseLinkedList { + public ListNode reverseList(ListNode head) { + ListNode current = null; + ListNode previous = null; + while (head != null) { + previous = current; + current = new ListNode(head.val); + current.next = previous; + head = head.next; + } + + return current; + } + + public ListNode reverseListWithoutChangeHead(ListNode head) { + ListNode current = head; + ListNode previous = null; + ListNode nextNode; + while (current != null) { + nextNode = current.next; + current.next = previous; + previous = current; + current = nextNode; + } + + return previous; + } + + public ListNode reverseListWithRecursive(ListNode head) { + while (head == null || head.next == null) { + return head; + } + ListNode p = reverseListWithRecursive(head.next); + head.next.next = head; + head.next = null; + + return p; + } + + public static void main(String[] args) { + int[] input = {1, 2, 3, 4, 5}; + ListNode head = ListNode.listNodeWithIntArray(input); + System.out.println("Input: " + head.toString()); + ReverseLinkedList obj = new ReverseLinkedList(); + //ListNode result = obj.reverseList(head); + //ListNode result = obj.reverseListWithoutChangeHead(head); + ListNode result = obj.reverseListWithRecursive(head); + System.out.println("Output: " + result.toString()); + } + +} diff --git a/code/LeetCode/src/popular/Sorting/HeapSort.java b/code/LeetCode/src/popular/Sorting/HeapSort.java new file mode 100644 index 00000000..89b63e54 --- /dev/null +++ b/code/LeetCode/src/popular/Sorting/HeapSort.java @@ -0,0 +1,53 @@ +package popular.Sorting; + +import java.util.Arrays; + +public class HeapSort { + + public static void heapSort(int[] data) { + // build top big heap + for (int i = data.length/2 -1; i >= 0; i--) { + // build heap + buildHeap(data, i, data.length); + } + + // change seat between the first and the last, length-- + for (int k = data.length - 1; k >=0; k--) { + // change seat between first and last one + swap(data, 0, k); + // build heap + buildHeap(data, 0, k); + } + } + + public static void buildHeap(int[] data, int nodeIndex, int length) { + int temp = data[nodeIndex]; + for (int k = nodeIndex * 2 + 1; k < length; k = k * 2 + 1) { + if (k + 1 < length && data[k] < data[k + 1]) { + k = k + 1; + } + if (data[k] > temp) { + data[nodeIndex] = data[k]; + nodeIndex = k; + } else { + break; + } + } + + data[nodeIndex] = temp; + } + + + public static void swap(int[] data, int i, int j) { + int temp = data[i]; + data[i] = data[j]; + data[j] = temp; + } + + public static void main(String[] args) { + int[] data = new int[]{4, 6, 5, 3, 7, 1, 2}; + System.out.println(Arrays.toString(data)); + heapSort(data); + System.out.println(Arrays.toString(data)); + } +} diff --git a/code/LeetCode/src/popular/Sorting/InsertionSort.java b/code/LeetCode/src/popular/Sorting/InsertionSort.java new file mode 100644 index 00000000..4f3af785 --- /dev/null +++ b/code/LeetCode/src/popular/Sorting/InsertionSort.java @@ -0,0 +1,26 @@ +package popular.Sorting; + +import java.util.Arrays; + +public class InsertionSort { + + public void insertSort(int[] data) { + for (int i = 1; i < data.length; i++) { + int currentNumber = data[i]; + int j = i - 1; + while (j >= 0 && data[j] > currentNumber) { + data[j + 1] = data[j]; + j--; + } + data[j+1] = currentNumber; + } + } + + public static void main(String[] args) { + int[] data = new int[]{4, 6, 5, 3, 7, 1, 2}; + System.out.println(Arrays.toString(data)); + InsertionSort obj = new InsertionSort(); + obj.insertSort(data); + System.out.println(Arrays.toString(data)); + } +} diff --git a/code/LeetCode/src/popular/Sorting/MergeSort.java b/code/LeetCode/src/popular/Sorting/MergeSort.java new file mode 100644 index 00000000..cc8ad79d --- /dev/null +++ b/code/LeetCode/src/popular/Sorting/MergeSort.java @@ -0,0 +1,58 @@ +package popular.Sorting; + +import java.util.Arrays; + +public class MergeSort { + + public void mergeSort(int[] data) { + int[] temp = new int[data.length]; + subMergeSort(data, 0, data.length - 1, temp); + } + + + public void subMergeSort(int[] data, int left, int right, int[] temp) { + if (left < right) { + int mid = left + (right - left) / 2; + subMergeSort(data, left, mid, temp); + subMergeSort(data, mid + 1, right, temp); + merge(data, left, mid, right, temp); + } + } + + public void merge(int[] data, int left, int mid, int right, int[] temp) { + int i = left; + int k = mid + 1; + int t = 0; + while (i <= mid && k <= right) { + if (data[i] < data[k]) { + temp[t++] = data[i++]; + } else { + temp[t++] = data[k++]; + } + } + + while (i <= mid) { + temp[t++] = data[i++]; + } + + while (k <= right) { + temp[t++] = data[k++]; + } + + t = 0; + while (left <= right) { + data[left++] = temp[t++]; + } + + } + + public static void main(String[] args) { + int[] data = new int[]{4, 6, 5, 3, 7, 1, 2}; + System.out.println(Arrays.toString(data)); + MergeSort obj = new MergeSort(); + obj.mergeSort(data); + System.out.println(Arrays.toString(data)); + } + + +} diff --git a/code/LeetCode/src/popular/Sorting/QuickSort.java b/code/LeetCode/src/popular/Sorting/QuickSort.java new file mode 100644 index 00000000..fd18015f --- /dev/null +++ b/code/LeetCode/src/popular/Sorting/QuickSort.java @@ -0,0 +1,88 @@ +package popular.Sorting; + +import java.util.Arrays; + +public class QuickSort { + + public static void quickSort(int[] data) { + // divide to left, right index + subQuickSort(data, 0, data.length - 1); + } + + public static void subQuickSort(int[] data, int leftIndex, int rightIndex) { + if (leftIndex >= rightIndex) { + return; + } + + // pivot data: mid of the three number, and swap to right -1 + buildPivotCloseToRight(data, leftIndex, rightIndex); + + int i = leftIndex; + int k = rightIndex - 1; + int pivot = data[k]; + // two point from two side, ++left, --right + while (true) { + + // while ++left > pivot + while ((i+1) < rightIndex && data[++i] < pivot) { + + } + + // while --right < pivot + while ((k - 1) > leftIndex && data[--k] > pivot) { + + } + + // left < right, then swap + if (i < k) { + swap(data, i, k); + } else { + break; + } + } + + // if left < pivotIndex ,swap + if (i < rightIndex - 1) { + swap(data, i, rightIndex - 1); + } + + // divide two sub quick sort + subQuickSort(data, leftIndex, i); + subQuickSort(data, i + 1, rightIndex); + + } + + public static void buildPivotCloseToRight(int[] data, int leftIndex, int rightIndex) { + int midIndex = leftIndex + (rightIndex - leftIndex) / 2; + // swap small in left, between left, mid + if (data[leftIndex] > data[midIndex]) { + swap(data, leftIndex, midIndex); + } + + // swap small in left, between left, right + if (data[leftIndex] > data[rightIndex]) { + swap(data, leftIndex, rightIndex); + } + + // swap big in right, between mid, right + if (data[midIndex] > data[rightIndex]) { + swap(data, midIndex, rightIndex); + } + + // swap pivot int right -1 + swap(data, midIndex, rightIndex - 1); + } + + public static void swap(int[] data, int i, int k) { + int temp = data[i]; + data[i] = data[k]; + data[k] = temp; + } + + public static void main(String[] args) { + int[] data = new int[]{4, 6, 5, 3, 7, 1, 2}; + System.out.println(Arrays.toString(data)); + quickSort(data); + System.out.println(Arrays.toString(data)); + } +} diff --git a/code/LeetCode/src/popular/ValidSudoku.java b/code/LeetCode/src/popular/ValidSudoku.java new file mode 100644 index 00000000..bc92ad3c --- /dev/null +++ b/code/LeetCode/src/popular/ValidSudoku.java @@ -0,0 +1,60 @@ +package popular; + +import java.util.HashSet; +import java.util.Set; + +public class ValidSudoku { + + public boolean isValidSudoku(char[][] board) { + Set visitSet = new HashSet<>(81); + for (int row = 0; row < 9; row++) { + for (int column = 0; column < 9; column++) { + char data = board[row][column]; + if (data == '.') { + continue; + } + if (!visitSet.add(data + " row " + row)) { + System.out.println("duplicate board[" + row + "][" + column + "]" + " ;data: " + data+ " row " + row); + return false; + } + if (!visitSet.add(data + " column " + column)) { + System.out.println("duplicate board[" + row + "][" + column + "]" + " ;data: " + data+ " column " + column); + return false; + } + if (!visitSet.add(data + " cube " + row/3 + '-' + column/3) ) { + System.out.println("duplicate board[" + row + "][" + column + "]" + " ;data: " + data+ " cube " + row/3 + '-' + column/3); + return false; + } + } + } + + return true; + } + + public static void main(String[] args) { + char[][] board1 = { + {'5','3','.','.','7','.','.','.','.'}, + {'6','.','.','1','9','5','.','.','.'}, + {'.','9','8','.','.','.','.','6','.'}, + {'8','.','.','.','6','.','.','.','3'}, + {'4','.','.','8','.','3','.','.','1'}, + {'7','.','.','.','2','.','.','.','6'}, + {'.','6','.','.','.','.','2','8','.'}, + {'.','.','.','4','1','9','.','.','5'}, + {'.','.','.','.','8','.','.','7','9'}}; + char[][] board2 = { + {'8','3','.','.','7','.','.','.','.'}, + {'6','.','.','1','9','5','.','.','.'}, + {'.','9','8','.','.','.','.','6','.'}, + {'8','.','.','.','6','.','.','.','3'}, + {'4','.','.','8','.','3','.','.','1'}, + {'7','.','.','.','2','.','.','.','6'}, + {'.','6','.','.','.','.','2','8','.'}, + {'.','.','.','4','1','9','.','.','5'}, + {'.','.','.','.','8','.','.','7','9'}}; + ValidSudoku obj = new ValidSudoku(); + System.out.println("Output 1: " + obj.isValidSudoku(board1)); + System.out.println("Output 2: " + obj.isValidSudoku(board2)); + + } +} diff --git a/code/LeetCode/src/popular/ValidateBinarySearchTree.java b/code/LeetCode/src/popular/ValidateBinarySearchTree.java new file mode 100644 index 00000000..56bdffe2 --- /dev/null +++ b/code/LeetCode/src/popular/ValidateBinarySearchTree.java @@ -0,0 +1,25 @@ +package popular; + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ + +public class ValidateBinarySearchTree { + public boolean isValidBST(TreeNode root) { + return subIsValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE); + } + + public boolean subIsValidBST(TreeNode root, long minValue, long maxValue) { + if (root == null) { + return true; + } + if (root.val >= maxValue || root.val <= minValue) return false; + return subIsValidBST(root.left, minValue, root.val) && subIsValidBST(root.right, root.val, maxValue); + } +} diff --git a/code/LeetCode/src/stack/MinStack.java b/code/LeetCode/src/stack/MinStack.java new file mode 100644 index 00000000..c142f168 --- /dev/null +++ b/code/LeetCode/src/stack/MinStack.java @@ -0,0 +1,119 @@ +package stack; + +import java.util.Stack; + +class MinStackWithNode { + Node head; + + public void push(int x) { + if (head == null) { + head = new Node(x, x, null); + } else { + head = new Node(x, Math.min(x, head.min), head); + } + } + + public void pop() { + head = head.next; + } + + public int top() { + return head.val; + } + + public int getMin() { + return head.min; + } +} + +class Node { + int val; + int min = Integer.MAX_VALUE; + Node next; + + public Node(int val, int min, Node head) { + this.val = val; + this.min = min; + this.next = head; + } +} + +class MinsStackWithOneStack { + // data stack + Stack stack = new Stack<>(); + int min = Integer.MAX_VALUE; + + /* + if x <= min, then push min, and set min = x; + */ + public void push(int x) { + if (x <= min) { + stack.push(min); + min = x; + } + + stack.push(x); + } + + public void pop() { + if (stack.pop() == min) { + min = stack.pop(); + } + } + + public int top() { + return stack.peek(); + } + + public int getMin() { + return min; + } +} + +public class MinStack { + // data stack + Stack dataStack; + // min stack + Stack minStack; + + /** initialize your data structure here. */ + public MinStack() { + dataStack = new Stack<>(); + minStack = new Stack<>(); + } + + public void push(int x) { + dataStack.push(x); + if (minStack.size() == 0 || minStack.peek() >= x) { + minStack.push(x); + } + } + + public void pop() { + if (dataStack.size() > 0) { + int d = dataStack.pop(); + if (minStack.size() > 0 && minStack.peek() == d) { + minStack.pop(); + } + } + + } + + public int top() { + if (dataStack.size() > 0) { + return dataStack.peek(); + } + // data is empty + return -1; + } + + public int getMin() { + if (minStack.size() > 0) { + return minStack.peek(); + } + + // data is empty + return -1; + } +} + diff --git a/code/LeetCode/src/stack/ValidParentheses.java b/code/LeetCode/src/stack/ValidParentheses.java new file mode 100644 index 00000000..dd7aa712 --- /dev/null +++ b/code/LeetCode/src/stack/ValidParentheses.java @@ -0,0 +1,34 @@ +package stack; + +import java.util.HashMap; +import java.util.Map; +import java.util.Stack; + +// https://leetcode.com/problems/valid-parentheses/ +public class ValidParentheses { + public boolean isValid(String s) { + Map map = new HashMap<>(); + map.put(']', '['); + map.put('}', '{'); + map.put(')', '('); + Stack stack = new Stack<>(); + for (char c: s.toCharArray()) { + if (c == '[' || c == '(' || c == '{') { + stack.push(c); + continue; + } + + if (stack.isEmpty()) { + return false; + } + + char pre = stack.pop(); + if (map.get(c) != pre) { + return false; + } + } + + return stack.isEmpty(); + } + +} diff --git a/code/LeetCode/src/tree/BalancedBinaryTree.java b/code/LeetCode/src/tree/BalancedBinaryTree.java new file mode 100644 index 00000000..3724f76a --- /dev/null +++ b/code/LeetCode/src/tree/BalancedBinaryTree.java @@ -0,0 +1,55 @@ +package tree; + +import common.TreeNode; +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ + +// https://leetcode.com/problems/balanced-binary-tree/ +public class BalancedBinaryTree { + + public boolean isBalanced(TreeNode root) { + if (root == null) { + return true; + } + + return Math.abs(depth(root.left) - depth(root.right)) <= 1 && isBalanced(root.left) && isBalanced(root.right); + } + + public int depth(TreeNode node) { + if (node == null) { + return 0; + } + + return Math.max(depth(node.left), depth(node.right)) + 1; + } + + + public boolean isBalancedWithDfsDepth(TreeNode root) { + return dfsDepth(root) != -1; + } + + public int dfsDepth(TreeNode node) { + if (node == null) { + return 0; + } + int leftDepth = dfsDepth(node.left); + if (leftDepth == -1) { + return -1; + } + int rightDepth = dfsDepth(node.right); + if (rightDepth == -1) { + return -1; + } + if (Math.abs(leftDepth - rightDepth) > 1) { + return -1; + } + return Math.max(leftDepth, rightDepth) + 1; + } +} diff --git a/code/LeetCode/src/tree/BinaryTreePaths.java b/code/LeetCode/src/tree/BinaryTreePaths.java new file mode 100644 index 00000000..781e73ce --- /dev/null +++ b/code/LeetCode/src/tree/BinaryTreePaths.java @@ -0,0 +1,69 @@ +package tree; + +import common.TreeNode; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Stack; + +// https://leetcode.com/problems/binary-tree-paths/ +public class BinaryTreePaths { + + public List binaryTreePaths(TreeNode root) { + if (root == null) { + return Collections.emptyList(); + } + List list = new ArrayList<>(); + dfs("", root, list); + + return list; + } + + private void dfs(String s, TreeNode root, List list) { + s += Integer.toString(root.val); + + if (root.left == null && root.right == null) { + list.add(s); + } + s += "->"; + if (root.left != null) { + dfs(s, root.left, list); + } + if (root.right != null) { + dfs(s, root.right, list); + } + } + + public List binaryTreePathsWithStack(TreeNode root) { + if (root == null) { + return Collections.emptyList(); + } + Stack stack = new Stack<>(); + Stack pathStack = new Stack<>(); + stack.push(root); + TreeNode current; + List list = new ArrayList<>(); + String s = ""; + pathStack.push(s); + while (!stack.isEmpty()) { + current = stack.pop(); + s = pathStack.pop(); + s += Integer.toString(current.val); + if (current.left == null && current.right == null) { + list.add(s); + } + s += "->"; + if (current.left != null) { + stack.push(current.left); + pathStack.push(s); + } + if (current.right != null) { + stack.push(current.right); + pathStack.push(s); + } + } + + return list; + } +} diff --git a/code/LeetCode/src/tree/ConvertBSTToGreaterTree.java b/code/LeetCode/src/tree/ConvertBSTToGreaterTree.java new file mode 100644 index 00000000..db2469de --- /dev/null +++ b/code/LeetCode/src/tree/ConvertBSTToGreaterTree.java @@ -0,0 +1,60 @@ +package tree; + +import common.TreeNode; + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ + +// https://leetcode.com/problems/convert-bst-to-greater-tree/ +public class ConvertBSTToGreaterTree { + + private int sum = 0; + + public TreeNode convertBST(TreeNode root) { + if (root != null) { + convertBST(root.right); + sum += root.val; + root.val = sum; + convertBST(root.left); + } + + return root; + } + + public static void main(String[] args) { + //TreeNode left1 = new TreeNode(2); + //TreeNode right1 = new TreeNode(13); + // + //TreeNode root = new TreeNode(5, left1, right1); + + TreeNode left1 = new TreeNode(1); + TreeNode right1 = new TreeNode(3); + + TreeNode rootLeft = new TreeNode(2, left1, right1); + + TreeNode left2 = new TreeNode(6); + TreeNode right2 = new TreeNode(15); + + TreeNode rootRight = new TreeNode(13, left2, right2); + + TreeNode root = new TreeNode(5, rootLeft, rootRight); + + root.toString(); + ConvertBSTToGreaterTree obj = new ConvertBSTToGreaterTree(); + TreeNode result = obj.convertBST(root); + result.toString(); + } +} diff --git a/code/LeetCode/src/tree/ConvertSortedArrayToBinarySearchTree.java b/code/LeetCode/src/tree/ConvertSortedArrayToBinarySearchTree.java new file mode 100644 index 00000000..8e816927 --- /dev/null +++ b/code/LeetCode/src/tree/ConvertSortedArrayToBinarySearchTree.java @@ -0,0 +1,94 @@ +package tree; + +import common.TreeNode; + +import java.util.LinkedList; +import java.util.Queue; + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ + +// https://leetcode.com/problems/convert-sorted-array-to-binary-search-tree/ +public class ConvertSortedArrayToBinarySearchTree { + // method 1: Recursive + public TreeNode sortedArrayToBST(int[] nums) { + // root == null + if (nums == null || nums.length <= 0) { + return null; + } + // recurcive select middle + return selectMiddle(0, nums.length - 1, nums); + } + + public TreeNode selectMiddle(int leftIndex, int rightIndex, int[] nums) { + // leftIndex > rightIndex, break + if (leftIndex > rightIndex) { + return null; + } + int midIndex = leftIndex + ((rightIndex - leftIndex) >> 1); + TreeNode node = new TreeNode(nums[midIndex]); + node.left = selectMiddle(leftIndex, midIndex - 1, nums); + node.right = selectMiddle(midIndex + 1, rightIndex, nums); + + return node; + } + + // method 2: Iterate + public TreeNode sortedArrayToBSTWithIterate(int[] nums) { + // root null + if (nums == null || nums.length <= 0) { + return null; + } + + // queue for: root, left, right node + LinkedList nodeList = new LinkedList<>(); + // root node + TreeNode root = new TreeNode(0); + nodeList.add(root); + // queue for: leftIndex + LinkedList leftIndexList = new LinkedList<>(); + leftIndexList.add(0); + // queue for: rightIndex + LinkedList rightIndexList = new LinkedList<>(); + rightIndexList.add(nums.length - 1); + TreeNode node; + + // Iterate nodeLisk + while (!nodeList.isEmpty()) { + node = nodeList.removeFirst(); + // mid Index + int leftIndex = leftIndexList.removeFirst(); + int rightIndex = rightIndexList.removeFirst(); + int midIndex = leftIndex + ((rightIndex - leftIndex) >> 1); + node.val = nums[midIndex]; + + // left node + if (leftIndex < midIndex) { + node.left = new TreeNode(0); + nodeList.add(node.left); + leftIndexList.add(leftIndex); + rightIndexList.add(midIndex - 1); + } + + // right node + if (rightIndex > midIndex) { + node.right = new TreeNode(0); + nodeList.add(node.right); + leftIndexList.add(midIndex + 1); + rightIndexList.add(rightIndex); + } + } + + + return root; + } + + +} diff --git a/code/LeetCode/src/tree/InvertBinaryTree.java b/code/LeetCode/src/tree/InvertBinaryTree.java new file mode 100644 index 00000000..63b23857 --- /dev/null +++ b/code/LeetCode/src/tree/InvertBinaryTree.java @@ -0,0 +1,52 @@ +package tree; + +import common.TreeNode; + +import java.util.LinkedList; +import java.util.Queue; + +// https://leetcode.com/problems/invert-binary-tree/ +public class InvertBinaryTree { + + public TreeNode invertTree(TreeNode root) { + if (root == null) { + return null; + } + + TreeNode leftNode = invertTree(root.left); + TreeNode rightNode = invertTree(root.right); + + root.left = rightNode; + root.right = leftNode; + + return root; + } + + public TreeNode invertTreeWithBFS(TreeNode root) { + if (root == null) { + return null; + } + + Queue queue = new LinkedList<>(); + queue.add(root); + TreeNode leftNode; + TreeNode currentNode; + while (!queue.isEmpty()) { + currentNode = queue.poll(); + leftNode = currentNode.left; + currentNode.left = currentNode.right; + currentNode.right = leftNode; + + if (currentNode.left != null) { + queue.add(currentNode.left); + } + if (currentNode.right != null) { + queue.add(currentNode.right); + } + + } + + return root; + } + +} diff --git a/code/LeetCode/src/tree/LowestCommonAncestorOfABinarySearchTree.java b/code/LeetCode/src/tree/LowestCommonAncestorOfABinarySearchTree.java new file mode 100644 index 00000000..a3930ad0 --- /dev/null +++ b/code/LeetCode/src/tree/LowestCommonAncestorOfABinarySearchTree.java @@ -0,0 +1,18 @@ +package tree; + +import common.TreeNode; + +// https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree +public class LowestCommonAncestorOfABinarySearchTree { + + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + + if (root.val > p.val && root.val > q.val) { + return lowestCommonAncestor(root.left, p, q); + } else if (root.val < p.val && root.val < q.val) { + return lowestCommonAncestor(root.right, p, q); + } else { + return root; + } + } +} diff --git a/code/LeetCode/src/tree/MaximumDepthOfBinaryTree.java b/code/LeetCode/src/tree/MaximumDepthOfBinaryTree.java new file mode 100644 index 00000000..9d7866a0 --- /dev/null +++ b/code/LeetCode/src/tree/MaximumDepthOfBinaryTree.java @@ -0,0 +1,43 @@ +package tree; + +import common.TreeNode; + +import java.util.LinkedList; +import java.util.Queue; + +// https://leetcode.com/problems/maximum-depth-of-binary-tree/ +public class MaximumDepthOfBinaryTree { + + public int maxDepthWithDFS(TreeNode root) { + if (root == null) { + return 0; + } + return Math.max(maxDepthWithDFS(root.left), maxDepthWithDFS(root.right)) + 1; + } + + public int maxDepthWithBFS(TreeNode root) { + int max = 0; + if (root == null) { + return max; + } + Queue queue = new LinkedList<>(); + queue.add(root); + TreeNode current; + while (!queue.isEmpty()) { + max++; + int count = queue.size(); + for (int i = 0; i < count; i++) { + current = queue.poll(); + if (current.left != null) { + queue.add(current.left); + } + + if (current.right != null) { + queue.add(current.right); + } + } + } + + return max; + } +} diff --git a/code/LeetCode/src/tree/MinimumDepthOfBinaryTree.java b/code/LeetCode/src/tree/MinimumDepthOfBinaryTree.java new file mode 100644 index 00000000..c3b1119e --- /dev/null +++ b/code/LeetCode/src/tree/MinimumDepthOfBinaryTree.java @@ -0,0 +1,68 @@ +package tree; + +import common.TreeNode; + +import java.util.LinkedList; +import java.util.Queue; + +// https://leetcode.com/problems/minimum-depth-of-binary-tree/ +public class MinimumDepthOfBinaryTree { + + // Breath First Search by iterate + public int minDepth(TreeNode root) { + if (root == null) { + return 0; + } + + Queue queue = new LinkedList<>(); + queue.add(root); + int result = 0; + int currentLength; + boolean breakFlag; + TreeNode currentNode; + while (!queue.isEmpty()) { + result++; + currentLength = queue.size(); + breakFlag = false; + for (int i = 0; i < currentLength; i++) { + currentNode = queue.poll(); + if (currentNode.left == null && currentNode.right == null) { + breakFlag = true; + break; + } + if (currentNode.left != null) { + queue.add(currentNode.left); + } + if (currentNode.right != null) { + queue.add(currentNode.right); + } + } + if (breakFlag) { + break; + } + } + + return result; + } + + // Depth First Search + public int minDepthDSF(TreeNode root) { + if (root == null) { + return 0; + } + int leftDepth = minDepth(root.left); + if (root.right == null) { + return leftDepth + 1; + } + int rightDepth = minDepth(root.right); + if (root.left == null) { + return rightDepth + 1; + } + + return Math.min(leftDepth, rightDepth) + 1; + + } + + + +} diff --git a/code/LeetCode/src/tree/PathSum.java b/code/LeetCode/src/tree/PathSum.java new file mode 100644 index 00000000..787da43e --- /dev/null +++ b/code/LeetCode/src/tree/PathSum.java @@ -0,0 +1,19 @@ +package tree; + +import common.TreeNode; + +// https://leetcode.com/problems/path-sum/ +public class PathSum { + + public boolean hasPathSum(TreeNode root, int sum) { + if (root == null) { + return false; + } + // valid root is leaf + if (root.left == null && root.right == null && root.val == sum) { + return true; + } + sum -= root.val; + return hasPathSum(root.left, sum) || hasPathSum(root.right, sum); + } +} diff --git a/code/LeetCode/src/tree/SymmetricTree.java b/code/LeetCode/src/tree/SymmetricTree.java new file mode 100644 index 00000000..ce5d3076 --- /dev/null +++ b/code/LeetCode/src/tree/SymmetricTree.java @@ -0,0 +1,53 @@ +package tree; + +import common.TreeNode; + +import java.util.LinkedList; +import java.util.Queue; + +// https://leetcode.com/problems/symmetric-tree/ +public class SymmetricTree { + + public boolean isSymmetricWithRecursive(TreeNode root) { + return isMirror(root, root); + } + + public boolean isMirror(TreeNode leftN, TreeNode rightN) { + if (leftN == null && rightN == null) { + return true; + } + if (leftN == null || rightN == null) { + return false; + } + return leftN.val == rightN.val + && isMirror(leftN.left, rightN.right) + && isMirror(leftN.right, rightN.left); + } + + public boolean isSymmetric(TreeNode root) { + Queue queue = new LinkedList<>(); + queue.add(root); + queue.add(root); + while (!queue.isEmpty()) { + TreeNode leftN = queue.poll(); + TreeNode rightN = queue.poll(); + if (leftN == null && rightN == null) { + continue; + } + if (leftN == null || rightN == null) { + return false; + } + if(leftN.val != rightN.val) { + return false; + } + + queue.add(leftN.left); + queue.add(rightN.right); + + queue.add(leftN.right); + queue.add(rightN.left); + } + + return true; + } +} diff --git a/code/LeetCode/src/tree/TreeLevelOrderBottom.java b/code/LeetCode/src/tree/TreeLevelOrderBottom.java new file mode 100644 index 00000000..01794f51 --- /dev/null +++ b/code/LeetCode/src/tree/TreeLevelOrderBottom.java @@ -0,0 +1,85 @@ +package tree; + +import common.TreeNode; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +//class TreeNode { +// int val; +// TreeNode left; +// TreeNode right; +// TreeNode(int x) { +// val = x; +// } +//} + +// https://leetcode.com/problems/binary-tree-level-order-traversal-ii/ +public class TreeLevelOrderBottom { + + public List> levelOrderBottom(TreeNode root) { + // root == null + if (root == null) { + return Collections.emptyList(); + } + + List> resultList = new ArrayList<>(); + // queue LinkedList for breadth search + LinkedList queue = new LinkedList<>(); + queue.add(root); + TreeNode currentNode; + while (!queue.isEmpty()) { + // current length + int length = queue.size(); + List list = new ArrayList<>(); + // iterate each depth + for (int i = 0; i < length; i++) { + currentNode = queue.pop(); + list.add(currentNode.val); + + // add tail data in queue + if (currentNode.left != null) { + queue.add(currentNode.left); + } + if (currentNode.right != null) { + queue.add(currentNode.right); + } + } + + // insert data in 0 position + resultList.add(0, list); + } + + // return result list + return resultList; + } + + public List> levelOrderBottomWithRecursive(TreeNode root) { + List> resultList = new ArrayList<>(); + depthSearchFirst(0, root, resultList); + + return resultList; + } + + public void depthSearchFirst(int level, TreeNode node, List> resultList) { + // null + if (node == null) { + return; + } + // create item List when size <= level + if (resultList.size() <= level) { + // warning: must add new item at first place. Because the left node will execute first. + resultList.add(0, new ArrayList()); + } + // left node + depthSearchFirst(level + 1, node.left, resultList); + // right node + depthSearchFirst( level + 1, node.right, resultList); + // add item Integer + resultList.get(resultList.size() - level - 1).add(node.val); + } + + +} diff --git a/code/LeetCode/src/tree/ValidateBinarySearchTree.java b/code/LeetCode/src/tree/ValidateBinarySearchTree.java new file mode 100644 index 00000000..b8f1b685 --- /dev/null +++ b/code/LeetCode/src/tree/ValidateBinarySearchTree.java @@ -0,0 +1,74 @@ +package tree; + +import common.TreeNode; + +import java.util.LinkedList; +import java.util.Queue; + +// https://leetcode.com/problems/validate-binary-search-tree/ +public class ValidateBinarySearchTree { + + public boolean isValidBST(TreeNode root) { + if (root == null) { + return true; + } + + return isValidBSTWithLowerAndUpper(root, null, null); + } + + public boolean isValidBSTWithLowerAndUpper(TreeNode root, Integer lower, Integer upper) { + if (root == null) { + return true; + } + if (lower != null && root.val <= lower) { + return false; + } + if (upper != null && root.val >= upper) { + return false; + } + + + return isValidBSTWithLowerAndUpper(root.left, lower, root.val) && isValidBSTWithLowerAndUpper(root.right, root.val, upper); + } + + public boolean isValidBSTWithIterate(TreeNode root) { + if (root == null) { + return true; + } + Queue queue = new LinkedList<>(); + queue.add(root); + Queue valleyQueue = new LinkedList<>(); + valleyQueue.add(null); + Queue peakQueue = new LinkedList<>(); + peakQueue.add(null); + TreeNode current; + Integer valley; + Integer peak; + while (!queue.isEmpty()) { + current = queue.poll(); + valley = valleyQueue.poll(); + peak = peakQueue.poll(); + if (valley != null && current.val <= valley) { + return false; + } + if (peak != null && current.val >= peak) { + return false; + } + + if (current.left != null) { + queue.add(current.left); + valleyQueue.add(valley); + peakQueue.add(current.val); + } + + if (current.right != null) { + queue.add(current.right); + valleyQueue.add(current.val); + peakQueue.add(peak); + } + + } + + return true; + } +}