diff --git a/UniqueBinarySearchTreesII/generateTrees.py b/UniqueBinarySearchTreesII/generateTrees.py new file mode 100644 index 000000000..fee07dc5e --- /dev/null +++ b/UniqueBinarySearchTreesII/generateTrees.py @@ -0,0 +1,24 @@ +def generateTrees(self, n): + if n == 0: return [] + + def helper(start, end): + ls = [] + if start > end: + ls.append(None) + return ls + if start == end: + ls.append(TreeNode(start)) + return ls + + for i in range(start, end + 1): + left = helper(start, i - 1) + right = helper(i + 1, end) + for lnode in left: + for rnode in right: + root = TreeNode(i) + root.left = lnode + root.right = rnode + ls.append(root) + return ls + + return helper(1, n) \ No newline at end of file diff --git a/ValidMountainArray/validMountainArray.py b/ValidMountainArray/validMountainArray.py new file mode 100644 index 000000000..c40f5db3a --- /dev/null +++ b/ValidMountainArray/validMountainArray.py @@ -0,0 +1,20 @@ +# Method 1: using index find the max first, and then process + +def validMountainArray(self, A): + if len(A) < 3: return False + index = A.index(max(A)) + if index == 0 or index == len(A) -1: return False + for i in range(1, len(A)): + if i <= index: + if A[i] <= A[i - 1]: return False + else: + if A[i] >= A[i - 1]: return False + return True + + +# Method 2: one pass, using two pointers trace from the begining and end +def validMountainArray(self, A): + i, j = 0, len(A) - 1 + while i < len(A) - 1 and A[i] < A[i + 1]: i += 1 + while j > 0 and A[j - 1] > A[j]: j -= 1 + return 0 < i == j < len(A) - 1 \ No newline at end of file diff --git a/ValidateBinarySearchTree/isValidBST.py b/ValidateBinarySearchTree/isValidBST.py new file mode 100644 index 000000000..06a1243e0 --- /dev/null +++ b/ValidateBinarySearchTree/isValidBST.py @@ -0,0 +1,26 @@ +# method 1: using recursion + +def isValidBST1(self, root, lower = float('-inf'), upper = float('inf')): + """ + :type root: TreeNode + :rtype: bool + """ + if not root: return True + if root.val <= lower or root.val >= upper: return False + return self.isValidBST(root.left, lower, min(upper, root.val)) \ + and self.isValidBST(root.right, max(lower, root.val), upper) + + +# method 2: a proper BST should have this porperty: inorder traversal is increasing +def isValidBST2(self, root): + inorder = [] + def helper(root): + if root: + helper(root.left) + inorder.append(root.val) + helper(root.right) + + helper(root) + for i in range(len(inorder) - 1): + if inorder[i + 1] <= inorder[i]: return False + return True \ No newline at end of file diff --git a/XOfAKindInADeckOfCards/hasGroupsSizeX.py b/XOfAKindInADeckOfCards/hasGroupsSizeX.py new file mode 100644 index 000000000..e65e2554f --- /dev/null +++ b/XOfAKindInADeckOfCards/hasGroupsSizeX.py @@ -0,0 +1,19 @@ +# Method 1: find the greatest common divisor using iteration + +def hasGroupsSizeX(self, deck): + if len(deck) < 2: return False + vals = collections.Counter(deck).values() + for n in range(2, max(vals) + 1): + if all(v % n == 0 for v in vals): return True + return False + +# Method 2: find the greatest common divisor using reduce +# Time complexity: O(n) +def hasGroupsSizeX(self, deck): + from functools import reduce + if len(deck) < 2: return False + vals = collections.Counter(deck).values() + def gcd(a, b): + while b: a, b = b, a % b + return a + return reduce(gcd, vals) \ No newline at end of file diff --git a/uniquePaths/uniquePathsIII.py b/uniquePaths/uniquePathsIII.py new file mode 100644 index 000000000..d7ba4dfe6 --- /dev/null +++ b/uniquePaths/uniquePathsIII.py @@ -0,0 +1,74 @@ +# 980. Unique Paths III +# On a 2-dimensional grid, there are 4 types of squares: + +# 1 represents the starting square. There is exactly one starting square. +# 2 represents the ending square. There is exactly one ending square. +# 0 represents empty squares we can walk over. +# -1 represents obstacles that we cannot walk over. +# Return the number of 4-directional walks from the starting square to the ending square, that walk over every non-obstacle square exactly once. + + + +# Example 1: + +# Input: [[1,0,0,0],[0,0,0,0],[0,0,2,-1]] +# Output: 2 +# Explanation: We have the following two paths: +# 1. (0,0),(0,1),(0,2),(0,3),(1,3),(1,2),(1,1),(1,0),(2,0),(2,1),(2,2) +# 2. (0,0),(1,0),(2,0),(2,1),(1,1),(0,1),(0,2),(0,3),(1,3),(1,2),(2,2) +# Example 2: + +# Input: [[1,0,0,0],[0,0,0,0],[0,0,0,2]] +# Output: 4 +# Explanation: We have the following four paths: +# 1. (0,0),(0,1),(0,2),(0,3),(1,3),(1,2),(1,1),(1,0),(2,0),(2,1),(2,2),(2,3) +# 2. (0,0),(0,1),(1,1),(1,0),(2,0),(2,1),(2,2),(1,2),(0,2),(0,3),(1,3),(2,3) +# 3. (0,0),(1,0),(2,0),(2,1),(2,2),(1,2),(1,1),(0,1),(0,2),(0,3),(1,3),(2,3) +# 4. (0,0),(1,0),(2,0),(2,1),(1,1),(0,1),(0,2),(0,3),(1,3),(1,2),(2,2),(2,3) +# Example 3: + +# Input: [[0,1],[2,0]] +# Output: 0 +# Explanation: +# There is no path that walks over every empty square exactly once. +# Note that the starting and ending square can be anywhere in the grid. + + +# Note: + +# 1 <= grid.length * grid[0].length <= 20 + +class Solution: + ans = 0 + def findPathNum(self, i, j, grid: List[List[int]], curLen, pLen)->None: + if(grid[i][j]==2): + if(pLen-1==curLen): + self.ans+=1 + return + elif (grid[i][j]==-1): + return + curLen+=1 + grid[i][j]=-1 + if(i-1>=0): + self.findPathNum(i-1, j, grid, curLen, pLen) + if(j-1>=0): + self.findPathNum(i, j-1, grid, curLen, pLen) + if(i+1 int: + pathLen = 0 + start = (0, 0) + for i in range(len(grid)): + for j in range(len(grid[0])): + if(grid[i][j]!=-1): + pathLen+=1 + if(grid[i][j]==1): + start = (i, j) + self.findPathNum(start[0], start[1], grid, 0, pathLen) + return self.ans + \ No newline at end of file