├── 3Sum Closest.py ├── 3Sum.py ├── Add Binary.py ├── Add Two Numbers.py ├── Anagrams.py ├── Balanced Binary Tree.py ├── Best Time to Buy and Sell Stock II.py ├── Best Time to Buy and Sell Stock III.py ├── Best Time to Buy and Sell Stock.py ├── Binary Tree Inorder Traversal.py ├── Binary Tree Level Order Traversal II.py ├── Binary Tree Level Order Traversal.py ├── Binary Tree Maximum Path Sum.py ├── Binary Tree Postorder Traversal.py ├── Binary Tree Preorder Traversal.py ├── Binary Tree Zigzag Level Order Traversal.py ├── Candy.py ├── Climbing Stairs.py ├── Clone Graph.py ├── Combination Sum II.py ├── Combination Sum.py ├── Combinations.py ├── Construct Binary Tree from Inorder and Postorder Traversal.py ├── Construct Binary Tree from Preorder and Inorder Traversal.py ├── Container With Most Water.py ├── Convert Sorted Array to Binary Search Tree.py ├── Convert Sorted List to Binary Search Tree.py ├── Copy List with Random Pointer.py ├── Count and Say.py ├── Decode Ways.py ├── Distinct Subsequences.py ├── Edit Distance.py ├── Evaluate Reverse Polish Notation.py ├── First Missing Positive.py ├── Flatten Binary Tree to Linked List.py ├── Gas Station.py ├── Generate Parentheses.py ├── Gray Code.py ├── Implement strStr().py ├── Insert Interval.py ├── Insertion Sort List.py ├── Integer to Roman.py ├── Interleaving String.py ├── Jump Game II.py ├── Jump Game.py ├── LRU Cache.py ├── Largest Rectangle in Histogram.py ├── Length of Last Word.py ├── Letter Combinations of a Phone Number.py ├── Linked List Cycle II.py ├── Linked List Cycle.py ├── Longest Common Prefix.py ├── Longest Consecutive Sequence.py ├── Longest Palindromic Substring.py ├── Longest Substring Without Repeating Characters.py ├── Longest Valid Parentheses.py ├── Max Points on a Line.py ├── Maximal Rectangle.py ├── Maximum Depth of Binary Tree.py ├── Maximum Subarray.py ├── Merge Intervals.py ├── Merge Sorted Array.py ├── Merge Two Sorted Lists.py ├── Merge k Sorted Lists.py ├── Minimum Depth of Binary Tree.py ├── Minimum Path Sum.py ├── Multiply Strings.py ├── N-Queens II.py ├── N-Queens.py ├── Next Permutation.py ├── Palindrome Number.py ├── Palindrome Partitioning II.py ├── Palindrome Partitioning.py ├── Partition List.py ├── Pascal's Triangle II.py ├── Pascal's Triangle.py ├── Path Sum II.py ├── Path Sum.py ├── Permutation Sequence.py ├── Permutations II.py ├── Permutations.py ├── Plus One.py ├── Populating Next Right Pointers in Each Node II.py ├── Populating Next Right Pointers in Each Node.py ├── Pow(x, n).py ├── README.md ├── Remove Duplicates from Sorted Array II.py ├── Remove Duplicates from Sorted Array.py ├── Remove Duplicates from Sorted List II.py ├── Remove Duplicates from Sorted List.py ├── Remove Element.py ├── Remove Nth Node From End of List.py ├── Reorder List.py ├── Restore IP Addresses.py ├── Reverse Integer.py ├── Reverse Linked List II.py ├── Reverse Words in a String.py ├── Roman to Integer.py ├── Rotate Image.py ├── Rotate List.py ├── Same Tree.py ├── Search Insert Position.py ├── Search a 2D Matrix.py ├── Search for a Range.py ├── Search in Rotated Sorted Array II.py ├── Search in Rotated Sorted Array.py ├── Set Matrix Zeroes.py ├── Simplify Path.py ├── Single Number II.py ├── Single Number.py ├── Sort Colors.py ├── Sort List.py ├── Spiral Matrix II.py ├── Spiral Matrix.py ├── Sqrt(x).py ├── String to Integer (atoi).py ├── Subsets II.py ├── Subsets.py ├── Sum Root to Leaf Numbers.py ├── Surrounded Regions.py ├── Swap Nodes in Pairs.py ├── Symmetric Tree.py ├── Trapping Rain Water.py ├── Triangle.py ├── Two Sum.py ├── Unique Binary Search Trees II.py ├── Unique Binary Search Trees.py ├── Unique Paths II.py ├── Unique Paths.py ├── Valid Palindrome.py ├── Valid Parentheses.py ├── Valid Sudoku.py ├── Validate Binary Search Tree.py ├── Word Break II.py ├── Word Break.py ├── Word Ladder II.py ├── Word Ladder.py ├── Word Search.py └── ZigZag Conversion.py /3Sum Closest.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def threeSumClosest(self, A, target): 3 | A, result, closest_diff, i = sorted(A), 2147483647, 2147483647, 0 4 | while i < len(A) - 2: 5 | j, k = i + 1, len(A) - 1 6 | while j < k: 7 | diff = A[i] + A[j] + A[k] - target 8 | if diff < 0: 9 | if math.fabs(diff) < math.fabs(closest_diff): 10 | result, closest_diff = A[i] + A[j] + A[k], diff 11 | j += 1 12 | elif diff > 0: 13 | if math.fabs(diff) < math.fabs(closest_diff): 14 | result, closest_diff = A[i] + A[j] + A[k], diff 15 | k -= 1 16 | else: 17 | return target 18 | i += 1 19 | return result -------------------------------------------------------------------------------- /3Sum.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def threeSum(self, A): 3 | A, result, i = sorted(A), [], 0 4 | while i < len(A) - 2: 5 | j, k = i + 1, len(A) - 1 6 | while j < k: 7 | if A[i] + A[j] + A[k] < 0: 8 | j += 1 9 | elif A[i] + A[j] + A[k] > 0: 10 | k -= 1 11 | else: 12 | result.append([A[i], A[j], A[k]]) 13 | j, k = j + 1, k - 1 14 | while j < k and A[j] == A[j - 1]: 15 | j += 1 16 | while j < k and A[k] == A[k + 1]: 17 | k -= 1 18 | i += 1 19 | while i < len(A) - 2 and A[i] == A[i - 1]: 20 | i += 1 21 | return result -------------------------------------------------------------------------------- /Add Binary.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def addBinary(self, a, b): 3 | return bin(int(a, 2) + int(b, 2)).split('b')[1] 4 | 5 | def addBinary(self, a, b): 6 | """Sometimes built-in function cheats too much. 7 | """ 8 | res, carry, len_a, len_b, i = "", 0, len(a), len(b), 0 9 | for i in range(max(len_a, len_b)): 10 | sum = carry 11 | if i < len_a: 12 | sum += int(a[-(i + 1)]) 13 | if i < len_b: 14 | sum += int(b[-(i + 1)]) 15 | carry = sum / 2 16 | sum = sum % 2 17 | res = "{0}{1}".format(sum, res) 18 | if carry == 1: 19 | res = "1" + res 20 | return res 21 | 22 | # def addBinary(self, a, b): 23 | # """Using carry without sum is also fine. But the readability sucks. 24 | # """ 25 | # res, carry, len_a, len_b, i = "", 0, len(a), len(b), 0 26 | # for i in range(max(len_a, len_b)): 27 | # if i < len_a: 28 | # carry += int(a[-(i + 1)]) 29 | # if i < len_b: 30 | # carry += int(b[-(i + 1)]) 31 | # res = "{0}{1}".format(carry % 2, res) 32 | # carry = carry / 2 33 | # if carry == 1: 34 | # res = "1" + res 35 | # return res -------------------------------------------------------------------------------- /Add Two Numbers.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def addTwoNumbers(self, l1, l2): 3 | dummy = ListNode(0) 4 | current, carry = dummy, 0 5 | while l1 != None or l2 != None: 6 | res = carry 7 | if l1 != None: 8 | res += l1.val 9 | l1 = l1.next 10 | if l2 != None: 11 | res += l2.val 12 | l2 = l2.next 13 | carry, res = res / 10, res % 10 14 | current.next = ListNode(res) 15 | current = current.next 16 | if carry == 1: 17 | current.next = ListNode(1) 18 | return dummy.next -------------------------------------------------------------------------------- /Anagrams.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def anagrams(self, strs): 3 | anagram_map, res = {}, [] 4 | for str in strs: 5 | sorted_str = ("").join(sorted(str)) 6 | if sorted_str in anagram_map: 7 | anagram_map[sorted_str].append(str) 8 | else: 9 | anagram_map[sorted_str] = [str] 10 | for anagrams in anagram_map.values(): 11 | if len(anagrams) > 1: 12 | res += anagrams 13 | return res 14 | 15 | # def anagrams(self, strs): 16 | # """List comprehension may be more elegant but less readable here. 17 | # """ 18 | # anagram_map = {} 19 | # for str in strs: 20 | # sorted_str = ("").join(sorted(str)) 21 | # if sorted_str in anagram_map: 22 | # anagram_map[sorted_str].append(str) 23 | # else: 24 | # anagram_map[sorted_str] = [str] 25 | # return [anagram for anagrams in anagram_map.values() if len(anagrams) > 1 for anagram in anagrams] -------------------------------------------------------------------------------- /Balanced Binary Tree.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def isBalanced(self, root): 3 | return self.getHeight(root) != -1 4 | 5 | def getHeight(self, root): 6 | if root == None: 7 | return 0 8 | left_height, right_height = self.getHeight(root.left), self.getHeight(root.right) 9 | if left_height < 0 or right_height < 0 or math.fabs(left_height - right_height) > 1: 10 | return -1 11 | return max(left_height, right_height) + 1 -------------------------------------------------------------------------------- /Best Time to Buy and Sell Stock II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def maxProfit(self, prices): 3 | profit = 0 4 | for i in range(len(prices) - 1): 5 | profit += max(0, prices[i + 1] - prices[i]) 6 | return profit -------------------------------------------------------------------------------- /Best Time to Buy and Sell Stock III.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def maxProfit(self, prices): 3 | min_price, max_profit, max_profits = 9223372036854775807, 0, [] 4 | for price in prices: 5 | min_price = min(min_price, price) 6 | max_profit = max(max_profit, price - min_price) 7 | max_profits.append(max_profit) 8 | max_price, max_profit_after, max_combined_profit = 0, 0, 0 9 | for i in reversed(range(len(prices))): 10 | max_price = max(max_price, prices[i]) 11 | max_profit_after = max(max_profit_after, max_price - prices[i]) 12 | max_combined_profit = max(max_combined_profit, max_profit_after + max_profits[i]) 13 | return max_combined_profit -------------------------------------------------------------------------------- /Best Time to Buy and Sell Stock.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def maxProfit(self, prices): 3 | max_profit = 0 4 | min_price = 9223372036854775807 5 | for price in prices: 6 | min_price = min(min_price, price) 7 | max_profit = max(max_profit, price - min_price) 8 | return max_profit -------------------------------------------------------------------------------- /Binary Tree Inorder Traversal.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def inorderTraversal(self, root): 3 | res, stack, current = [], [], root 4 | while stack or current: 5 | if current: 6 | stack.append(current) 7 | current = current.left 8 | else: 9 | parent = stack.pop() 10 | res.append(parent.val) 11 | current = parent.right 12 | return res -------------------------------------------------------------------------------- /Binary Tree Level Order Traversal II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def levelOrderBottom(self, root): 3 | if root is None: 4 | return [] 5 | res, current = [], [root] 6 | while current: 7 | next, vals = [], [] 8 | for node in current: 9 | vals.append(node.val) 10 | if node.left: 11 | next.append(node.left) 12 | if node.right: 13 | next.append(node.right) 14 | current = next 15 | res.insert(0, vals) 16 | return res 17 | 18 | # def levelOrderBottom(self, root): 19 | # """ Using a queue is also fine. 20 | # """ 21 | # if root is None: 22 | # return [] 23 | # current, res = [root], [] 24 | # while current: 25 | # vals, length = [], len(current) 26 | # for i in range(length): 27 | # node = current[0] 28 | # vals.append(node.val) 29 | # if node.left: 30 | # current.append(node.left) 31 | # if node.right: 32 | # current.append(node.right) 33 | # current.pop(0) 34 | # res.insert(0, vals) 35 | # return res -------------------------------------------------------------------------------- /Binary Tree Level Order Traversal.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def levelOrder(self, root): 3 | if root is None: 4 | return [] 5 | current, res = [root], [] 6 | while current: 7 | next, vals = [], [] 8 | for node in current: 9 | vals.append(node.val) 10 | if node.left: 11 | next.append(node.left) 12 | if node.right: 13 | next.append(node.right) 14 | res.append(vals) 15 | current = next 16 | return res 17 | 18 | # def levelOrder(self, root): 19 | # """ Using a queue is also fine. 20 | # """ 21 | # if root is None: 22 | # return [] 23 | # current, res = [root], [] 24 | # while current: 25 | # vals, length = [], len(current) 26 | # for i in range(length): 27 | # node = current[0] 28 | # vals.append(node.val) 29 | # if node.left: 30 | # current.append(node.left) 31 | # if node.right: 32 | # current.append(node.right) 33 | # current.pop(0) 34 | # res.append(vals) 35 | # return res -------------------------------------------------------------------------------- /Binary Tree Maximum Path Sum.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | maxSum = -2147483648 3 | def maxPathSum(self, root): 4 | self.maxPathRecur(root) 5 | return self.maxSum 6 | 7 | def maxPathRecur(self, root): 8 | if root == None: 9 | return 0 10 | left = max(0, self.maxPathRecur(root.left)) 11 | right = max(0, self.maxPathRecur(root.right)) 12 | self.maxSum = max(self.maxSum, left + right + root.val) 13 | return root.val + max(left, right) -------------------------------------------------------------------------------- /Binary Tree Postorder Traversal.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def postorderTraversal(self, root): 3 | res, stack, current, prev = [], [], root, None 4 | while stack or current: 5 | if current: 6 | stack.append(current) 7 | current = current.left 8 | else: 9 | parent = stack[-1] 10 | if parent.right in (None, prev): 11 | prev = stack.pop() 12 | res.append(prev.val) 13 | else: 14 | current = parent.right 15 | return res -------------------------------------------------------------------------------- /Binary Tree Preorder Traversal.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def preorderTraversal(self, root): 3 | res, stack = [], [root] 4 | if root is None: 5 | return res 6 | while stack: 7 | current = stack.pop() 8 | if current.right: 9 | stack.append(current.right) 10 | if current.left: 11 | stack.append(current.left) 12 | res.append(current.val) 13 | return res -------------------------------------------------------------------------------- /Binary Tree Zigzag Level Order Traversal.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def zigzagLevelOrder(self, root): 3 | result = [] 4 | if root == None: 5 | return result 6 | current, reverse = [root], 0 7 | while len(current) > 0: 8 | # Python is just so slow, but who I can complain? I have to write following code to optimize for skewed tree 9 | # -- None of the code from this tag to the next tag is actually needed -- # 10 | if len(current) == 1 and (current[0].left == None or current[0].right== None): 11 | this_node = current[0] 12 | result.append([this_node.val]) 13 | if this_node.left == None and this_node.right != None: 14 | current = [this_node.right] 15 | elif this_node.left != None and this_node.right == None: 16 | current = [this_node.left] 17 | else: 18 | current.pop(0) 19 | else: 20 | # -- None of the code above this tag up to the previous tag is actually needed -- # 21 | vals = [] 22 | size = len(current) 23 | for i in range(size): 24 | this_node = current[0] 25 | if reverse: 26 | vals.insert(0, this_node.val) 27 | else: 28 | vals.append(this_node.val) 29 | if i < len(current) - 1: 30 | this_node.next = current[i+1] 31 | if this_node.left != None: 32 | current.append(this_node.left) 33 | if this_node.right != None: 34 | current.append(this_node.right) 35 | current.pop(0) 36 | result.append(vals) 37 | reverse = 1 - reverse 38 | return result -------------------------------------------------------------------------------- /Candy.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def candy(self, ratings): 3 | candies = [1 for i in range(len(ratings))] 4 | for i in range(1, len(ratings)): 5 | if ratings[i] > ratings[i - 1]: 6 | candies[i] = candies[i - 1] + 1 7 | for i in reversed(range(1, len(ratings))): 8 | if ratings[i - 1] > ratings[i] and candies[i - 1] <= candies[i]: 9 | candies[i - 1] = candies[i] + 1 10 | return reduce(operator.add, candies) -------------------------------------------------------------------------------- /Climbing Stairs.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def climbStairs(self, n): 3 | prev, current = 0, 1 4 | for i in range(n): 5 | prev, current = current, current + prev 6 | return current -------------------------------------------------------------------------------- /Clone Graph.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def cloneGraph(self, node): 3 | if node == None: 4 | return None 5 | start = UndirectedGraphNode(node.label) 6 | map, current = {node: start}, [node] 7 | while len(current) > 0: 8 | next = [] 9 | for x in current: 10 | for neighbor in x.neighbors: 11 | if neighbor not in map: 12 | neighbor_copy = UndirectedGraphNode(neighbor.label) 13 | next.append(neighbor) 14 | map[x].neighbors.append(neighbor_copy) 15 | map[neighbor] = neighbor_copy 16 | else: 17 | map[x].neighbors.append(map[neighbor]) 18 | current = next 19 | return start -------------------------------------------------------------------------------- /Combination Sum II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def combinationSum2(self, candidates, target): 3 | result = [] 4 | self.combinationSumRecur(sorted(candidates), result, [], 0, target) 5 | return result 6 | 7 | def combinationSumRecur(self, candidates, result, current, start, target): 8 | if target == 0 and current not in result: 9 | result.append(current) 10 | else: 11 | while start < len(candidates) and candidates[start] <= target: 12 | self.combinationSumRecur(candidates, result, current + [candidates[start]], start + 1, target - candidates[start]) 13 | start += 1 -------------------------------------------------------------------------------- /Combination Sum.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def combinationSum(self, candidates, target): 3 | result = [] 4 | self.combinationSumRecur(sorted(candidates), result, [], 0, target) 5 | return result 6 | 7 | def combinationSumRecur(self, candidates, result, current, start, target): 8 | if target == 0: 9 | result.append(current) 10 | else: 11 | while start < len(candidates) and candidates[start] <= target: 12 | self.combinationSumRecur(candidates, result, current + [candidates[start]], start, target - candidates[start]) 13 | start += 1 -------------------------------------------------------------------------------- /Combinations.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def combine(self, n, k): 3 | return self.combineRecur([], n, k, 1) 4 | 5 | def combineRecur(self, current, n, k, i): 6 | if k == 0: 7 | return [current] 8 | if i > n: 9 | return [] 10 | return self.combineRecur(current, n, k, i + 1) + self.combineRecur(current + [i], n, k - 1, i + 1) -------------------------------------------------------------------------------- /Construct Binary Tree from Inorder and Postorder Traversal.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def buildTree(self, inorder, postorder): 3 | # using dictionary for index lookup improves the performance of algorithm from O(N^2) to O(N), where N = |postorder| 4 | lookup = {} 5 | for i in range(len(inorder)): 6 | lookup[inorder[i]] = i 7 | return self.buildTreeRecur(lookup, inorder, postorder, 0, len(postorder) - 1, len(postorder) - 1) 8 | 9 | def buildTreeRecur(self, lookup, inorder, postorder, in_start, in_end, post_end): 10 | if in_start > in_end: 11 | return None 12 | current = TreeNode(postorder[post_end]) 13 | i = lookup[postorder[post_end]] 14 | current.left = self.buildTreeRecur(lookup, inorder, postorder, in_start, i - 1, post_end - (in_end - i) - 1) 15 | current.right = self.buildTreeRecur(lookup, inorder, postorder, i + 1, in_end, post_end - 1) 16 | return current -------------------------------------------------------------------------------- /Construct Binary Tree from Preorder and Inorder Traversal.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def buildTree(self, preorder, inorder): 3 | # using dictionary for index lookup improves the performance of algorithm from O(N^2) to O(N), where N = |preorder| 4 | lookup = {} 5 | for i in range(len(inorder)): 6 | lookup[inorder[i]] = i 7 | return self.buildTreeRecur(lookup, preorder, inorder, 0, len(preorder) - 1, 0) 8 | 9 | def buildTreeRecur(self, lookup, preorder, inorder, in_start, in_end, pre_start): 10 | if in_start > in_end: 11 | return None 12 | current = TreeNode(preorder[pre_start]) 13 | i = lookup[preorder[pre_start]] 14 | current.left = self.buildTreeRecur(lookup, preorder, inorder, in_start, i - 1, pre_start + 1) 15 | current.right = self.buildTreeRecur(lookup, preorder, inorder, i + 1, in_end, pre_start + i - in_start + 1) 16 | return current -------------------------------------------------------------------------------- /Container With Most Water.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def maxArea(self, height): 3 | i, j, max_area = 0, len(height) - 1, 0 4 | while i < j: 5 | max_area = max(max_area, (j - i) * min(height[i], height[j])) 6 | if height[i] < height[j]: 7 | i += 1 8 | else: 9 | j -= 1 10 | return max_area -------------------------------------------------------------------------------- /Convert Sorted Array to Binary Search Tree.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def sortedArrayToBST(self, num): 3 | if len(num) == 0: 4 | return None 5 | mid = len(num) / 2 6 | current = TreeNode(num[mid]) 7 | current.left = self.sortedArrayToBST(num[:mid]) 8 | current.right = self.sortedArrayToBST(num[mid + 1:]) 9 | return current -------------------------------------------------------------------------------- /Convert Sorted List to Binary Search Tree.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | head = None 3 | def sortedListToBST(self, head): 4 | current, length = head, 0 5 | while current != None: 6 | current, length = current.next, length + 1 7 | self.head = head 8 | return self.sortedRecur(0, length - 1) 9 | 10 | def sortedRecur(self, start, end): 11 | if start > end: 12 | return None 13 | mid = (start + end) / 2 14 | left = self.sortedRecur(start, mid - 1) 15 | current = TreeNode(self.head.val) 16 | current.left = left 17 | self.head = self.head.next 18 | current.right = self.sortedRecur(mid + 1, end) 19 | return current -------------------------------------------------------------------------------- /Copy List with Random Pointer.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def copyRandomList(self, head): 3 | dummy = RandomListNode(0) 4 | current, prev, map = head, dummy, {} 5 | while current: 6 | copy = RandomListNode(current.label) 7 | map[current] = copy 8 | prev.next = copy 9 | prev, current = prev.next, current.next 10 | current = head 11 | while current: 12 | if current.random: 13 | map[current].random = map[current.random] 14 | current = current.next 15 | return dummy.next -------------------------------------------------------------------------------- /Count and Say.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def countAndSay(self, n): 3 | chars = "1" 4 | for i in range(n - 1): 5 | j, next = 0, "" 6 | while j < len(chars): 7 | count = 1 8 | while j < len(chars) - 1 and chars[j] == chars[j + 1]: 9 | j += 1 10 | count += 1 11 | next += "{0}{1}".format(count, chars[j]) 12 | j += 1 13 | chars = next 14 | return chars -------------------------------------------------------------------------------- /Decode Ways.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def numDecodings(self, s): 3 | if len(s) == 0: 4 | return 0 5 | prev, prev_prev = 1, 0 6 | for i in range(len(s)): 7 | current = 0 8 | if s[i] != '0': 9 | current = prev 10 | if i > 0 and (s[i - 1] == "1" or (s[i - 1] == "2" and s[i] <= "6")): 11 | current += prev_prev 12 | prev, prev_prev = current, prev 13 | return prev -------------------------------------------------------------------------------- /Distinct Subsequences.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def numDistinct(self, S, T): 3 | n, m = len(S), len(T) 4 | f = [0] * (m + 1) 5 | f[0] = 1 6 | for i in xrange(n): 7 | for j in xrange(m - 1, -1, -1): 8 | if S[i] == T[j]: 9 | f[j + 1] += f[j] 10 | return f[m] 11 | 12 | class Solution: 13 | ''' The original solution is to use a 2D array. 14 | ''' 15 | def numDistinct(self, S, T): 16 | ways = [[0 for j in range(len(S) + 1)] for i in range(len(T) + 1)] 17 | for i in range(len(S) + 1): 18 | ways[0][i] = 1 19 | for i in range(1, len(T) + 1): 20 | for j in range(1, len(S) + 1): 21 | ways[i][j] = ways[i][j - 1] 22 | if T[i - 1] == S[j - 1]: 23 | ways[i][j] += ways[i - 1][j - 1] 24 | return ways[len(T)][len(S)] 25 | -------------------------------------------------------------------------------- /Edit Distance.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def minDistance(self, word1, word2): 3 | distance = [[i] for i in range(len(word1) + 1)] 4 | distance[0] = [i for i in range(len(word2) + 1)] 5 | for i in range(1, len(word1) + 1): 6 | for j in range(1, len(word2) + 1): 7 | deletion = distance[i - 1][j] + 1 8 | addition = distance[i][j - 1] + 1 9 | substitution = distance[i - 1][j - 1] 10 | if word1[i - 1] != word2[j - 1]: 11 | substitution += 1 12 | distance[i].append(min(deletion, addition, substitution)) 13 | return distance[-1][-1] 14 | 15 | def minDistance(self, word1, word2): 16 | """This is an example of horrible code. Long statement inside the nested for loop 17 | is hard to understand. 18 | """ 19 | distance = [[i] for i in range(len(word1) + 1)] 20 | distance[0] = [i for i in range(len(word2) + 1)] 21 | for i in range(1, len(word1) + 1): 22 | for j in range(1, len(word2) + 1): 23 | distance[i].append(min(distance[i - 1][j] + 1, distance[i][j - 1] + 1, distance[i - 1][j - 1] + (word1[i - 1] != word2[j - 1]))) 24 | return distance[-1][-1] -------------------------------------------------------------------------------- /Evaluate Reverse Polish Notation.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def evalRPN(self, tokens): 3 | numerals, operators = [], {"+": operator.add, "-": operator.sub, "*": operator.mul, "/": operator.div} 4 | for token in tokens: 5 | if token.isdigit() or token[1:].isdigit(): 6 | numerals.append(int(token)) 7 | else: 8 | x, y = numerals.pop(), numerals.pop() 9 | numerals.append(int(operators[token](y * 1.0, x))) 10 | return numerals.pop() -------------------------------------------------------------------------------- /First Missing Positive.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def firstMissingPositive(self, A): 3 | i = 0 4 | while i < len(A): 5 | if A[i] > 0 and A[i] - 1 < len(A) and A[A[i] - 1] != A[i]: 6 | A[A[i] - 1], A[i] = A[i], A[A[i] - 1] 7 | else: 8 | i += 1 9 | for i in range(len(A)): 10 | if A[i] != i + 1: 11 | return i + 1 12 | return len(A) + 1 -------------------------------------------------------------------------------- /Flatten Binary Tree to Linked List.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | last = None 3 | 4 | def flatten(self, root): 5 | if root != None: 6 | self.flatten(root.right) 7 | self.flatten(root.left) 8 | root.right = self.last 9 | root.left = None 10 | self.last = root -------------------------------------------------------------------------------- /Gas Station.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def canCompleteCircuit(self, gas, cost): 3 | start, sum_so_far, sum = 0, 0, 0 4 | for i in range(len(gas)): 5 | diff = gas[i] - cost[i] 6 | if sum_so_far + diff < 0: 7 | start = i + 1 8 | sum_so_far = 0 9 | else: 10 | sum_so_far += diff 11 | sum += diff 12 | if sum >= 0: 13 | return start 14 | return -1 -------------------------------------------------------------------------------- /Generate Parentheses.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def generateParenthesis(self, n): 3 | result = [] 4 | self.generateParenthesisRecur(result, "", n, n) 5 | return result 6 | 7 | def generateParenthesisRecur(self, result, current, left, right): 8 | if left == 0 and right == 0: 9 | result.append(current) 10 | if left > 0: 11 | self.generateParenthesisRecur(result, current + "(", left - 1, right) 12 | if left < right: 13 | self.generateParenthesisRecur(result, current + ")", left, right - 1) -------------------------------------------------------------------------------- /Gray Code.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def grayCode(self, n): 3 | return [(x / 2) ^ x for x in range(1 << n)] -------------------------------------------------------------------------------- /Implement strStr().py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def strStr(self, haystack, needle): 3 | for i in range(len(haystack) - len(needle) + 1): 4 | if haystack[i : i + len(needle)] == needle: 5 | return haystack[i:] 6 | return None -------------------------------------------------------------------------------- /Insert Interval.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def insert(self, intervals, newInterval): 3 | return self.merge(intervals + [newInterval]) 4 | 5 | def merge(self, intervals): 6 | if len(intervals) == 0: 7 | return intervals 8 | intervals.sort(key = lambda x: x.start) 9 | result = [intervals[0]] 10 | for i in range(1, len(intervals)): 11 | current, prev = intervals[i], result[-1] 12 | if current.start <= prev.end: 13 | prev.end = max(prev.end, current.end) 14 | else: 15 | result.append(current) 16 | return result -------------------------------------------------------------------------------- /Insertion Sort List.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def isListAllSorted(self, head): 3 | current = head 4 | while current and current.next: 5 | if current.val > current.next.val: 6 | return False 7 | current = current.next 8 | return True 9 | 10 | def insertionSortList(self, head): 11 | if head == None or self.isListAllSorted(head): 12 | return head 13 | dummy = ListNode(-9223372036854775808) 14 | dummy.next = head 15 | current, prev_current = head.next, head 16 | while current != None: 17 | prev = dummy 18 | while prev.next.val < current.val: 19 | prev = prev.next 20 | if prev.next != current and prev.next.val >= current.val: 21 | current.next, prev.next, prev_current.next = prev.next, current, current.next 22 | current = prev_current.next 23 | else: 24 | current, prev_current = current.next, prev_current.next 25 | return dummy.next -------------------------------------------------------------------------------- /Integer to Roman.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def intToRoman(self, num): 3 | numeral_map = {1: "I", 4: "IV", 5: "V", 9: "IX", 10: "X", 40: "XL", 50: "L", 90: "XC", 100: "C", 400: "CD", 500: "D", 900: "CM", 1000: "M"} 4 | keyset, length, result = sorted(numeral_map.keys()), len(numeral_map), "" 5 | while num > 0: 6 | for i in reversed(range(length)): 7 | key = keyset[i] 8 | while num / key > 0: 9 | result += numeral_map[key] 10 | num -= key 11 | return result -------------------------------------------------------------------------------- /Interleaving String.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def isInterleave(self, s1, s2, s3): 3 | if len(s1) + len(s2) != len(s3): 4 | return False 5 | interleave_matrix = [[False for i in range(len(s2) + 1)] for j in range(len(s1) + 1)] 6 | interleave_matrix[0][0] = True 7 | for i in range(1, len(s1) + 1): 8 | interleave_matrix[i][0] = interleave_matrix[i - 1][0] and s1[i - 1] == s3[i - 1] 9 | for i in range(1, len(s2) + 1): 10 | interleave_matrix[0][i] = interleave_matrix[0][i - 1] and s2[i - 1] == s3[i - 1] 11 | for i in range(1, len(s1) + 1): 12 | for j in range(1, len(s2) + 1): 13 | interleave_matrix[i][j] = (interleave_matrix[i - 1][j] and s1[i - 1] == s3[i + j - 1]) or (interleave_matrix[i][j - 1] and s2[j - 1] == s3[i + j - 1]) 14 | return interleave_matrix[-1][-1] -------------------------------------------------------------------------------- /Jump Game II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def jump(self, A): 3 | step, reachable, i = -1, 0, 0 4 | while i < len(A) and i <= reachable: 5 | next_reachable = 0 6 | while i <= reachable and i < len(A): 7 | next_reachable = max(next_reachable, A[i] + i) 8 | i += 1 9 | reachable = next_reachable 10 | step += 1 11 | return step -------------------------------------------------------------------------------- /Jump Game.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def canJump(self, A): 3 | reachable = 0 4 | for i in range(len(A)): 5 | if i > reachable: 6 | return False 7 | reachable = max(reachable, i + A[i]) 8 | return True -------------------------------------------------------------------------------- /LRU Cache.py: -------------------------------------------------------------------------------- 1 | class LRUCache: 2 | def __init__(self, capacity): 3 | self.cache = collections.OrderedDict() 4 | self.capacity = capacity 5 | 6 | def get(self, key): 7 | if key not in self.cache: 8 | return -1 9 | val = self.cache[key] 10 | del self.cache[key] 11 | self.cache[key] = val 12 | return val 13 | 14 | def set(self, key, value): 15 | if key in self.cache: 16 | del self.cache[key] 17 | elif len(self.cache) == self.capacity: 18 | self.cache.popitem(last=False) 19 | self.cache[key] = value 20 | 21 | # Following is the implementation without using ordereddict. 22 | class ListNode: 23 | def __init__(self, key, val): 24 | self.val = val 25 | self.key = key 26 | self.next = None 27 | self.prev = None 28 | 29 | class LinkedList: 30 | def __init__(self): 31 | self.head = None 32 | self.tail = None 33 | 34 | def insert(self, node): 35 | if self.head is None: 36 | self.head = node 37 | else: 38 | self.tail.next = node 39 | node.prev = self.tail 40 | self.tail = node 41 | 42 | def delete(self, node): 43 | if node.prev: 44 | node.prev.next = node.next 45 | else: 46 | self.head = node.next 47 | if node.next: 48 | node.next.prev = node.prev 49 | else: 50 | self.tail = node.prev 51 | 52 | class LRUCache: 53 | def __init__(self, capacity): 54 | self.list = LinkedList() 55 | self.dict = {} 56 | self.capacity = capacity 57 | 58 | def _insert(self, key, val): 59 | node = ListNode(key, val) 60 | self.list.insert(node) 61 | self.dict[key] = node 62 | 63 | def get(self, key): 64 | if key in self.dict: 65 | val = self.dict[key].val 66 | self.list.delete(self.dict[key]) 67 | self._insert(key, val) 68 | return val 69 | return -1 70 | 71 | def set(self, key, val): 72 | if key in self.dict: 73 | self.list.delete(self.dict[key]) 74 | elif len(self.dict) == self.capacity: 75 | del self.dict[self.list.head.key] 76 | self.list.delete(self.list.head) 77 | self._insert(key, val) -------------------------------------------------------------------------------- /Largest Rectangle in Histogram.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def largestRectangleArea(self, height): 3 | increasing, area, i = [], 0, 0 4 | while i <= len(height): 5 | if len(increasing) == 0 or (i < len(height) and height[i] > height[increasing[-1]]): 6 | increasing.append(i) 7 | i += 1 8 | else: 9 | last = increasing.pop() 10 | if len(increasing) == 0: 11 | area = max(area, height[last] * i) 12 | else: 13 | area = max(area, height[last] * (i - increasing[-1] - 1)) 14 | return area -------------------------------------------------------------------------------- /Length of Last Word.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def lengthOfLastWord(self, s): 3 | return len(s.strip().split(" ")[-1]) -------------------------------------------------------------------------------- /Letter Combinations of a Phone Number.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def letterCombinations(self, digits): 3 | lookup, res = ["", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"], [] 4 | self.letterCombinationsRecur(lookup, res, "", digits) 5 | return res 6 | 7 | def letterCombinationsRecur(self, lookup, res, current, digits): 8 | if digits == "": 9 | res.append(current) 10 | return 11 | for choice in lookup[int(digits[0])]: 12 | self.letterCombinationsRecur(lookup, res, current + choice, digits[1:]) -------------------------------------------------------------------------------- /Linked List Cycle II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def detectCycle(self, head): 3 | fast, slow = head, head 4 | while fast and fast.next: 5 | fast, slow = fast.next.next, slow.next 6 | if fast is slow: 7 | fast = head 8 | while fast is not slow: 9 | fast, slow = fast.next, slow.next 10 | return fast 11 | return None -------------------------------------------------------------------------------- /Linked List Cycle.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def hasCycle(self, head): 3 | fast, slow = head, head 4 | while fast and fast.next: 5 | fast, slow = fast.next.next, slow.next 6 | if fast is slow: 7 | return True 8 | return False -------------------------------------------------------------------------------- /Longest Common Prefix.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def longestCommonPrefix(self, strs): 3 | if len(strs) == 0: 4 | return "" 5 | longest = strs[0] 6 | for str in strs[1:]: 7 | i = 0 8 | while i < len(str) and i < len(longest) and str[i] == longest[i]: 9 | i += 1 10 | longest = longest[:i] 11 | return longest -------------------------------------------------------------------------------- /Longest Consecutive Sequence.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def longestConsecutive(self, nums): 3 | lookup, longest = {num: False for num in nums}, 0 4 | for num in lookup: 5 | if lookup[num] == False: 6 | lookup[num] = True 7 | consecutive, i, j = 1, num + 1, num - 1 8 | while i in lookup and lookup[i] == False: 9 | consecutive += 1 10 | lookup[i] = True 11 | i += 1 12 | while j in lookup and lookup[j] == False: 13 | consecutive += 1 14 | lookup[j] = True 15 | j -= 1 16 | longest = max(longest, consecutive) 17 | return longest 18 | 19 | # def longestConsecutive(self, num): 20 | # """Using visited set is also fine. 21 | # """ 22 | # visited, sequence, count = set([]), set(num), {} 23 | # for x in num: 24 | # if x in visited: 25 | # continue 26 | # count[x] = 1 27 | # left, right = x - 1, x + 1 28 | # while right in sequence: 29 | # visited.add(right) 30 | # count[x] += 1 31 | # right += 1 32 | # while left in sequence: 33 | # visited.add(left) 34 | # count[x] += 1 35 | # left -=1 36 | # visited.add(x) 37 | # return reduce(max, count.values()) -------------------------------------------------------------------------------- /Longest Palindromic Substring.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def longestPalindrome(self, s): 3 | longest, mid = "", (len(s) - 1) / 2 4 | i, j = mid, mid 5 | while i >= 0 and j < len(s): 6 | args = [(s, i, i), (s, i, i + 1), (s, j, j), (s, j, j + 1)] 7 | for arg in args: 8 | tmp = self.longestPalindromeByAxis(*arg) 9 | if len(tmp) > len(longest): 10 | longest = tmp 11 | if len(longest) >= i * 2: 12 | return longest 13 | i, j = i - 1, j + 1 14 | return longest 15 | 16 | def longestPalindromeByAxis(self, s, left, right): 17 | while left >= 0 and right < len(s) and s[left] == s[right]: 18 | left, right = left - 1, right + 1 19 | return s[left + 1 : right] -------------------------------------------------------------------------------- /Longest Substring Without Repeating Characters.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def lengthOfLongestSubstring(self, s): 3 | longest, start, visited = 0, 0, [False for i in range(256)] 4 | for i, char in enumerate(s): 5 | if visited[ord(char)] == False: 6 | visited[ord(char)] = True 7 | else: 8 | while s[start] != char: 9 | visited[ord(s[start])] = False 10 | start += 1 11 | start += 1 12 | longest = max(longest, i - start + 1) 13 | return longest -------------------------------------------------------------------------------- /Longest Valid Parentheses.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def longestValidParentheses(self, s): 3 | longest, last, indices = 0, 0, [] 4 | for i in range(len(s)): 5 | if s[i] == '(': 6 | indices.append(i) 7 | elif len(indices) == 0: 8 | last = i + 1 9 | else: 10 | index = indices.pop() 11 | if len(indices) == 0: 12 | longest = max(longest, i - last + 1) 13 | else: 14 | longest = max(longest, i - indices[-1]) 15 | return longest -------------------------------------------------------------------------------- /Max Points on a Line.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def maxPoints(self, points): 3 | max_points = 0 4 | for i in range(len(points)): 5 | map, same, current_max, inf, start = {}, 1, 0, 0, points[i] 6 | for j in range(i + 1, len(points)): 7 | end = points[j] 8 | if start.x == end.x and start.y == end.y: 9 | same += 1 10 | elif start.x == end.x: 11 | inf += 1 12 | else: 13 | slope = (start.y - end.y) * 1.0 / (start.x - end.x) 14 | if slope not in map: 15 | map[slope] = 1 16 | else: 17 | map[slope] += 1 18 | for slope in map: 19 | current_max = max(current_max, map[slope] + same) 20 | max_points = max(max_points, current_max, same + inf) 21 | return max_points -------------------------------------------------------------------------------- /Maximal Rectangle.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def maximalRectangle(self, matrix): 3 | heights = [[0 for j in range(len(matrix[0]))] for i in range(len(matrix))] 4 | for i in range(0, len(matrix)): 5 | for j in range(len(matrix[0])): 6 | if matrix[i][j] == "0": 7 | heights[i][j] = 0 8 | elif i == 0: 9 | heights[i][j] = 1 10 | else: 11 | heights[i][j] = int(heights[i - 1][j]) + 1 12 | return reduce(lambda acc, i: max(acc, self.largestRectangleArea(heights[i])), range(len(heights)), 0) 13 | 14 | # This is the solution for question Largest Rectangle in Histogram 15 | def largestRectangleArea(self, height): 16 | increasing, area, i = [], 0, 0 17 | while i <= len(height): 18 | if len(increasing) == 0 or (i < len(height) and height[i] > height[increasing[-1]]): 19 | increasing.append(i) 20 | i += 1 21 | else: 22 | last = increasing.pop() 23 | if len(increasing) == 0: 24 | area = max(area, height[last] * i) 25 | else: 26 | area = max(area, height[last] * (i - increasing[-1] - 1)) 27 | return area -------------------------------------------------------------------------------- /Maximum Depth of Binary Tree.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def maxDepth(self, root): 10 | if root == None: 11 | return 0 12 | return max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1 -------------------------------------------------------------------------------- /Maximum Subarray.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def maxSubArray(self, A): 3 | global_max, local_max = -9223372036854775808, 0 4 | for element in A: 5 | global_max = max(global_max, local_max + element) 6 | local_max = max(0, local_max + element) 7 | return global_max -------------------------------------------------------------------------------- /Merge Intervals.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def merge(self, intervals): 3 | if len(intervals) == 0: 4 | return intervals 5 | intervals.sort(key = lambda x: x.start) 6 | result = [intervals[0]] 7 | for i in range(1, len(intervals)): 8 | current, prev = intervals[i], result[-1] 9 | if current.start <= prev.end: 10 | prev.end = max(prev.end, current.end) 11 | else: 12 | result.append(current) 13 | return result -------------------------------------------------------------------------------- /Merge Sorted Array.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def merge(self, A, m, B, n): 3 | last, i, j = m + n - 1, m - 1, n - 1 4 | while i >= 0 and j >= 0: 5 | if A[i] > B[j]: 6 | A[last] = A[i] 7 | i, last = i - 1, last - 1 8 | else: 9 | A[last] = B[j] 10 | j, last = j - 1, last - 1 11 | while j >= 0: 12 | A[last] = B[j] 13 | j, last = j - 1, last - 1 -------------------------------------------------------------------------------- /Merge Two Sorted Lists.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def mergeTwoLists(self, l1, l2): 3 | dummy = ListNode(0) 4 | current = dummy 5 | while l1 and l2: 6 | if l1.val < l2.val: 7 | current.next = l1 8 | l1 = l1.next 9 | else: 10 | current.next = l2 11 | l2 = l2.next 12 | current = current.next 13 | if l1: 14 | current.next = l1 15 | else: 16 | current.next = l2 17 | return dummy.next -------------------------------------------------------------------------------- /Merge k Sorted Lists.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def mergeKLists(self, lists): 3 | dummy = ListNode(0) 4 | current = dummy 5 | heap = [] 6 | for sorted_list in lists: 7 | if sorted_list: 8 | heapq.heappush(heap, (sorted_list.val, sorted_list)) 9 | while heap: 10 | smallest = heapq.heappop(heap)[1] 11 | current.next = smallest 12 | current = current.next 13 | if smallest.next: 14 | heapq.heappush(heap, (smallest.next.val, smallest.next)) 15 | return dummy.next -------------------------------------------------------------------------------- /Minimum Depth of Binary Tree.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def minDepth(self, root): 3 | if root is None: 4 | return 0 5 | if root.left and root.right is None: 6 | return self.minDepth(root.left) + 1 7 | elif root.right and root.left is None: 8 | return self.minDepth(root.right) + 1 9 | return min(self.minDepth(root.left), self.minDepth(root.right)) + 1 10 | 11 | # def minDepth(self, root): 12 | # """ This method has better readability, but more recursive calls. 13 | # """ 14 | # if root == None: 15 | # return 0 16 | # left_nodes = self.minDepth(root.left) 17 | # right_nodes = self.minDepth(root.right) 18 | # if left_nodes == 0 or right_nodes == 0: 19 | # return 1 + left_nodes + right_nodes 20 | # return 1 + min(left_nodes, right_nodes) -------------------------------------------------------------------------------- /Minimum Path Sum.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def minPathSum(self, grid): 3 | width, height = len(grid[0]), len(grid) 4 | for i in range(1, width): 5 | grid[0][i] += grid[0][i - 1] 6 | for i in range(1, height): 7 | grid[i][0] += grid[i - 1][0] 8 | for i in range(1, height): 9 | for j in range(1, width): 10 | grid[i][j] += min(grid[i - 1][j], grid[i][j - 1]) 11 | return grid[-1][-1] -------------------------------------------------------------------------------- /Multiply Strings.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def multiply(self, num1, num2): 3 | num1, num2 = num1[::-1], num2[::-1] 4 | result = [0 for i in range(len(num1) + len(num2))] 5 | for i in range(len(num1)): 6 | for j in range(len(num2)): 7 | result[i + j] += int(num1[i]) * int(num2[j]) 8 | carry, total = 0, [] 9 | for digit in result: 10 | sum = carry + digit 11 | carry = sum / 10 12 | total.insert(0, str(sum % 10)) 13 | while len(total) > 1 and total[0] == "0": 14 | del total[0] 15 | return ''.join(total) 16 | 17 | def multiply(self, num1, num2): 18 | """ This problem is actually designed away by Python 19 | """ 20 | return str(int(num1) * int(num2)) -------------------------------------------------------------------------------- /N-Queens II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def totalNQueens(self, n): 3 | return self.solveRecur([], n, 0) 4 | 5 | def solveRecur(self, solution, n, row): 6 | if row == n: 7 | return 1 8 | res = 0 9 | for i in range(n): 10 | if i not in solution and reduce(lambda acc, j: abs(row - j) != abs(i - solution[j]) and acc, range(len(solution)), True): 11 | res += self.solveRecur(solution + [i], n, row + 1) 12 | return res 13 | 14 | # The alternative is to make one line reduce function a separate method. Either way is fine. 15 | 16 | # def is_diagonally_legal(self, solution, n, row, col): 17 | # for i in range(len(solution)): 18 | # if abs(row - i) == abs(col - solution[i]): 19 | # return False 20 | # return True 21 | 22 | # def solveRecur(self, solution, n, col): 23 | # if col == n: 24 | # return 1 25 | # total = 0 26 | # for j in range(n): 27 | # if j not in solution and self.is_diagonally_legal(solution, n, col, j): 28 | # total += self.solveRecur(solution + [j], n, col + 1) 29 | # return total -------------------------------------------------------------------------------- /N-Queens.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def solveNQueens(self, n): 3 | solutions = [] 4 | self.solveRecur(solutions, [], n, 0) 5 | return solutions 6 | 7 | def solveRecur(self, solutions, solution, n, row): 8 | if row == n: 9 | solutions.append(map(lambda x: '.' * x + "Q" + '.' * (n - x - 1), solution)) 10 | for i in range(n): 11 | if i not in solution and reduce(lambda acc, j: abs(row - j) != abs(i - solution[j]) and acc, range(len(solution)), True): 12 | self.solveRecur(solutions, solution + [i], n, row + 1) 13 | 14 | # The alternative is to make one line reduce function a separate method. Either way is fine. 15 | 16 | # def is_diagonally_legal(self, solution, n, row, col): 17 | # for i in range(len(solution)): 18 | # if abs(row - i) == abs(col - solution[i]): 19 | # return False 20 | # return True 21 | 22 | # def solveNQueensRecur(self, solutions, solution, n, i): 23 | # if i == n: 24 | # solutions.append(map(lambda x: '.' * x + "Q" + '.' * (n - x - 1), solution)) 25 | # for j in range(n): 26 | # if j not in solution and self.is_diagonally_legal(solution, n, i, j): 27 | # self.solveNQueensRecur(solutions, solution + [j], n, i + 1) -------------------------------------------------------------------------------- /Next Permutation.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def nextPermutation(self, num): 3 | k, l = -1, 0 4 | for i in range(len(num) - 1): 5 | if num[i] < num[i + 1]: 6 | k = i 7 | if k == -1: 8 | return num[::-1] 9 | for i in range(len(num)): 10 | if num[i] > num[k]: 11 | l = i 12 | num[k], num[l] = num[l], num[k] 13 | return num[:k + 1] + num[:k:-1] -------------------------------------------------------------------------------- /Palindrome Number.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def isPalindrome(self, x): 3 | if x < 0: 4 | return False 5 | copy, reverse = x, 0 6 | while copy > 0: 7 | reverse = 10 * reverse + copy % 10 8 | copy /= 10 9 | return reverse == x -------------------------------------------------------------------------------- /Palindrome Partitioning II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def minCut(self, s): 3 | lookup, mincut = [[False for j in range(len(s))] for i in range(len(s))], [0 for i in range(len(s))] 4 | for i in reversed(range(len(s))): 5 | for j in range(i, len(s)): 6 | if s[i] == s[j] and (j - i < 2 or lookup[i + 1][j - 1]): 7 | lookup[i][j] = True 8 | else: 9 | lookup[i][j] = False 10 | for i in range(len(s)): 11 | min_so_far = 2147483647 12 | if lookup[0][i] == False: 13 | for j in range(i): 14 | if lookup[j + 1][i] == True: 15 | min_so_far = min(min_so_far, mincut[j] + 1) 16 | else: 17 | min_so_far = 0 18 | mincut[i] = min_so_far 19 | return mincut[-1] -------------------------------------------------------------------------------- /Palindrome Partitioning.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def partition(self, s): 3 | result = [] 4 | self.partitionRecur(result, [], s, 0) 5 | return result 6 | 7 | def partitionRecur(self, result, current, s, i): 8 | if i == len(s): 9 | result.append(current) 10 | else: 11 | for j in range(i, len(s)): 12 | if self.isPalindrome(s[i: j + 1]): 13 | self.partitionRecur(result, current + [s[i: j + 1]], s, j + 1) 14 | 15 | def isPalindrome(self, s): 16 | for i in range(len(s) / 2): 17 | if s[i] != s[-(i + 1)]: 18 | return False 19 | return True -------------------------------------------------------------------------------- /Partition List.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def partition(self, head, x): 3 | smaller, larger = ListNode(0), ListNode(0) 4 | smaller_copy, larger_copy = smaller, larger 5 | while head != None: 6 | if head.val < x: 7 | smaller.next = head 8 | smaller = smaller.next 9 | else: 10 | larger.next = head 11 | larger = larger.next 12 | head = head.next 13 | smaller.next = larger_copy.next 14 | larger.next = None 15 | return smaller_copy.next -------------------------------------------------------------------------------- /Pascal's Triangle II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def getRow(self, rowIndex): 3 | result = [1] 4 | for i in range(1, rowIndex + 1): 5 | result = [1] + [result[j - 1] + result[j] for j in range(1, i)] + [1] 6 | return result -------------------------------------------------------------------------------- /Pascal's Triangle.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def generate(self, numRows): 3 | triangles = [] 4 | for i in range(numRows): 5 | triangles.append([]) 6 | for j in range(i + 1): 7 | if j == 0 or j == i: 8 | triangles[i].append(1) 9 | else: 10 | triangles[i].append(triangles[i - 1][j - 1] + triangles[i - 1][j]) 11 | return triangles -------------------------------------------------------------------------------- /Path Sum II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def pathSum(self, root, sum): 3 | return self.pathSumRecur([], [], root, sum) 4 | 5 | def pathSumRecur(self, result, path, root, sum): 6 | if root is None: 7 | return result 8 | if root.left is None and root.right is None and root.val == sum: 9 | return result + [path + [root.val]] 10 | return self.pathSumRecur(result, path + [root.val], root.left, sum - root.val) + self.pathSumRecur(result, path + [root.val], root.right, sum - root.val) -------------------------------------------------------------------------------- /Path Sum.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def hasPathSum(self, root, sum): 3 | if root is None: 4 | return False 5 | if root.left is None and root.right is None and sum == root.val: 6 | return True 7 | return self.hasPathSum(root.left, sum - root.val) or self.hasPathSum(root.right, sum - root.val) -------------------------------------------------------------------------------- /Permutation Sequence.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def getPermutation(self, n, k): 3 | seq, k, fact = "", k - 1, math.factorial(n - 1) 4 | perm = [i for i in range(1, n + 1)] 5 | for i in reversed(range(n)): 6 | curr = perm[k / fact] 7 | seq += str(curr) 8 | perm.remove(curr) 9 | if i > 0: 10 | k %= fact 11 | fact /= i 12 | return seq -------------------------------------------------------------------------------- /Permutations II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def permuteUnique(self, nums): 3 | solutions = [[]] 4 | for num in nums: 5 | next = [] 6 | for solution in solutions: 7 | for i in range(len(solution) + 1): 8 | candidate = solution[:i] + [num] + solution[i:] 9 | if candidate not in next: 10 | next.append(candidate) 11 | solutions = next 12 | return solutions -------------------------------------------------------------------------------- /Permutations.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def permute(self, nums): 3 | solutions = [[]] 4 | for num in nums: 5 | next = [] 6 | for solution in solutions: 7 | for i in range(len(solution) + 1): 8 | next.append(solution[:i] + [num] + solution[i:]) 9 | solutions = next 10 | return solutions 11 | 12 | # Recursive Solution 13 | # def permute(self, nums): 14 | # res = [] 15 | # self.permuteRecur(res, [], nums) 16 | # return res 17 | 18 | # def permuteRecur(self, res, current, nums): 19 | # if len(nums) == 0: 20 | # res.append(current) 21 | # return 22 | # for i in range(len(current) + 1): 23 | # self.permuteRecur(res, current[:i] + [nums[0]] + current[i:], nums[1:]) -------------------------------------------------------------------------------- /Plus One.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def plusOne(self, digits): 3 | carry = 1 4 | for i in reversed(range(len(digits))): 5 | sum = digits[i] + carry 6 | digits[i] = sum % 10 7 | carry = sum / 10 8 | if carry: 9 | digits = [1] + digits 10 | return digits -------------------------------------------------------------------------------- /Populating Next Right Pointers in Each Node II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def connect(self, root): 3 | if root is None: 4 | return root 5 | current = [root] 6 | while current: 7 | next = [] 8 | for i in range(len(current)): 9 | if i < len(current) - 1: 10 | current[i].next = current[i + 1] 11 | if current[i].left is not None: 12 | next.append(current[i].left) 13 | if current[i].right is not None: 14 | next.append(current[i].right) 15 | current = next 16 | return root 17 | 18 | #### constant space solution 19 | def connect_2(self, root): 20 | if not root: 21 | return 22 | nexthead = root 23 | while nexthead: 24 | c, nexthead, prevs = nexthead, None, None 25 | while c: 26 | for x in [c.left, c.right]: 27 | if x: 28 | if not nexthead: 29 | nexthead, prevs = x, x 30 | else: 31 | prevs.next, prevs = x, x 32 | c = c.next 33 | 34 | -------------------------------------------------------------------------------- /Populating Next Right Pointers in Each Node.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | 3 | def connect(self, root): 4 | if root is None: 5 | return 6 | if root.left: 7 | root.left.next = root.right 8 | if root.right and root.next: 9 | root.right.next = root.next.left 10 | self.connect(root.left) 11 | self.connect(root.right) 12 | 13 | # constant space solution 14 | def connect_2(self, root): 15 | head = root 16 | while head: 17 | current = head 18 | while current: 19 | if current.left: 20 | current.left.next = current.right 21 | if current.next: 22 | current.right.next = current.next.left 23 | current = current.next 24 | head = head.left 25 | -------------------------------------------------------------------------------- /Pow(x, n).py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def pow(self, x, n): 3 | if n < 0: 4 | return 1 / self.powRecur(x, -n) 5 | return self.powRecur(x, n) 6 | 7 | def powRecur(self, x, n): 8 | if n == 0: 9 | return 1 10 | if n % 2 == 0: 11 | return self.powRecur(x * x, n / 2) 12 | return x * self.powRecur(x * x, n / 2) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This project is no longer maintained here. 2 | 3 | Please go to https://github.com/jw2013/Leetcode-Py for latest update and for making pull request. Thanks! 4 | -------------------------------------------------------------------------------- /Remove Duplicates from Sorted Array II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def removeDuplicates(self, A): 3 | if len(A) == 0: 4 | return 0 5 | i, same = 0, 0 6 | for j in range(1, len(A)): 7 | if A[i] != A[j] or same == 0: 8 | same = A[i] == A[j] 9 | i += 1 10 | A[i] = A[j] 11 | return i + 1 -------------------------------------------------------------------------------- /Remove Duplicates from Sorted Array.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def removeDuplicates(self, A): 3 | if len(A) == 0: 4 | return 0 5 | i = 0 6 | for j in range(1, len(A)): 7 | if A[i] != A[j]: 8 | i += 1 9 | A[i] = A[j] 10 | return i + 1 -------------------------------------------------------------------------------- /Remove Duplicates from Sorted List II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def deleteDuplicates(self, head): 3 | dummy = ListNode(0) 4 | dummy.next = head 5 | current = dummy 6 | while current.next: 7 | next = current.next 8 | while next.next and next.next.val == next.val: 9 | next = next.next 10 | if current.next is not next: 11 | current.next = next.next 12 | else: 13 | current = current.next 14 | return dummy.next -------------------------------------------------------------------------------- /Remove Duplicates from Sorted List.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def deleteDuplicates(self, head): 3 | current = head 4 | while current and current.next: 5 | next = current.next 6 | if current.val == next.val: 7 | current.next = current.next.next 8 | else: 9 | current = next 10 | return head -------------------------------------------------------------------------------- /Remove Element.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def removeElement(self, A, elem): 3 | last, i = len(A) - 1, 0 4 | while i <= last: 5 | if A[i] == elem: 6 | A[i], A[last] = A[last], A[i] 7 | last -= 1 8 | else: 9 | i += 1 10 | return last + 1 -------------------------------------------------------------------------------- /Remove Nth Node From End of List.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def removeNthFromEnd(self, head, n): 3 | fast, slow, prev = head, head, None 4 | while n > 0: 5 | fast, n = fast.next, n - 1 6 | while fast != None: 7 | fast, slow, prev = fast.next, slow.next, slow 8 | if prev == None: 9 | return head.next 10 | prev.next = prev.next.next 11 | return head -------------------------------------------------------------------------------- /Reorder List.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def reorderList(self, head): 3 | if head == None or head.next == None: 4 | return head 5 | fast, slow, prev = head, head, None 6 | while fast != None and fast.next != None: 7 | fast, slow, prev = fast.next.next, slow.next, slow 8 | current, prev.next, prev = slow, None, None 9 | while current != None: 10 | tmp = current.next 11 | current.next = prev 12 | prev = current 13 | current = tmp 14 | l1, l2 = head, prev 15 | current = l1 16 | while l1 != None and l2 != None: 17 | current.next, current, l1 = l1, l1, l1.next 18 | current.next, current, l2 = l2, l2, l2.next 19 | return head -------------------------------------------------------------------------------- /Restore IP Addresses.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def restoreIpAddresses(self, s): 3 | result = [] 4 | self.restoreIpAddressesRecur(result, s, "", 0) 5 | return result 6 | 7 | def restoreIpAddressesRecur(self, result, s, current, dots): 8 | # pruning to improve performance 9 | if (4 - dots) * 3 < len(s): 10 | return 11 | if dots == 3: 12 | if self.isValid(s): 13 | result.append(current + s) 14 | else: 15 | for i in range(3): 16 | if len(s) > i and self.isValid(s[:i + 1]): 17 | self.restoreIpAddressesRecur(result, s[i + 1:], current + s[:i + 1] + '.', dots + 1) 18 | 19 | def isValid(self, s): 20 | if len(s) == 0 or (s[0] == "0" and s != "0"): 21 | return False 22 | return int(s) < 256 -------------------------------------------------------------------------------- /Reverse Integer.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def reverse(self, x): 3 | sign = 1 4 | result = 0 5 | if x < 0: 6 | sign = -1 7 | x = -x 8 | while x > 0: 9 | result = result * 10 + x % 10 10 | x /= 10 11 | return sign * result -------------------------------------------------------------------------------- /Reverse Linked List II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def reverseBetween(self, head, m, n): 3 | diff, dummy, current= n - m, ListNode(0), head 4 | dummy.next = head 5 | last_unswapped = dummy 6 | while current != None and m > 1: 7 | current, last_unswapped, m = current.next, current, m - 1 8 | prev, first_swapped = last_unswapped, current 9 | while current != None and diff >= 0: 10 | tmp = current.next 11 | current.next = prev 12 | prev = current 13 | current = tmp 14 | diff -= 1 15 | last_unswapped.next, first_swapped.next = prev, current 16 | return dummy.next -------------------------------------------------------------------------------- /Reverse Words in a String.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def reverseWords(self, s): 3 | return " ".join(filter(lambda x: x, reversed(s.split(" ")))) -------------------------------------------------------------------------------- /Roman to Integer.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def romanToInt(self, S): 3 | numeral_map = {"I": 1, "V": 5, "X": 10, "L": 50, "C":100, "D": 500, "M": 1000} 4 | decimal = 0 5 | for i in reversed(range(len(S))): 6 | if i == len(S) - 1 or numeral_map[S[i]] >= numeral_map[S[i + 1]]: 7 | decimal += numeral_map[S[i]] 8 | else: 9 | decimal -= numeral_map[S[i]] 10 | return decimal -------------------------------------------------------------------------------- /Rotate Image.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def rotate(self, matrix): 3 | return [list(reversed(x)) for x in zip(*matrix)] -------------------------------------------------------------------------------- /Rotate List.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def rotateRight(self, head, k): 3 | if head is None: 4 | return None 5 | copy, length = head, 1 6 | while copy.next: 7 | copy, length = copy.next, length + 1 8 | copy.next = head 9 | k = length - k % length - 1 10 | while k > 0: 11 | head, k = head.next, k - 1 12 | tmp = head.next 13 | head.next = None 14 | return tmp -------------------------------------------------------------------------------- /Same Tree.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def isSameTree(self, p, q): 3 | if p is None and q is None: 4 | return True 5 | elif p is None or q is None or p.val != q.val: 6 | return False 7 | return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right) -------------------------------------------------------------------------------- /Search Insert Position.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def searchInsert(self, A, target): 3 | return self.searchInsertRecur(A, target, 0, len(A) - 1) 4 | 5 | def searchInsertRecur(self, A, target, low, high): 6 | mid = (high + low) / 2 7 | if low > high: 8 | return low 9 | if A[mid] == target: 10 | return mid 11 | if A[mid] < target: 12 | return self.searchInsertRecur(A, target, mid + 1, high) 13 | else: 14 | return self.searchInsertRecur(A, target, low, mid - 1) 15 | 16 | # def searchInsert(self, A, target): 17 | # """Iterative solution is also fine. 18 | # """ 19 | # low, high = 0, len(A) - 1 20 | # while low <= high: 21 | # mid = (low + high) / 2 22 | # if A[mid] == target: 23 | # return mid 24 | # elif A[mid] < target: 25 | # low = mid + 1 26 | # else: 27 | # high = mid - 1 28 | # return low -------------------------------------------------------------------------------- /Search a 2D Matrix.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def searchMatrix(self, matrix, target): 3 | i, j = 0, len(matrix[0]) - 1 4 | while i < len(matrix) and j >= 0: 5 | if target < matrix[i][j]: 6 | j -= 1 7 | elif target > matrix[i][j]: 8 | i += 1 9 | else: 10 | return True 11 | return False -------------------------------------------------------------------------------- /Search for a Range.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def searchRange(self, A, target): 3 | left = self.searchRangeRecur(A, target, lambda x, y: x >= y, 0, len(A) - 1) 4 | if left >= len(A) or A[left] != target: 5 | return [-1, -1] 6 | right = self.searchRangeRecur(A, target, lambda x, y: x > y, 0, len(A) - 1) - 1 7 | return [left, right] 8 | 9 | def searchRangeRecur(self, A, target, compare, left, right): 10 | if left > right: 11 | return left 12 | mid = (left + right) / 2 13 | if compare(A[mid], target): 14 | return self.searchRangeRecur(A, target, compare, left, mid - 1) 15 | return self.searchRangeRecur(A, target, compare, mid + 1, right) 16 | 17 | def searchRange(self, A, target): 18 | """ The iterative solution is also fine. 19 | """ 20 | start, end, range = 0, len(A) - 1, [] 21 | while start < end: 22 | mid = (start + end) / 2 23 | if target <= A[mid]: 24 | end = mid 25 | else: 26 | start = mid + 1 27 | if A[start] != target: 28 | return [-1, -1] 29 | range.append(start) 30 | start, end = 0, len(A) 31 | while start < end: 32 | mid = (start + end) / 2 33 | if target >= A[mid]: 34 | start = mid + 1 35 | else: 36 | end = mid 37 | return range + [start - 1] -------------------------------------------------------------------------------- /Search in Rotated Sorted Array II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def search(self, A, target): 3 | return self.searchRecur(A, target, len(A) - 1, 0) 4 | 5 | def searchRecur(self, A, target, high, low): 6 | if high < low: 7 | return False 8 | mid = (high + low) / 2 9 | if A[mid] == target: 10 | return True 11 | while A[low] == A[mid] and A[mid] == A[high] and high > low: 12 | low, high = low + 1, high - 1 13 | if (A[0] <= A[mid] and target < A[mid] and target >= A[0]) or (A[mid] <= A[high] and (target < A[mid] or target > A[high])): 14 | return self.searchRecur(A, target, mid - 1, low) 15 | else: 16 | return self.searchRecur(A, target, high, low + 1) -------------------------------------------------------------------------------- /Search in Rotated Sorted Array.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def search(self, A, target): 3 | return self.searchRecur(A, target, len(A) - 1, 0) 4 | 5 | def searchRecur(self, A, target, high, low): 6 | if high < low: 7 | return -1 8 | mid = (high + low) / 2 9 | if A[mid] == target: 10 | return mid 11 | if (A[0] < A[mid] and target < A[mid] and target >= A[0]) or (A[mid] < A[high] and (target < A[mid] or target > A[high])): 12 | return self.searchRecur(A, target, mid - 1, low) 13 | else: 14 | return self.searchRecur(A, target, high, low + 1) -------------------------------------------------------------------------------- /Set Matrix Zeroes.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | # Constant space solution 3 | def setZeroes(self, matrix): 4 | first_row = reduce(lambda acc, i: acc or matrix[0][i] == 0, range(len(matrix[0])), False) 5 | first_col = reduce(lambda acc, i: acc or matrix[i][0] == 0, range(len(matrix)), False) 6 | for i in range(1, len(matrix)): 7 | for j in range(1, len(matrix[0])): 8 | if matrix[i][j] == 0: 9 | matrix[i][0], matrix[0][j] = 0, 0 10 | for i in range(1, len(matrix)): 11 | for j in range(1, len(matrix[0])): 12 | if matrix[i][0] == 0 or matrix[0][j] == 0: 13 | matrix[i][j] = 0 14 | if first_col: 15 | for i in range(len(matrix)): 16 | matrix[i][0] = 0 17 | if first_row: 18 | for i in range(len(matrix[0])): 19 | matrix[0][i] = 0 20 | 21 | # O(m + n) solution 22 | # def setZeroes(self, matrix): 23 | # rows = [False for i in range(len(matrix))] 24 | # cols = [False for i in range(len(matrix[0]))] 25 | # for i in range(len(matrix)): 26 | # for j in range(len(matrix[i])): 27 | # rows[i] = rows[i] or matrix[i][j] == 0 28 | # cols[j] = cols[j] or matrix[i][j] == 0 29 | # for i in range(len(matrix)): 30 | # for j in range(len(matrix[i])): 31 | # if rows[i] or cols[j]: 32 | # matrix[i][j] = 0 -------------------------------------------------------------------------------- /Simplify Path.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def simplifyPath(self, path): 3 | stack, tokens = [], path.split("/") 4 | for token in tokens: 5 | if token == ".." and stack: 6 | stack.pop() 7 | elif token != ".." and token != "." and token: 8 | stack.append(token) 9 | return "/" + "/".join(stack) -------------------------------------------------------------------------------- /Single Number II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def singleNumber(self, A): 3 | one, two, three = 0, 0, 0 4 | for i in range(len(A)): 5 | two |= one & A[i]; 6 | one ^= A[i]; 7 | three = one & two; 8 | one &= ~three; 9 | two &= ~three; 10 | return one; -------------------------------------------------------------------------------- /Single Number.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def singleNumber(self, A): 3 | return reduce(operator.xor, A) -------------------------------------------------------------------------------- /Sort Colors.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def sortColors(self, A): 3 | i, last_zero, first_two = 0, -1, len(A) 4 | while i < first_two: 5 | if A[i] == 0: 6 | last_zero += 1 7 | A[last_zero], A[i] = A[i], A[last_zero] 8 | if A[i] == 2: 9 | first_two -= 1 10 | A[first_two], A[i] = A[i], A[first_two] 11 | i -= 1 12 | i += 1 -------------------------------------------------------------------------------- /Sort List.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def mergeTwoLists(self, l1, l2): 3 | head = ListNode(0) 4 | current = head 5 | while l1 != None and l2 != None: 6 | if l1.val <= l2.val: 7 | current.next, current, l1 = l1, l1, l1.next 8 | else: 9 | current.next, current, l2 = l2, l2, l2.next 10 | if l1 != None: 11 | current.next = l1 12 | if l2 != None: 13 | current.next = l2 14 | return head.next 15 | 16 | def sortList(self, head): 17 | if head == None or head.next == None: 18 | return head 19 | fast, slow, prev = head, head, None 20 | while fast != None and fast.next != None: 21 | prev, fast, slow = slow, fast.next.next, slow.next 22 | prev.next = None 23 | sorted_l1 = self.sortList(head) 24 | sorted_l2 = self.sortList(slow) 25 | return self.mergeTwoLists(sorted_l1, sorted_l2) -------------------------------------------------------------------------------- /Spiral Matrix II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def generateMatrix(self, n): 3 | matrix = [[0 for i in range(n)] for i in range(n)] 4 | left, right, top, bottom, num = 0, n - 1, 0, n - 1, 1 5 | while left <= right and top <= bottom: 6 | for i in range(left, right + 1): 7 | matrix[top][i] = num 8 | num += 1 9 | for i in range(top + 1, bottom): 10 | matrix[i][right] = num 11 | num += 1 12 | for i in reversed(range(left, right + 1)): 13 | if top < bottom: 14 | matrix[bottom][i] = num 15 | num += 1 16 | for i in reversed(range(top + 1, bottom)): 17 | matrix[i][left] = num 18 | num += 1 19 | left, right, top, bottom = left + 1, right - 1, top + 1, bottom - 1 20 | return matrix -------------------------------------------------------------------------------- /Spiral Matrix.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def spiralOrder(self, matrix): 3 | result = [] 4 | if matrix == [] or matrix[0] == []: 5 | return result 6 | left, right, top, bottom = 0, len(matrix[0]) - 1, 0, len(matrix) - 1 7 | while left <= right and top <= bottom: 8 | for i in range(left, right + 1): 9 | result.append(matrix[top][i]) 10 | for i in range(top + 1, bottom): 11 | result.append(matrix[i][right]) 12 | for i in reversed(range(left, right + 1)): 13 | if top < bottom: 14 | result.append(matrix[bottom][i]) 15 | for i in reversed(range(top + 1, bottom)): 16 | if left < right: 17 | result.append(matrix[i][left]) 18 | left, right, top, bottom = left + 1, right - 1, top + 1, bottom - 1 19 | return result -------------------------------------------------------------------------------- /Sqrt(x).py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def sqrt(self, x): 3 | low, high = 0, x / 2 + 1 4 | while high >= low: 5 | mid = (high + low) / 2 6 | if x < mid * mid: 7 | high = mid - 1 8 | else: 9 | low = mid + 1 10 | return int(high) -------------------------------------------------------------------------------- /String to Integer (atoi).py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def atoi(self, str): 3 | i, sign, ret = 0, 1, 0 4 | if len(str) == 0: 5 | return 0 6 | while i < len(str) and str[i] == ' ': 7 | i += 1 8 | if str[i] == '+': 9 | i += 1 10 | elif str[i] == '-': 11 | sign = -1 12 | i += 1 13 | while i < len(str) and str[i] >= '0' and str[i] <= '9': 14 | ret = ret * 10 + ord(str[i]) - ord('0') 15 | i += 1 16 | return max(min(ret * sign, 2147483647), -2147483648) -------------------------------------------------------------------------------- /Subsets II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def subsetsWithDup(self, S): 3 | results = [] 4 | self.subsetsRecur(results, [], sorted(S)) 5 | return results 6 | 7 | def subsetsRecur(self, results, result, S): 8 | if len(S) == 0 and result not in results: 9 | results.append(result) 10 | elif len(S): 11 | self.subsetsRecur(results, result, S[1:]) 12 | self.subsetsRecur(results, result + [S[0]], S[1:]) -------------------------------------------------------------------------------- /Subsets.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def subsets(self, S): 3 | return self.subsetsRecur([], sorted(S)) 4 | 5 | def subsetsRecur(self, current, S): 6 | if S: 7 | return self.subsetsRecur(current, S[1:]) + self.subsetsRecur(current + [S[0]], S[1:]) 8 | return [current] -------------------------------------------------------------------------------- /Sum Root to Leaf Numbers.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def sumNumbers(self, root): 3 | return self.sumNumbersRecur(root, 0) 4 | 5 | def sumNumbersRecur(self, root, sum): 6 | if root == None: 7 | return 0 8 | if root.left == None and root.right == None: 9 | return 10 * sum + root.val 10 | return self.sumNumbersRecur(root.left, 10 * sum + root.val) + self.sumNumbersRecur(root.right, 10 * sum + root.val) -------------------------------------------------------------------------------- /Surrounded Regions.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def solve(self, board): 3 | if len(board) == 0: 4 | return 5 | visited = [[False for j in range(len(board[0]))] for i in range(len(board))] 6 | current = [(i, j) for i in range(len(board)) for j in (0, len(board[0]) - 1)] 7 | current += [(i, j) for i in (0, len(board) - 1) for j in range(len(board[0]))] 8 | while current: 9 | i, j = current.pop() 10 | visited[i][j] = True 11 | if board[i][j] == 'O': 12 | board[i][j] = 'V' 13 | for x, y in [(i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1)]: 14 | if 0 <= x < len(board) and 0 <= y < len(board[0]) and visited[x][y] is False: 15 | visited[x][y] = True 16 | current.append((x, y)) 17 | mapping = {'X': 'X', 'O': 'X', 'V': 'O'} 18 | for i in range(len(board)): 19 | for j in range(len(board[0])): 20 | board[i][j] = mapping[board[i][j]] 21 | 22 | def solve(self, board): 23 | """ Same code. I am not sure which version I like more. 24 | """ 25 | if len(board) == 0: 26 | return 27 | current, visited = [], [[False for j in range(len(board[0]))] for i in range(len(board))] 28 | for i in range(len(board)): 29 | current.append((i, 0)) 30 | current.append((i, len(board[0]) - 1)) 31 | for i in range(len(board[0])): 32 | current.append((0, i)) 33 | current.append((len(board) - 1, i)) 34 | while current: 35 | i, j = current.pop() 36 | visited[i][j] = True 37 | if board[i][j] == 'O': 38 | board[i][j] = 'V' 39 | for x, y in [(i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1)]: 40 | if 0 <= x < len(board) and 0 <= y < len(board[0]) and visited[x][y] is False: 41 | visited[x][y] = True 42 | current.append((x, y)) 43 | for i in range(len(board)): 44 | for j in range(len(board[0])): 45 | if board[i][j] != 'V': 46 | board[i][j] = 'X' 47 | else: 48 | board[i][j] = 'O' -------------------------------------------------------------------------------- /Swap Nodes in Pairs.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def swapPairs(self, head): 3 | if head != None and head.next != None: 4 | next = head.next 5 | head.next = self.swapPairs(next.next) 6 | next.next = head 7 | return next 8 | return head 9 | 10 | # This is the non-recursive solution 11 | # def swapPairs(self, head): 12 | # current = ListNode(0) 13 | # current.next = head 14 | # head = current 15 | # while current.next != None and current.next.next != None: 16 | # next = current.next 17 | # next_three = next.next.next 18 | # current.next = next.next 19 | # current.next.next = next 20 | # next.next = next_three 21 | # current = next 22 | # return head.next -------------------------------------------------------------------------------- /Symmetric Tree.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def isSymmetric(self, root): 3 | if root is None: 4 | return True 5 | return self.isSymmetricRecur(root.left, root.right) 6 | 7 | def isSymmetricRecur(self, left, right): 8 | if left is None and right is None: 9 | return True 10 | if left is None or right is None or left.val != right.val: 11 | return False 12 | return self.isSymmetricRecur(left.left, right.right) and self.isSymmetricRecur(left.right, right.left) -------------------------------------------------------------------------------- /Trapping Rain Water.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def trap(self, A): 3 | left_max, left_maxes, right_max, right_maxes, water = 0, [], 0, [], 0 4 | for i in range(len(A)): 5 | left_maxes.append(left_max) 6 | left_max = max(A[i], left_max) 7 | for i in reversed(range(len(A))): 8 | right_maxes.insert(0, right_max) 9 | right_max = max(A[i], right_max) 10 | for i in range(len(A)): 11 | water += max(0, min(left_maxes[i], right_maxes[i]) - A[i]) 12 | return water 13 | 14 | # def trap(self, A): 15 | # """ My mania for functional programming needs a serious rest 16 | # """ 17 | # left_highests, left_highest = [], 0 18 | # for i in range(len(A)): 19 | # left_highest = max(left_highest, A[i]) 20 | # left_highests.append(left_highest) 21 | # right_highests, right_highest = [0 for i in range(len(A))], 0 22 | # for i in reversed(range(len(A))): 23 | # right_highest = max(right_highest, A[i]) 24 | # right_highests[i] = right_highest 25 | # return reduce(lambda acc, i: acc + max(0, min(left_highests[i], right_highests[i]) - A[i]), range(len(A)), 0) -------------------------------------------------------------------------------- /Triangle.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def minimumTotal(self, triangle): 3 | if len(triangle) == 0: 4 | return 0 5 | current = triangle[0] 6 | for i in range(1, len(triangle)): 7 | next = [] 8 | next.append(triangle[i][0] + current[0]) 9 | for j in range(1, i): 10 | next.append(triangle[i][j] + min(current[j - 1], current[j])) 11 | next.append(triangle[i][-1] + current[-1]) 12 | current = next 13 | return reduce(min, current) -------------------------------------------------------------------------------- /Two Sum.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def twoSum(self, nums, target): 3 | lookup = {} 4 | for i, num in enumerate(nums): 5 | if target - num in lookup: 6 | return (lookup[target - num] + 1, i + 1) 7 | lookup[num] = i -------------------------------------------------------------------------------- /Unique Binary Search Trees II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def generateTrees(self, n): 3 | return self.generateTreesRecur(1, n) 4 | 5 | def generateTreesRecur(self, low, high): 6 | result = [] 7 | if low > high: 8 | result.append(None) 9 | for i in range(low, high + 1): 10 | left = self.generateTreesRecur(low, i - 1) 11 | right = self.generateTreesRecur(i + 1, high) 12 | for j in left: 13 | for k in right: 14 | current = TreeNode(i) 15 | current.left = j 16 | current.right = k 17 | result.append(current) 18 | return result -------------------------------------------------------------------------------- /Unique Binary Search Trees.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def numTrees(self, n): 3 | counts = [1, 1] 4 | for i in range(2, n + 1): 5 | count = 0 6 | for j in range(0, i): 7 | count += counts[j] * counts[i - j - 1] 8 | counts.append(count) 9 | return counts[-1] -------------------------------------------------------------------------------- /Unique Paths II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def uniquePathsWithObstacles(self, obstacleGrid): 3 | m, n = len(obstacleGrid), len(obstacleGrid[0]) 4 | ways = [[0 for i in range(n)] for i in range(m)] 5 | for i in range(m): 6 | for j in range(n): 7 | if obstacleGrid[i][j] == 0: 8 | if i == 0 and j == 0: 9 | ways[i][j] = 1 10 | elif i == 0: 11 | ways[i][j] = ways[i][j - 1] 12 | elif j == 0: 13 | ways[i][j] = ways[i - 1][j] 14 | else: 15 | ways[i][j] = ways[i - 1][j] + ways[i][j - 1] 16 | return ways[m - 1][n - 1] -------------------------------------------------------------------------------- /Unique Paths.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | 3 | def uniquePaths(self, m, n): 4 | ways = [[1] for i in range(m)] 5 | for i in range(1, n): 6 | ways[0].append(1) 7 | for i in range(1, m): 8 | for j in range(1, n): 9 | ways[i].append(ways[i - 1][j] + ways[i][j - 1]) 10 | return ways[m - 1][n - 1] 11 | 12 | # it's pascal's triangle, we can get result by computing C(m,n), we can 13 | # achieve O(min(m,n)) 14 | 15 | def uniquePaths_2(self, m, n): 16 | if m < n: 17 | return self.uniquePaths(n, m) 18 | if m == 1 and n == 1: 19 | return 1 20 | m, n, res = m + n - 2, n - 1, 1 21 | if n > (m / 2): 22 | n = m - n 23 | for i in xrange(n): 24 | res = res * (m - i) / (i + 1) 25 | return res 26 | -------------------------------------------------------------------------------- /Valid Palindrome.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def isPalindrome(self, s): 3 | i, j = 0, len(s) - 1 4 | while i < j: 5 | while i < j and not (s[i].isalpha() or s[i].isdigit()): 6 | i += 1 7 | while i < j and not (s[j].isalpha() or s[j].isdigit()): 8 | j -= 1 9 | if s[i].lower() != s[j].lower(): 10 | return False 11 | i, j = i + 1, j - 1 12 | return True -------------------------------------------------------------------------------- /Valid Parentheses.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def isValid(self, parentheses): 3 | stack, lookup = [], {"(": ")", "{": "}", "[": "]"} 4 | for parenthese in parentheses: 5 | if parenthese in lookup: 6 | stack.append(parenthese) 7 | elif len(stack) == 0 or lookup[stack.pop()] != parenthese: 8 | return False 9 | return len(stack) == 0 -------------------------------------------------------------------------------- /Valid Sudoku.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def isValidList(self, xs): 3 | xs = filter(lambda x: x != '.', xs) 4 | return len(set(xs)) == len(xs) 5 | 6 | def isValidSudoku(self, board): 7 | for i in range(9): 8 | if not self.isValidList([board[i][j] for j in range(9)]) or not self.isValidList([board[j][i] for j in range(9)]): 9 | return False 10 | for i in range(3): 11 | for j in range(3): 12 | if not self.isValidList([board[k][l] for l in range(3 * j, 3 * j + 3) for k in range(3 * i, 3 * i + 3)]): 13 | return False 14 | return True -------------------------------------------------------------------------------- /Validate Binary Search Tree.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def isValidBST(self, root): 3 | return self.isValidBSTRecur(root, 9223372036854775807, -9223372036854775808) 4 | 5 | def isValidBSTRecur(self, root, upper, lower): 6 | if root is None: 7 | return True 8 | if root.val <= lower or root.val >= upper: 9 | return False 10 | return self.isValidBSTRecur(root.left, root.val, lower) and self.isValidBSTRecur(root.right, upper, root.val) -------------------------------------------------------------------------------- /Word Break II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def wordBreak(self, s, dict): 3 | n = len(s) 4 | f = [False for _ in xrange(n)] 5 | trace = [[False] * n for _ in xrange(n)] 6 | for i in xrange(n): 7 | if s[:i+1] in dict: 8 | f[i] = True 9 | trace[0][i] = True 10 | for j in xrange(i): 11 | if f[j] and s[j+1:i+1] in dict: 12 | f[i] = True 13 | trace[j+1][i] = True 14 | result = [] 15 | if f[n-1]: 16 | self.backtrack(s, trace, 0, [], result) 17 | return result 18 | 19 | def backtrack(self, s, trace, start, path, result): 20 | if start == len(s): 21 | result.append(" ".join(path)) 22 | return 23 | for i in xrange(start, len(s)): 24 | if trace[start][i]: 25 | self.backtrack(s, trace, i + 1, path + [s[start:i+1]], result) 26 | 27 | class Solution: 28 | """ The alternative solution is to precheck before actually break the words. 29 | """ 30 | def canBreak(self, s, dict): 31 | possible = [] 32 | for i in range(len(s)): 33 | if s[:i + 1] in dict: 34 | possible.append(True) 35 | else: 36 | found = False 37 | for j in range(i): 38 | if possible[j] == True and s[j + 1: i + 1] in dict: 39 | found = True 40 | break 41 | possible.append(found) 42 | return possible[len(s) - 1] 43 | 44 | def wordBreak(self, s, dict): 45 | result = {} 46 | if not self.canBreak(s, dict): 47 | return [] 48 | for i in range(len(s)): 49 | result[s[:i + 1]] = [] 50 | if s[:i + 1] in dict: 51 | result[s[:i + 1]] = [s[:i + 1]] 52 | for j in range(i): 53 | if s[:j + 1] in result and s[j + 1: i + 1] in dict: 54 | for k in result[s[:j + 1]]: 55 | result[s[:i + 1]].append(k + " " + s[j + 1: i + 1]) 56 | return result[s] 57 | -------------------------------------------------------------------------------- /Word Break.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def wordBreak(self, s, dict): 3 | possible = [] 4 | for i in range(len(s)): 5 | if s[:i + 1] in dict: 6 | possible.append(True) 7 | else: 8 | found = False 9 | for j in range(i): 10 | if possible[j] == True and s[j + 1: i + 1] in dict: 11 | found = True 12 | break 13 | possible.append(found) 14 | return possible[len(s) - 1] -------------------------------------------------------------------------------- /Word Ladder II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def backtrack(self, result, trace, path, word): 3 | if len(trace[word]) == 0: 4 | result.append([word] + path) 5 | else: 6 | for prev in trace[word]: 7 | self.backtrack(result, trace, [word] + path, prev) 8 | 9 | def findLadders(self, start, end, dict): 10 | result, trace, current = [], {word: [] for word in dict}, set([start]) 11 | while current and end not in current: 12 | for word in current: 13 | dict.remove(word) 14 | next = set([]) 15 | for word in current: 16 | for i in range(len(word)): 17 | for j in 'abcdefghijklmnopqrstuvwxyz': 18 | candidate = word[:i] + j + word[i + 1:] 19 | if candidate in dict: 20 | trace[candidate].append(word) 21 | next.add(candidate) 22 | current = next 23 | if current: 24 | self.backtrack(result, trace, [], end) 25 | return result -------------------------------------------------------------------------------- /Word Ladder.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def ladderLength(self, start, end, dict): 3 | distance, current, visited = 0, [start], set([start]) 4 | dict.add(end) 5 | while current: 6 | next = [] 7 | for word in current: 8 | if word == end: 9 | return distance + 1 10 | for i in range(len(word)): 11 | for j in 'abcdefghijklmnopqrstuvwxyz': 12 | candidate = word[:i] + j + word[i + 1:] 13 | if candidate not in visited and candidate in dict: 14 | next.append(candidate) 15 | visited.add(candidate) 16 | distance += 1 17 | current = next 18 | return 0 -------------------------------------------------------------------------------- /Word Search.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def exist(self, board, word): 3 | visited = [[0 for y in range(len(board[0]))] for x in range(len(board))] 4 | for i in range(len(board)): 5 | for j in range(len(board[0])): 6 | if self.existRecur(board, word, visited, i, j) == True: 7 | return True 8 | return False 9 | 10 | def existRecur(self, board, word, visited, i, j): 11 | if len(word) == 0: 12 | return True 13 | if i >= len(board) or j >= len(board[0]) or i < 0 or j < 0 or visited[i][j] == 1 or board[i][j] != word[0]: 14 | return False 15 | visited[i][j] = 1 16 | found = self.existRecur(board, word[1:], visited, i + 1, j) or self.existRecur(board, word[1:], visited, i - 1, j) or self.existRecur(board, word[1:], visited, i, j + 1) or self.existRecur(board, word[1:], visited, i, j - 1) 17 | visited[i][j] = 0 18 | return found -------------------------------------------------------------------------------- /ZigZag Conversion.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def convert(self, s, nRows): 3 | step, zigzag = 2 * nRows - 2, "" 4 | if s == None or len(s) == 0 or nRows <= 0: 5 | return "" 6 | if nRows == 1: 7 | return s 8 | for i in range(nRows): 9 | for j in range(i, len(s), step): 10 | zigzag += s[j] 11 | if i > 0 and i < nRows - 1 and j + step - 2 * i < len(s): 12 | zigzag += s[j + step - 2 * i] 13 | return zigzag --------------------------------------------------------------------------------