diff --git a/AccountMerge.py b/AccountMerge.py new file mode 100644 index 0000000..84d7657 --- /dev/null +++ b/AccountMerge.py @@ -0,0 +1,50 @@ +from typing import List + + +class Solution: + def accountsMerge(self, accounts: List[List[str]]) -> List[List[str]]: + reverse_dict = dict() + result = dict() + uf = UnionFind(len(accounts)) + + for index, emails in enumerate(accounts): + for email in emails[1::]: + if email in reverse_dict: + uf.union(reverse_dict[email], index) + reverse_dict[email] = index + + for index, emails in enumerate(accounts): + root_index = uf.find_root(index) + if root_index not in result: + result[root_index] = set() + + result[root_index].update(set(emails[1::])) + + return [[accounts[k][0]] + sorted(list(v)) for k, v in result.items()] + + +class UnionFind: + def __init__(self, length): + self.list = list(range(length)) + + def find_root(self, n): + while n != self.list[n]: + n = self.list[n] + return n + + def union(self, i, j): + i_root = self.find_root(i) + j_root = self.find_root(j) + if j_root < i_root: + j_root, i_root = i_root, j_root + + self.list[j_root] = i_root + + +if __name__ == "__main__": + accounts = [["David", "David0@m.co", "David1@m.co"], + ["David", "David3@m.co", "David4@m.co"], + ["David", "David4@m.co", "David5@m.co"], + ["David", "David2@m.co", "David3@m.co"], + ["David", "David1@m.co", "David2@m.co"]] + print(Solution().accountsMerge(accounts)) diff --git a/DPI.java b/DPI.java new file mode 100644 index 0000000..90949ae --- /dev/null +++ b/DPI.java @@ -0,0 +1,93 @@ +public class DPI { + /** + * Fibonacci Number + *

+ * Get the Kth number in the Fibonacci Sequence. (K is 0-indexed, the 0th + * Fibonacci number is 0 and the 1st Fibonacci number is 1). + */ + public long fibonacci(int K) { + long a = 0; + long b = 1; + while (K-- > 0) { + long temp = a + b; + a = b; + b = temp; + } + return a; + } + + /** + * Longest Ascending SubArray + *

+ * Given an unsorted array, find the length of the longest subarray in which the + * numbers are in ascending order. + */ + public int longest(int[] array) { + int max = 0; + int cur = 0; + int prev = 0; + for (int i = 0; i < array.length; i++) { + if (i == 0) { + max = 1; + cur = 1; + prev = array[0]; + } else { + if (array[i] > prev) { + cur++; + prev = array[i]; + if (cur > max) { + max = cur; + } + } else { + prev = array[i]; + cur = 1; + } + } + } + return max; + } + + /** + * Max Product Of Cutting Rope + *

+ * Given a rope with positive integer-length n, how to cut the rope into m + * integer-length parts with length p[0], p[1], ...,p[m-1], in order to get the + * maximal product of p[0]*p[1]* ... *p[m-1]? m is determined by you and must be + * greater than 0 (at least one cut must be made). Return the max product you + * can have. + */ + public int maxProduct(int length) { + int[] dp = new int[length]; + dp[0] = 1; + if (length <= 3) { + return length - 1; + } + for (int i = 1; i < length; i++) { + dp[i] = i + 1; + for (int j = 1; j <= i; j++) { + dp[i] = Math.max(dp[i], j * dp[i - j]); + } + } + return dp[length - 1]; + } + + /** + * Array Hopper I + *

+ * Given an array A of non-negative integers, you are initially positioned at + * index 0 of the array. A[i] means the maximum jump distance from that position + * (you can only jump towards the end of the array). Determine if you are able + * to reach the last index. + */ + public boolean canJump(int[] array) { + int max = array[0]; + for (int i = 0; i < array.length; i++) { + if (i > max) { + return false; + } else { + max = Math.max(max, i + array[i]); + } + } + return true; + } +} diff --git a/DPII.java b/DPII.java new file mode 100644 index 0000000..eef8112 --- /dev/null +++ b/DPII.java @@ -0,0 +1,165 @@ +import java.util.*; + +public class DPII { + public static void main(String[] args) { + int[][] matrix = new int[][] { + {0, 1, 1, 1}, + {1, 1, 0, 1}, + {0, 1, 0, 1}, + {1, 1, 1, 1}, + }; + DPII d = new DPII(); + d.largest(matrix); + + } + /** + * Array Hopper II + *

+ * Given an array A of non-negative integers, you are initially positioned at + * index 0 of the array. A[i] means the maximum jump distance from index i (you + * can only jump towards the end of the array). Determine the minimum number of + * jumps you need to reach the end of array. If you can not reach the end of the + * array, return -1. + */ + public int minJump(int[] array) { + int[] dp = new int[array.length]; + dp[0] = 1; + + for (int i = 0; i < array.length; i++) { + if (dp[i] == 0) { + return -1; + } else { + for (int j = i + 1; j <= i + array[i] && j < array.length; j++) { + if (dp[j] == 0) { + dp[j] = dp[i] + 1; + } else { + dp[j] = Math.min(dp[i] + 1, dp[j]); + } + } + } + } + return dp[array.length - 1] - 1; + } + + /** + * Largest SubArray Sum + *

+ * Given an unsorted integer array, find the subarray that has the greatest sum. + * Return the sum. + */ + public int largestSum(int[] array) { + int cur = 0; + int max = Integer.MIN_VALUE; + for (int i = 0; i < array.length; i++) { + cur += array[i]; + max = Math.max(cur, max); + if (cur < 0) { + cur = 0; + } + } + return max; + } + + /** + * Dictionary Word I + *

+ * Given a word and a dictionary, determine if it can be composed by + * concatenating words from the given dictionary. + */ + public boolean canBreak(String input, String[] dict) { + Set set = new HashSet<>(); + for (String s : dict) { + set.add(s); + } + + boolean[] dp = new boolean[input.length() + 1]; + dp[0] = true; + char[] array = input.toCharArray(); + for (int i = 0; i < array.length; i++) { + for (int j = 0; j <= i; j++) { + if (dp[j]) { + if (set.contains(new String(array, j, i + 1 - j))) { + dp[i + 1] = true; + break; + } + } + } + } + return dp[input.length()]; + } + + /** + * Edit Distance + *

+ * Given two strings of alphanumeric characters, determine the minimum number of + * Replace, Delete, and Insert operations needed to transform one string into + * the other. + */ + public int editDistance(String one, String two) { + int l1 = one.length(); + int l2 = two.length(); + int[][] dp = new int[l1 + 1][l2 + 1]; + dp[0][0] = 0; + + for (int i = 1; i <= l1; i++) { + dp[i][0] = i; + } + + for (int j = 0; j <= l2; j++) { + dp[0][j] = j; + } + + for (int i = 1; i <= l1; i++) { + for (int j = 1; j <= l2; j++) { + if (one.charAt(i - 1) == two.charAt(j - 1)) { + dp[i][j] = dp[i - 1][j - 1]; + } else { + dp[i][j] = dp[i - 1][j - 1] + 1; + } + dp[i][j] = Math.min(dp[i][j], dp[i - 1][j] + 1); + dp[i][j] = Math.min(dp[i][j], dp[i][j - 1] + 1); + } + } + + return dp[l1][l2]; + } + + /** + * Largest Square Of 1s + *

+ * Determine the largest square of 1s in a binary matrix (a binary matrix only + * contains 0 and 1), return the length of the largest square. + */ + public int largest(int[][] matrix) { + int max = 0; + int H = matrix.length; + int W = matrix[0].length; + + int[][] dp = new int[H][W]; + + for (int i = 0; i < H; i++) { + for (int j = 0; j < W; j++) { + if (matrix[i][j] == 1) { + if (i == 0 || j == 0) { + dp[i][j] = 1; + } else { + dp[i][j] = Math.min(Math.min(dp[i][j - 1], dp[i - 1][j]), dp[i - 1][j - 1]) + 1; + } + + max = Math.max(dp[i][j], max); + } + } + } + + for (int i = 0; i < H; i++) { + System.out.print("|"); + for (int j = 0; j < W; j++) { + System.out.print(dp[i][j]); + System.out.print(" "); + } + System.out.println("|"); + } + + return max; + } +} diff --git a/DPIII.java b/DPIII.java new file mode 100644 index 0000000..d2681e1 --- /dev/null +++ b/DPIII.java @@ -0,0 +1,93 @@ +public class DPIII { + /** + * Longest Consecutive 1s + *

+ * Given an array containing only 0s and 1s, find the length of the longest + * subarray of consecutive 1s. + */ + public int longest(int[] array) { + int max = 0; + int cur = 0; + for (int num : array) { + if (num == 1) { + cur++; + max = Math.max(max, cur); + } else { + cur = 0; + } + } + return max; + } + + /** + * Longest Cross Of 1s + *

+ * Given a matrix that contains only 1s and 0s, find the largest cross which + * contains only 1s, with the same arm lengths and the four arms joining at the + * central point. + * + * Return the arm length of the largest cross. + */ + public int largest(int[][] matrix) { + int H = matrix.length; + int W = matrix[0].length; + + int[][] right = new int[H][W]; + int[][] left = new int[H][W]; + int[][] up = new int[H][W]; + int[][] down = new int[H][W]; + + int max = 0; + + for (int i = 0; i < H; i++) { + for (int j = 0; j < W; j++) { + if (matrix[i][j] == 1) { + if (j == 0) { + left[i][j] = 1; + } else { + left[i][j] = left[i][j - 1] + 1; + } + } + } + } + for (int i = 0; i < H; i++) { + for (int j = 0; j < W; j++) { + if (matrix[i][j] == 1) { + if (i == 0) { + up[i][j] = 1; + } else { + up[i][j] = up[i - 1][j] + 1; + } + } + } + } + for (int i = 0; i < H; i++) { + for (int j = W - 1; j >= 0; j--) { + if (matrix[i][j] == 1) { + if (j == W - 1) { + right[i][j] = 1; + } else { + right[i][j] = right[i][j + 1] + 1; + } + } + } + } + for (int i = H - 1; i >= 0; i--) { + for (int j = 0; j < W; j++) { + if (matrix[i][j] == 1) { + if (i == H - 1) { + down[i][j] = 1; + } else { + down[i][j] = down[i + 1][j] + 1; + } + } + } + } + for (int i = 0; i < H; i++) { + for (int j = 0; j < W; j++) { + max = Math.max(Math.min(Math.min(up[i][j], down[i][j]), Math.min(left[i][j], right[i][j])), max); + } + } + return max; + } +} diff --git a/RecursionII.java b/RecursionII.java index cffd09f..052b2eb 100644 --- a/RecursionII.java +++ b/RecursionII.java @@ -164,10 +164,10 @@ public int numNodesLeftHelper(TreeNode root) { } /** - * Lowest Common Ancestor I - *

- * Given two nodes in a binary tree, find their lowest common ancestor. - */ + * Lowest Common Ancestor I + *

+ * Given two nodes in a binary tree, find their lowest common ancestor. + */ public TreeNode lowestCommonAncestor(TreeNode root, TreeNode one, TreeNode two) { if (root == null || root == one || root == two) { return root; @@ -183,4 +183,65 @@ public TreeNode lowestCommonAncestor(TreeNode root, TreeNode one, TreeNode two) return root; } } + + /** + * Spiral Order Traverse II + *

+ * Traverse an M * N 2D array in spiral order clock-wise starting from the top left corner. Return the list of traversal sequence. + */ + public List spiral2(int[][] matrix) { + int H = matrix.length; + int W = matrix[0].length; + + + List result = new ArrayList<>(); + int offset = 0; + int maxOffset = Math.min(H / 2, W / 2); + while (offset < maxOffset) { + for (int i = offset; i < W - offset - 1; i++) { + result.add(matrix[offset][i]); + } + for (int i = offset; i < H - offset - 1; i++) { + result.add(matrix[i][W - 1 - offset]); + } + for (int i = W - 1 - offset; i > offset; i--) { + result.add(matrix[H - 1 - offset][i]); + } + for (int i = H - 1 - offset; i > offset; i--) { + result.add(matrix[i][offset]); + } + offset++; + } + + if (H > W && W % 2 == 1) { + for (int i = offset; i < H - offset; i++) { + result.add(matrix[i][offset]); + } + } + + if (W >= H && H % 2 == 1) { + for (int i = offset; i < W - offset; i++) { + result.add(matrix[offset][i]); + } + } + return result; + } + + /** + * Reverse Binary Tree Upside Down + *

+ * Given a binary tree where all the right nodes are leaf nodes, flip it upside down and turn it into a tree with left leaf nodes as the root. + */ + public TreeNode reverse(TreeNode root) { + if (root == null || root.left == null) { + return root; + } + TreeNode left = root.left; + TreeNode newHead = reverse(root.left); + left.left = root; + root.left = null; + left.right = root.right; + root.right = null; + return newHead; + } }