├── 0_icons └── book.png ├── Array ├── 3SumWithMultiplicity.py ├── AddTowNumbersII.py ├── AddTwoNumbers.py ├── BestTimeToBuyAndSellStockI_II.py ├── BinarySubarraysWithSum.py ├── ContainerWithMostWater.py ├── CountOfSmallerNumbersAfterSelf.py ├── FairCandySwap.py ├── FindFirstAndLastPositionOfElementInSortedArray.py ├── FindMinimumInRotatedSortedArray.py ├── FindMinimumInRotatedSortedArrayII.py ├── FindPeakElement.py ├── FizzBuzz.py ├── FootballFans.py ├── FruitIntoBaskets.py ├── GasStation.py ├── GlobalAndLocalInversions.py ├── GroupAnagrams.py ├── IncreasingTripletSubsequence.py ├── InsertInterval.py ├── IntersectionOfTwoArrays.py ├── IntersectionOfTwoArraysII.py ├── IntersectionOfTwoLinkedLists.py ├── JumpGame.py ├── JumpGameII.py ├── KthLargestElementInAnArray.js ├── KthLargestElementInAnArray.py ├── LargestNumber.py ├── LinkedListCycle.js ├── LinkedListCycle.py ├── LongestConsecutiveSequence.py ├── MaxAreaOfIsland.py ├── MaximizeDistanceToClosestPerson.py ├── MaximumProductSubarray.py ├── MaximumSubarray.py ├── MaximumSumCircularSubarray.py ├── MedianOfTwoSorted.py ├── MergeArray.py ├── MergeSortedArray.py ├── MergerTwoSortedList.py ├── MinimumFallingPathSum.py ├── MinimumIndexSumOfTwoLists.py ├── MinimumPathSum.py ├── MissingNumber.py ├── NumberOfIslands.py ├── OddEvenLinkedList.py ├── PartitionArrayIntoDisjointIntervals.py ├── PartitionList.py ├── Pascal's TriangleI_II.py ├── PlusOne.py ├── ProductOfArrayExceptSelf.py ├── RemoveDuplicatesFromSortedArray.py ├── RemoveDuplicatesFromSortedArrayII.py ├── RemoveDuplicatesFromSortedList.py ├── RemoveDuplicatesFromSortedListII.py ├── RemoveLinkedListElements.py ├── RemoveNthNodeFromEndOfList.py ├── ReverseLinkedList.js ├── ReverseNodesInk-Group.js ├── RotateList.py ├── Search2DMatrix.py ├── Search2DMatrixII.py ├── SearchInRotatedSortedArray.py ├── SearchInRotatedSortedArrayII.py ├── SetMatrixZeroes.py ├── ShuffleAnArray.py ├── SingleNumber.py ├── SlidingWindowMaximum.py ├── SortArrayByParity.py ├── SortArrayByParityII.py ├── SortColors.py ├── SpiralMatrix.py ├── SpiralMatrixII.py ├── SubarraySumEqualsK.py ├── SumOfSubarrayMinimums.py ├── SurfaceAreaOf3DShapes.py ├── SurroundedRegions.py ├── ThirdMaximumNumbers.py ├── ThreeSum.py ├── TopKFrequentElements.py ├── Triangle.py ├── TwoSumIIAlreadySorted.py ├── WordSubsets.py ├── max_increase_to_keep_city_skyline.py ├── twoSum.js └── two_sum.py ├── BFS ├── BinaryTreeLevelOrderTraversal.py ├── BinaryTreeLevelOrderTraversalII.py ├── BinaryTreeZigzagLevelOrderTraversal.py ├── FindBottomLeftTreeValue.py ├── MaximumDepthOfBinaryTree.py └── WordLadder.py ├── Backtracking ├── GenerateParentheses.py └── subsets.py ├── DFS ├── PathSum.py ├── WordSearch.py └── WordSearchII.py ├── DP ├── BitwiseORsOfSubarray.py ├── ClimbingStairs.js ├── ClimbingStairs.py ├── CoinChange.py ├── CombinationSum.js ├── DecodeWays.py ├── FindAllAnagramsInAString.py ├── FlipStringToMonotoneIncreasing.py ├── HouseRobber.py ├── HouseRobberII.py ├── InterleavingString.py ├── LongestContinuousIncreasingSubsequence.py ├── MaxASubarrayLessThanMinBSubarray.py ├── MaximumLengthOfPairChain.py ├── MinCostClimbingStairs.js ├── NumberofLongestIncreasingSubsequence.py ├── PickCards.py ├── ReversePairs.py ├── SubarrayProductLessThanK.py ├── UniquePath.py ├── UniquePathII.py ├── WordBreak.py └── longesSubsequence.py ├── Design ├── InsertDeleteGetRandomO(1).py ├── LRUCache.py └── RLEIterator.py ├── Heap ├── FindMedianFromDataStream.py ├── KthSmallestElementInASortedMatrix.py ├── MergeKSortedLists.js └── MergeKSortedLists.py ├── Number ├── DivideTwoIntegers.py └── Sqrt(x).py ├── README.md ├── Sorted ├── SortList.py ├── WiggleSortII.py └── sotred.py ├── Stack ├── GetMinStack.py ├── ImplementQueueUsingStack.py ├── ReverseAStackByRecursive.py └── TrappingRainWater.py ├── String ├── DetectCapital.py ├── FindAndReplacePattern.py ├── FirstUniqueCharacterInAString.py ├── HammingDistance.py ├── ImplementStrStr().py ├── IsomorphicStrings.py ├── JewelsAndStones.py ├── LengthOfLastWord.py ├── LetterCombinationsOfAPhoneNumber.py ├── LongPressedName.py ├── LongesSubstrings.py ├── LongestCommonPrefix.py ├── LongestPalindromicSubstrings.py ├── MinimumAddToMakeParenthesesValid.py ├── MinimumWindowSubstring.py ├── NumberOfSegmentsInString.py ├── PermutationInString.py ├── ReplaceWords.py ├── ReverseInteger.py ├── ReverseString.py ├── ShiftingLetters.py ├── SimplifyPath.py ├── SortCharactersByFrequency.py ├── StringToInteger.py ├── ToLowerCase.py ├── UniqueEmailAddresses.py ├── ValidAnagram.py ├── ValidNumber.py ├── ValidPalindrome.py ├── ValidParentheses.py └── WordPattern.py └── Tree ├── BinarySearchTree.py ├── BinaryTreeMaximumPathSum.py ├── BinaryTreeRightSideView.py ├── CompleteBinaryTreeInserter.py ├── ConstructBinaryTreeFromInorderAndPostorderTraversal.py ├── ConstructBinaryTreeFromPreorderAndInorderTraversal.py ├── ConstructBinaryTreeFromPreorderAndPostorderTraversal.py ├── ConvertSortedArrayToBinarySearchTree.py ├── ConvertSortedListToBinarySearchTree.py ├── KthSmallestElementInABST.py ├── LowestCommonAncestorOfABinarySearchTree.py ├── LowestCommonAncestorOfABinaryTree.py ├── PathSumII.py ├── PopulatingNextRightPointersInEachNode.py ├── PopulatingNextRightPointersInEachNodeII.py ├── SerializeAndDeserializeBinaryTree.py ├── SumRootToLeafNumbers.py ├── SymmetricTree.py ├── Trie.py ├── ValidateBinarySearchTree.py └── serializeAndDeserialize.py /0_icons/book.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HuberTRoy/leetCode/e19c670fe09035a55692e2b3d2dd993db3be4725/0_icons/book.png -------------------------------------------------------------------------------- /Array/AddTwoNumbers.py: -------------------------------------------------------------------------------- 1 | """ 2 | You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. 3 | 4 | You may assume the two numbers do not contain any leading zero, except the number 0 itself. 5 | 6 | Example: 7 | 8 | Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) 9 | Output: 7 -> 0 -> 8 10 | Explanation: 342 + 465 = 807. 11 | 12 | 13 | 给两个非空的链表,每个节点包含一个整数。数字是以倒序排列的,现在输出两个链表相加得出的新链表。 14 | 15 | 长度问题: 16 | 1. 同长度不需要考虑。 17 | 2. 不同长度下,正序意味着 18 | 3421 + 465 = 3421 19 | 465 20 | 这种情况最好的方法应该是从后向前,但此题目中给出的就是从后向前,所以也不必考虑这个, 21 | 直接给0即可。 22 | 23 | 思路: 24 | 头到尾,对于每一个位来说,最大是 9+9,进位最大是1. 25 | 26 | Ok,一遍过,O(n)。 27 | beat 67%. 28 | 29 | 30 | """ 31 | 32 | 33 | # Definition for singly-linked list. 34 | # class ListNode(object): 35 | # def __init__(self, x): 36 | # self.val = x 37 | # self.next = None 38 | 39 | class Solution(object): 40 | def addTwoNumbers(self, l1, l2): 41 | """ 42 | :type l1: ListNode 43 | :type l2: ListNode 44 | :rtype: ListNode 45 | """ 46 | 47 | get_value = self.getRest(l1, l2) 48 | root = ListNode(get_value[0]) 49 | rest_value = get_value[1] 50 | l1 = l1.next 51 | l2 = l2.next 52 | 53 | backup_root = root 54 | 55 | while l1 is not None or l2 is not None: 56 | 57 | get_value = self.getRest(l1, l2, rest_value) 58 | 59 | new_node = ListNode(get_value[0]) 60 | rest_value = get_value[1] 61 | 62 | root.next = new_node 63 | root = new_node 64 | 65 | l1 = l1.next if l1 else None 66 | l2 = l2.next if l2 else None 67 | 68 | if rest_value: 69 | root.next = ListNode(rest_value) 70 | 71 | return backup_root 72 | 73 | def getRest(self, l1, l2, rest=0): 74 | # return (val, rest) 75 | # 9+8 (7, 1) 76 | l1_val = l1.val if l1 else 0 77 | l2_val = l2.val if l2 else 0 78 | 79 | return ((l1_val + l2_val + rest) % 10, (l1_val + l2_val + rest) // 10) 80 | -------------------------------------------------------------------------------- /Array/BinarySubarraysWithSum.py: -------------------------------------------------------------------------------- 1 | """ 2 | In an array A of 0s and 1s, how many non-empty subarrays have sum S? 3 | 4 | 5 | 6 | Example 1: 7 | 8 | Input: A = [1,0,1,0,1], S = 2 9 | Output: 4 10 | Explanation: 11 | The 4 subarrays are bolded below: 12 | [1,0,1,0,1] 13 | [1,0,1,0,1] 14 | [1,0,1,0,1] 15 | [1,0,1,0,1] 16 | 17 | 18 | Note: 19 | 20 | A.length <= 30000 21 | 0 <= S <= A.length 22 | A[i] is either 0 or 1. 23 | 24 | pre result + hash 有一个思路一模一样,代码也一模一样的。 25 | 26 | 测试地址: 27 | https://leetcode.com/contest/weekly-contest-108/problems/binary-subarrays-with-sum/ 28 | 29 | """ 30 | class Solution(object): 31 | def numSubarraysWithSum(self, A, S): 32 | """ 33 | :type A: List[int] 34 | :type S: int 35 | :rtype: int 36 | """ 37 | 38 | dicts = {0:1} 39 | 40 | pre = 0 41 | result = 0 42 | 43 | for i in A: 44 | pre += i 45 | 46 | result += dicts.get(pre-S, 0) 47 | dicts[pre] = dicts.get(pre, 0) + 1 48 | 49 | return result 50 | -------------------------------------------------------------------------------- /Array/CountOfSmallerNumbersAfterSelf.py: -------------------------------------------------------------------------------- 1 | """ 2 | You are given an integer array nums and you have to return a new counts array. The counts array has the property where counts[i] is the number of smaller elements to the right of nums[i]. 3 | 4 | Example: 5 | 6 | Input: [5,2,6,1] 7 | Output: [2,1,1,0] 8 | Explanation: 9 | To the right of 5 there are 2 smaller elements (2 and 1). 10 | To the right of 2 there is only 1 smaller element (1). 11 | To the right of 6 there is 1 smaller element (1). 12 | To the right of 1 there is 0 smaller element. 13 | 14 | 思路: 15 | 二分。 16 | 17 | 瓶颈依然在于插入列表中的时候需要的时间复杂度为 O(n)。 18 | 19 | beat 20 | 82% 21 | 22 | 测试地址: 23 | https://leetcode.com/problems/count-of-smaller-numbers-after-self/description/ 24 | 25 | """ 26 | import bisect 27 | 28 | class Solution(object): 29 | def countSmaller(self, nums): 30 | """ 31 | :type nums: List[int] 32 | :rtype: List[int] 33 | """ 34 | 35 | x = [] 36 | result = [] 37 | 38 | for i in nums[::-1]: 39 | result.append(bisect.bisect_left(x, i)) 40 | bisect.insort(x,i) 41 | 42 | return result[::-1] -------------------------------------------------------------------------------- /Array/FairCandySwap.py: -------------------------------------------------------------------------------- 1 | """ 2 | Alice and Bob have candy bars of different sizes: A[i] is the size of the i-th bar of candy that Alice has, and B[j] is the size of the j-th bar of candy that Bob has. 3 | 4 | Since they are friends, they would like to exchange one candy bar each so that after the exchange, they both have the same total amount of candy. (The total amount of candy a person has is the sum of the sizes of candy bars they have.) 5 | 6 | Return an integer array ans where ans[0] is the size of the candy bar that Alice must exchange, and ans[1] is the size of the candy bar that Bob must exchange. 7 | 8 | If there are multiple answers, you may return any one of them. It is guaranteed an answer exists. 9 | 10 | 11 | 12 | Example 1: 13 | 14 | Input: A = [1,1], B = [2,2] 15 | Output: [1,2] 16 | Example 2: 17 | 18 | Input: A = [1,2], B = [2,3] 19 | Output: [1,2] 20 | Example 3: 21 | 22 | Input: A = [2], B = [1,3] 23 | Output: [2,3] 24 | Example 4: 25 | 26 | Input: A = [1,2,5], B = [2,4] 27 | Output: [5,4] 28 | 29 | 30 | Note: 31 | 32 | 1 <= A.length <= 10000 33 | 1 <= B.length <= 10000 34 | 1 <= A[i] <= 100000 35 | 1 <= B[i] <= 100000 36 | It is guaranteed that Alice and Bob have different total amounts of candy. 37 | It is guaranteed there exists an answer. 38 | 39 | 40 | 开胃菜。 41 | 42 | 有两个好盆友,要交换糖果使得他们两个的糖果一样。 43 | 44 | 输出的结果也是交换的糖果数量而不是下标,所以非常容易写。 45 | 46 | 设爱丽丝给 x 颗糖,得到 y颗。那鲍勃就给 y 得到 x。 47 | 48 | 最终是 49 | 1? - x + y = 2? - y + x 50 | 2x - 2y = 1? - 2? 51 | 52 | x - y = (1? - 2?) / 2 53 | 54 | 55 | 1?即 爱丽丝的初始糖, 56 | 2?即 鲍勃的初始糖。 57 | 58 | 那么首先把 爱丽丝和鲍勃的糖加起来 / 2,然后迭代 爱丽丝的糖,若迭代的这个糖 - 前面计算出来的糖鲍勃有的话返回即可。 59 | 60 | 要写的话首先把鲍勃的糖哈希一下,这样查找的时间复杂度为 O(1)。 61 | 62 | 测试地址: 63 | https://leetcode.com/contest/weekly-contest-98/problems/fair-candy-swap/ 64 | 65 | beat: 66 | 100% 44 ms 67 | 68 | 69 | """ 70 | 71 | class Solution(object): 72 | def fairCandySwap(self, A, B): 73 | """ 74 | :type A: List[int] 75 | :type B: List[int] 76 | :rtype: List[int] 77 | """ 78 | x = (sum(A) - sum(B)) // 2 79 | b = set(B) 80 | for i in A: 81 | if i - x in b: 82 | return (i, i-x) 83 | -------------------------------------------------------------------------------- /Array/FindMinimumInRotatedSortedArray.py: -------------------------------------------------------------------------------- 1 | """ 2 | Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. 3 | 4 | (i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]). 5 | 6 | Find the minimum element. 7 | 8 | You may assume no duplicate exists in the array. 9 | 10 | Example 1: 11 | 12 | Input: [3,4,5,1,2] 13 | Output: 1 14 | Example 2: 15 | 16 | Input: [4,5,6,7,0,1,2] 17 | Output: 0 18 | 19 | 找旋转过的排序数组中最小的数。 20 | 21 | 有旋转则旋转点最小,无则 0 最小。 22 | 23 | beat: 100% 20ms 24 | 48% 24ms 25 | 26 | 测试地址: 27 | https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/description/ 28 | 29 | """ 30 | class Solution(object): 31 | def find_rotate(self, nums): 32 | target = nums[0] 33 | 34 | lo = 1 35 | 36 | hi = len(nums) 37 | 38 | while lo < hi: 39 | mid = (lo + hi) // 2 40 | if nums[mid] > target: 41 | lo = mid + 1 42 | else: 43 | hi = mid 44 | 45 | return lo 46 | 47 | def findMin(self, nums): 48 | """ 49 | :type nums: List[int] 50 | :rtype: int 51 | """ 52 | 53 | rotate = self.find_rotate(nums) 54 | 55 | if rotate == len(nums): 56 | return nums[0] 57 | 58 | return nums[rotate] 59 | -------------------------------------------------------------------------------- /Array/FindMinimumInRotatedSortedArrayII.py: -------------------------------------------------------------------------------- 1 | """ 2 | Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. 3 | 4 | (i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]). 5 | 6 | Find the minimum element. 7 | 8 | The array may contain duplicates. 9 | 10 | Example 1: 11 | 12 | Input: [1,3,5] 13 | Output: 1 14 | Example 2: 15 | 16 | Input: [2,2,2,0,1] 17 | Output: 0 18 | Note: 19 | 20 | This is a follow up problem to Find Minimum in Rotated Sorted Array. 21 | Would allow duplicates affect the run-time complexity? How and why? 22 | 23 | 与Search in Rotated Sorted Array II 中讨论的一样,主要就是重复的数。用同样的方法即可。 24 | 25 | 解释请看 SearchInRotatedSortedArrayII.py. 26 | 27 | beat 100% 20ms~24ms都有可能。 28 | 29 | 测试地址: 30 | https://leetcode.com/problems/find-minimum-in-rotated-sorted-array-ii/description/ 31 | 32 | """ 33 | class Solution(object): 34 | def find_rotate(self, nums): 35 | target = nums[0] 36 | 37 | lo = 1 38 | 39 | for i in range(1, len(nums)): 40 | if nums[i] == target: 41 | lo += 1 42 | else: 43 | break 44 | 45 | hi = len(nums) 46 | 47 | while lo < hi: 48 | mid = (lo + hi) // 2 49 | if nums[mid] > target: 50 | lo = mid + 1 51 | else: 52 | hi = mid 53 | 54 | return lo 55 | 56 | def findMin(self, nums): 57 | """ 58 | :type nums: List[int] 59 | :rtype: int 60 | """ 61 | 62 | rotate = self.find_rotate(nums) 63 | 64 | if rotate == len(nums): 65 | return nums[0] 66 | 67 | return nums[rotate] 68 | -------------------------------------------------------------------------------- /Array/FindPeakElement.py: -------------------------------------------------------------------------------- 1 | """ 2 | A peak element is an element that is greater than its neighbors. 3 | 4 | Given an input array nums, where nums[i] ≠ nums[i+1], find a peak element and return its index. 5 | 6 | The array may contain multiple peaks, in that case return the index to any one of the peaks is fine. 7 | 8 | You may imagine that nums[-1] = nums[n] = -∞. 9 | 10 | Example 1: 11 | 12 | Input: nums = [1,2,3,1] 13 | Output: 2 14 | Explanation: 3 is a peak element and your function should return the index number 2. 15 | Example 2: 16 | 17 | Input: nums = [1,2,1,3,5,6,4] 18 | Output: 1 or 5 19 | Explanation: Your function can return either index number 1 where the peak element is 2, 20 | or index number 5 where the peak element is 6. 21 | Note: 22 | 23 | Your solution should be in logarithmic complexity. 24 | 25 | log n待续。 26 | 27 | 先O(n)。 28 | 29 | 看来测试数据不多,O(n) 的可以 beat 100%. 30 | 31 | 测试地址: 32 | https://leetcode.com/problems/find-peak-element/description/ 33 | 34 | """ 35 | class Solution(object): 36 | def findPeakElement(self, nums): 37 | """ 38 | :type nums: List[int] 39 | :rtype: int 40 | """ 41 | 42 | length = len(nums) 43 | 44 | for i in range(1, length-1): 45 | if nums[i-1] < nums[i] > nums[i+1]: 46 | return i 47 | 48 | if length <= 2: 49 | return nums.index(max(nums)) 50 | else: 51 | if nums[0] > nums[1]: 52 | return 0 53 | elif nums[-1] > nums[-2]: 54 | return length-1 55 | return None 56 | -------------------------------------------------------------------------------- /Array/FizzBuzz.py: -------------------------------------------------------------------------------- 1 | """ 2 | Write a program that outputs the string representation of numbers from 1 to n. 3 | 4 | But for multiples of three it should output “Fizz” instead of the number and for the multiples of five output “Buzz”. For numbers which are multiples of both three and five output “FizzBuzz”. 5 | 6 | Example: 7 | 8 | n = 15, 9 | 10 | Return: 11 | [ 12 | "1", 13 | "2", 14 | "Fizz", 15 | "4", 16 | "Buzz", 17 | "Fizz", 18 | "7", 19 | "8", 20 | "Fizz", 21 | "Buzz", 22 | "11", 23 | "Fizz", 24 | "13", 25 | "14", 26 | "FizzBuzz" 27 | ] 28 | 29 | 1 - n 30 | 3的倍数加 Fizz 31 | 5的倍数加 Buzz 32 | 3和5的倍数加 FizzBuzz 33 | 34 | 比较简单,今日的零启动。 35 | 36 | 用取模%也可以,一开始觉得取模可能效率不高就没用。 37 | 38 | 不过看结果是一样的: 39 | 40 | beat 94% 41 | 测试链接: 42 | https://leetcode.com/problems/fizz-buzz/description/ 43 | 44 | """ 45 | class Solution(object): 46 | def fizzBuzz(self, n): 47 | """ 48 | :type n: int 49 | :rtype: List[str] 50 | """ 51 | 52 | result = [] 53 | fizz_time = 0 54 | buzz_time = 0 55 | fizzbuzz_time = 0 56 | 57 | 58 | for i in range(1, n+1): 59 | fizz_time += 1 60 | buzz_time += 1 61 | fizzbuzz_time += 1 62 | 63 | if fizzbuzz_time == 15: 64 | result.append("FizzBuzz") 65 | fizzbuzz_time = 0 66 | fizz_time = 0 67 | buzz_time = 0 68 | continue 69 | 70 | if fizz_time == 3: 71 | fizz_time = 0 72 | result.append("Fizz") 73 | continue 74 | 75 | if buzz_time == 5: 76 | buzz_time = 0 77 | result.append("Buzz") 78 | continue 79 | 80 | result.append(str(i)) 81 | return result 82 | -------------------------------------------------------------------------------- /Array/FootballFans.py: -------------------------------------------------------------------------------- 1 | """ 2 | 好像是今日头条2018 秋招算法题? 3 | 4 | 球场C 可容纳 M*N个球迷。统计有几组球迷群体: 5 | 6 | 1. 每组球迷群体会选择相邻的作为(8个方位。) 7 | 2. 不同球迷群体不会相邻。 8 | 3. 给一个 M*N 的二维球场,0为没人,1为有人,求出群体个数P以及最大的群体人数Q. 9 | 10 | OK, bug free. 11 | 12 | 类似算法的 leetcode: 13 | https://leetcode.com/problems/number-of-islands/description/ 解答请看 NumberOfIslands.py 14 | https://leetcode.com/problems/max-area-of-island/description/ 解答请看 MaxAreaOfIsland.py 15 | 16 | """ 17 | 18 | test = [ 19 | [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 20 | [0, 0, 0, 1, 1, 0, 1, 0, 0, 0], 21 | [0, 1, 0, 0, 0, 0, 0, 1, 0, 1], 22 | [1, 0, 0, 0, 0, 0, 0, 0, 1, 1], 23 | [0, 0, 0, 1, 1, 1, 0, 0, 0, 1], 24 | [0, 0, 0, 0, 0, 0, 1, 0, 1, 1], 25 | [0, 1, 1, 0, 0, 0, 0, 0, 0, 0], 26 | [0, 0, 0, 1, 0, 1, 0, 0, 0, 0], 27 | [0, 0, 1, 0, 0, 1, 0, 0, 0, 0], 28 | [0, 1, 0, 0, 0, 0, 0, 0, 0, 0], 29 | ] 30 | 31 | # 6 8 32 | 33 | def makeAroundXY(x, y): 34 | # ((x, y)....) 35 | return ((x, y-1), 36 | (x, y+1), 37 | (x-1, y), 38 | (x+1, y), 39 | (x-1, y-1), 40 | (x-1, y+1), 41 | (x+1, y+1), 42 | (x+1, y-1)) 43 | 44 | def getFootballFans(court): 45 | """ 46 | [[0, 0, 0].....] 47 | 从 0,0 开始,如果遇到1则进入递归: 48 | 递归结束条件: 49 | 四周都是 0或边界。 50 | 结束时将搜索到的人数添加。 51 | 未结束时根据四周的情况进入相同的递归。 52 | """ 53 | 54 | fans_groups = [] 55 | x = 0 56 | y = 0 57 | 58 | x_length = len(court[0]) 59 | y_length = len(court) 60 | 61 | def helper(x, y, result=0): 62 | nonlocal court 63 | Xy = makeAroundXY(x, y) 64 | for i in Xy: 65 | try: 66 | if i[0] < 0 or i[1] < 0: 67 | continue 68 | 69 | if court[i[1]][i[0]] == 1: 70 | court[i[1]][i[0]] = 0 71 | result += 1 72 | t = helper(i[0], i[1], 0) 73 | result += t 74 | except IndexError: 75 | continue 76 | else: 77 | return result 78 | 79 | 80 | for y in range(y_length): 81 | for x in range(x_length): 82 | if court[y][x] == 1: 83 | court[y][x] = 0 84 | fans_groups.append(helper(x, y, 1)) 85 | 86 | 87 | 88 | if not fans_groups: 89 | return (0, 0) 90 | 91 | return (len(fans_groups, max(fans_groups))) 92 | 93 | getFootballFans(test) -------------------------------------------------------------------------------- /Array/GlobalAndLocalInversions.py: -------------------------------------------------------------------------------- 1 | """ 2 | We have some permutation A of [0, 1, ..., N - 1], where N is the length of A. 3 | 4 | The number of (global) inversions is the number of i < j with 0 <= i < j < N and A[i] > A[j]. 5 | 6 | The number of local inversions is the number of i with 0 <= i < N and A[i] > A[i+1]. 7 | 8 | Return true if and only if the number of global inversions is equal to the number of local inversions. 9 | 10 | Example 1: 11 | 12 | Input: A = [1,0,2] 13 | Output: true 14 | Explanation: There is 1 global inversion, and 1 local inversion. 15 | Example 2: 16 | 17 | Input: A = [1,2,0] 18 | Output: false 19 | Explanation: There are 2 global inversions, and 1 local inversion. 20 | Note: 21 | 22 | A will be a permutation of [0, 1, ..., A.length - 1]. 23 | A will have length in range [1, 5000]. 24 | The time limit for this problem has been reduced. 25 | 26 | 思路: 27 | 二分法。 28 | 29 | 测试地址: 30 | https://leetcode.com/contest/weekly-contest-69/problems/global-and-local-inversions/ 31 | 32 | """ 33 | import bisect 34 | 35 | class Solution(object): 36 | def isIdealPermutation(self, A): 37 | """ 38 | :type A: List[int] 39 | :rtype: bool 40 | """ 41 | global_inversions = [] 42 | _g = 0 43 | 44 | for i in A[::-1]: 45 | _g += bisect.bisect_left(global_inversions, i) 46 | bisect.insort_left(global_inversions, i) 47 | 48 | _l = 0 49 | 50 | for i in range(len(A)-1): 51 | if A[i] > A[i+1]: 52 | _l += 1 53 | 54 | return _g == _l 55 | -------------------------------------------------------------------------------- /Array/GroupAnagrams.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given an array of strings, group anagrams together. 3 | 4 | Example: 5 | 6 | Input: ["eat", "tea", "tan", "ate", "nat", "bat"], 7 | Output: 8 | [ 9 | ["ate","eat","tea"], 10 | ["nat","tan"], 11 | ["bat"] 12 | ] 13 | Note: 14 | 15 | All inputs will be in lowercase. 16 | The order of your output does not matter. 17 | 18 | 给一组带有字符串的数组,进行变位词分类。 19 | 20 | 思路是排序的思路,排序后为同一个的放到一起。 21 | 22 | 效率就测试来看尚可。 23 | 24 | beat 70% 25 | 26 | 测试地址: 27 | https://leetcode.com/problems/group-anagrams/description/ 28 | 29 | """ 30 | class Solution(object): 31 | def groupAnagrams(self, strs): 32 | """ 33 | :type strs: List[str] 34 | :rtype: List[List[str]] 35 | """ 36 | result = {} 37 | 38 | for i in strs: 39 | key = ''.join(sorted(i)) 40 | 41 | try: 42 | result[key].append(i) 43 | except: 44 | result[key] = [i] 45 | 46 | return result.values() 47 | -------------------------------------------------------------------------------- /Array/IncreasingTripletSubsequence.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given an unsorted array return whether an increasing subsequence of length 3 exists or not in the array. 3 | 4 | Formally the function should: 5 | 6 | Return true if there exists i, j, k 7 | such that arr[i] < arr[j] < arr[k] given 0 ≤ i < j < k ≤ n-1 else return false. 8 | Note: Your algorithm should run in O(n) time complexity and O(1) space complexity. 9 | 10 | Example 1: 11 | 12 | Input: [1,2,3,4,5] 13 | Output: true 14 | Example 2: 15 | 16 | Input: [5,4,3,2,1] 17 | Output: false 18 | 19 | 给一个数组,若里面存在 arr[i] < arr[j] < arr[k] 且 0 <= i < j < k <= n-1,则返回True。 20 | 否则False. 21 | 22 | 要求 O(n)时间以及O(1) 空间。 23 | 24 | 25 | 对于 i 的规则是尽量小。首先确定为第一个,之后若出现比它小的,则确定为这个否则确定为 j。 26 | 对于 j 的规则依然是尽量小,但要大于i。 27 | 28 | 思考时有可能出现的陷阱: 29 | 30 | 1. 有比 i 小的就替换,那要是 arr[100] < i,那前面的99个确定没有符合条件的吗? 31 | 还要基于 j,i的判断条件是,若比 i 小则替换为 i,若比 i 大则与 j 比较,与 j 比较遵循同样的规则。 32 | 33 | 2. 有无可能出现在 j 之前有 3 个小于 j 的递增序列呢? 34 | 不可能: 35 | 一个数在 j 之前有两种状态: 36 | 比 j 大或与 j 相等。 37 | 若比 j 小则替换为 j 了。 38 | 在 j 之后也不可能,若这个数比 j 小则会替换为 j。 39 | 40 | 3. 那么有没有可能出现第一个 j 与第二个 j 之间存在 3 个这样的递增序列呢? 41 | 也是不可能的: 42 | 若比 j 大则直接返回了。 43 | 若比 j 小或等则替换。 44 | 45 | 所以按此规则: 46 | 1. i 之前不可能存在 3 个递增序列。 47 | 2. i - j 这段也不可能存在 3 个递增序列。 48 | 3. j - k 这段也不可能存在 3 个递增序列。 49 | 50 | o(n) o(1) 51 | 只有 4 个变量。 52 | 53 | beat 100% 54 | 55 | 测试地址: 56 | https://leetcode.com/problems/increasing-triplet-subsequence/description/ 57 | 58 | """ 59 | class Solution(object): 60 | def increasingTriplet(self, nums): 61 | """ 62 | :type nums: List[int] 63 | :rtype: bool 64 | """ 65 | 66 | if len(nums) < 3: 67 | return False 68 | 69 | one = None 70 | two = None 71 | for i, d in enumerate(nums): 72 | if one: 73 | if d <= one[1]: 74 | one = (i, d) 75 | continue 76 | 77 | if two: 78 | if d <= two[1]: 79 | two = (i, d) 80 | else: 81 | return True 82 | else: 83 | two = (i, d) 84 | else: 85 | one = (i, d) 86 | return False 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /Array/InsertInterval.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary). 3 | 4 | You may assume that the intervals were initially sorted according to their start times. 5 | 6 | Example 1: 7 | 8 | Input: intervals = [[1,3],[6,9]], newInterval = [2,5] 9 | Output: [[1,5],[6,9]] 10 | Example 2: 11 | 12 | Input: intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8] 13 | Output: [[1,2],[3,10],[12,16]] 14 | Explanation: Because the new interval [4,8] overlaps with [3,5],[6,7],[8,10]. 15 | 16 | 17 | 与 Merge Array 思路上是一样的,本以为用同样的代码会导致 TLE,不过也 Pass 了,beat 74%. 18 | 19 | C扩展的排序就是快,不用排序的思路: 20 | 这个只会部分重叠,所以目标是找到head和end的点: 21 | [[1,2],[3,5],[6,7],[8,10],[12,16]] [4, 8] 22 | head 找最后一个大于的。 23 | end 则找第一个小于的。 24 | 比如 4 对比 1, 3,6后,那么确定 head 为 3. [3, 5] 25 | 8 对比 2, 5, 7 后找到 10。 [8, 10] 26 | 27 | 测试地址: 28 | https://leetcode.com/problems/insert-interval/description/ 29 | 30 | """ 31 | # Definition for an interval. 32 | # class Interval(object): 33 | # def __init__(self, s=0, e=0): 34 | # self.start = s 35 | # self.end = e 36 | 37 | class Solution(object): 38 | def insert(self, _sentences, newInterval): 39 | """ 40 | :type intervals: List[Interval] 41 | :type newInterval: Interval 42 | :rtype: List[Interval] 43 | """ 44 | _sentences.append(newInterval) 45 | 46 | _sentences = sorted(_sentences, key=lambda x: x.start) 47 | 48 | if not _sentences: 49 | return [] 50 | 51 | result = [] 52 | 53 | head = _sentences[0].start 54 | tail = _sentences[0].end 55 | length = len(_sentences) 56 | for x in range(1, length): 57 | i = _sentences[x] 58 | if tail >= i.start: 59 | tail = max(tail, i.end) 60 | else: 61 | result.append([head, tail]) 62 | head = i.start 63 | tail = i.end 64 | 65 | result.append([head, tail]) 66 | return result 67 | 68 | -------------------------------------------------------------------------------- /Array/IntersectionOfTwoArrays.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given two arrays, write a function to compute their intersection. 3 | 4 | Example 1: 5 | 6 | Input: nums1 = [1,2,2,1], nums2 = [2,2] 7 | Output: [2] 8 | Example 2: 9 | 10 | Input: nums1 = [4,9,5], nums2 = [9,4,9,8,4] 11 | Output: [9,4] 12 | Note: 13 | 14 | Each element in the result must be unique. 15 | The result can be in any order. 16 | 17 | 18 | 找两个数组里的重复数据。 19 | 20 | 唯一,任意顺序。 21 | 22 | 集合,取交集即可。 23 | 24 | 零启动。 25 | 26 | beat 100% 20ms. 27 | 28 | 测试地址: 29 | https://leetcode.com/problems/intersection-of-two-arrays/description/ 30 | 31 | """ 32 | class Solution(object): 33 | def intersection(self, nums1, nums2): 34 | """ 35 | :type nums1: List[int] 36 | :type nums2: List[int] 37 | :rtype: List[int] 38 | """ 39 | 40 | return list(set(nums1) & set(nums2)) 41 | -------------------------------------------------------------------------------- /Array/IntersectionOfTwoArraysII.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given two arrays, write a function to compute their intersection. 3 | 4 | Example 1: 5 | 6 | Input: nums1 = [1,2,2,1], nums2 = [2,2] 7 | Output: [2,2] 8 | Example 2: 9 | 10 | Input: nums1 = [4,9,5], nums2 = [9,4,9,8,4] 11 | Output: [4,9] 12 | Note: 13 | 14 | Each element in the result should appear as many times as it shows in both arrays. 15 | The result can be in any order. 16 | Follow up: 17 | 18 | What if the given array is already sorted? How would you optimize your algorithm? 19 | What if nums1's size is small compared to nums2's size? Which algorithm is better? 20 | What if elements of nums2 are stored on disk, and the memory is limited such that you cannot load all elements into the memory at once? 21 | 22 | 与 1 差不多,不过这次有重复。 23 | 进阶条件里问: 24 | 1. 如果是已排序的可以怎么优化? 25 | 2. 如果 数组1 比 数组2 要小,哪个算法好些? 26 | 3. 如果 数组2 在硬盘里排过序,但内存不足以一次性全部读取该怎么做? 27 | 28 | 我的思路是: 29 | 1. 先排序。 30 | 2. 之后设置两个指针。 31 | 32 | 若 1与2相同,则将结果添加到最终结果的列表中,1和2各+1。 33 | 若 1比2要大,那么表示2向后走还有可能遇到和1相同的数字,所以2 +1。 34 | 否则 1 +1。直到有一个到了末尾。 35 | 36 | 这个思路的话,进阶的1和3直接可以包含进去。 37 | 2的话,Discuss 里的其他方法基本上是用 哈希表。 1和2哈希,然后取个数较小的交集,这种方法在数组较小的时候要比上面提到的思路快。 38 | 39 | 排序后的思路: 40 | 41 | beat 100% 24ms. 42 | 43 | 测试地址: 44 | https://leetcode.com/problems/intersection-of-two-arrays-ii/description/ 45 | 46 | 47 | """ 48 | class Solution(object): 49 | def intersect(self, nums1, nums2): 50 | """ 51 | :type nums1: List[int] 52 | :type nums2: List[int] 53 | :rtype: List[int] 54 | """ 55 | result = [] 56 | 57 | 58 | nums1.sort() 59 | nums2.sort() 60 | 61 | _n1 = 0 62 | _n2 = 0 63 | 64 | _n1_length = len(nums1) 65 | _n2_length = len(nums2) 66 | 67 | while _n1 < _n1_length and _n2 < _n2_length: 68 | if nums1[_n1] == nums2[_n2]: 69 | result.append(nums1[_n1]) 70 | _n1 += 1 71 | _n2 += 1 72 | 73 | elif nums1[_n1] < nums2[_n2]: 74 | _n1 += 1 75 | else: 76 | _n2 += 1 77 | 78 | return result -------------------------------------------------------------------------------- /Array/IntersectionOfTwoLinkedLists.py: -------------------------------------------------------------------------------- 1 | """ 2 | Write a program to find the node at which the intersection of two singly linked lists begins. 3 | 4 | 5 | For example, the following two linked lists: 6 | 7 | A: a1 → a2 8 | ↘ 9 | c1 → c2 → c3 10 | ↗ 11 | B: b1 → b2 → b3 12 | begin to intersect at node c1. 13 | 14 | 15 | Notes: 16 | 17 | If the two linked lists have no intersection at all, return null. 18 | The linked lists must retain their original structure after the function returns. 19 | You may assume there are no cycles anywhere in the entire linked structure. 20 | Your code should preferably run in O(n) time and use only O(1) memory. 21 | 22 | 给定两个链表,判断是否有交叉部分。 23 | 24 | 分析: 25 | 26 | 那么,就有了以下4种情况: 27 | 1. 长度相同,有交叉部分。 28 | 2. 长度不同,有交叉部分。 29 | 3. 长度相同,无交叉部分。 30 | 4. 长度不同,无交叉部分。 31 | 32 | 1. 两个链表,若存在交叉部分则最后至交叉点一定是相同的。 33 | 那么倒序判断可以说应该是最高效的,从两个链表的尾部开始,直至找到不同部分或一方为None表示无交叉。 34 | 由给定的链表节点可知,这是一只单向链表,所以此思路已经无法在继续进行。 O(n) 35 | 36 | 2. 另一个思路是根据上面的信息,顺序进行判断, 37 | 让长链表一方先走,然后与短的一起走,直至找到相同部分或一方为None表示无交叉, 38 | 但我们也不知道长度,只能先遍历一遍找到长度。O(2(m+n)) 39 | 40 | 3. 用的 Python 可以直接利用set(),一个哈希表,来达到O(1)的查找... 41 | 所以 原本的做法是,遍历b,然后判断b中的每一个是否在a中存在,存在则返回。这种做法简单粗暴.. 42 | 但相应的复杂度是O(mn). 43 | 44 | 1. 不可行,3.有点无脑。用2.来做一下 45 | 46 | 此做法参考了 Discuss 里的高票回答: 47 | 48 | 反正是要遍历两遍,直接让两个一起走, 49 | 要么一起结束: 50 | 1. 有相同返回相同. 51 | 2. 无相同,返回None. 52 | 53 | 要么一长一短: 54 | 1. 短的肯定是先走完的,然后让短的变成长的。 55 | 2. 短的变成长的之后原本的长的因为走了一段所以变成了较短的,所以会先走完。走的这段距离就是原本我们要求的差值。 56 | 3. 原本的长的再变成短的,一起走完即可。 57 | 58 | 例: 59 | 60 | a = [1, 2, 3, 4] 61 | b = [5, 6, 7] 62 | 63 | t = 1 64 | f = 5 65 | t != f 66 | t = 2 67 | f = 6 68 | t != f 69 | t = 3 70 | f = 7 71 | t != f 72 | 此时f已经走到的尽头,f替换为a. 73 | t = 4 74 | f = a.head = 1 75 | t != f 76 | 此时t已经走到了尽头,t替换为b. 77 | t = b.head = 5 78 | f = 2 79 | 此时已经与我们预想的一致了。 80 | a = [1, 2, 3, 4] 81 | b = [5, 6, 7] 82 | 83 | """ 84 | class ListNode(object): 85 | __slots__ = ('val', 'next') 86 | def __init__(self, x): 87 | self.val = x 88 | self.next = None 89 | 90 | class Solution(object): 91 | def getIntersectionNode(self, headA, headB): 92 | """ 93 | :type head1, head1: ListNode 94 | :rtype: ListNode 95 | """ 96 | 97 | a = headA 98 | b = headB 99 | 100 | if not a or not b: 101 | return None 102 | 103 | while a != b: 104 | 105 | a = headB if a is None else a.next 106 | b = headA if b is None else b.next 107 | 108 | return a 109 | -------------------------------------------------------------------------------- /Array/JumpGame.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given an array of non-negative integers, you are initially positioned at the first index of the array. 3 | 4 | Each element in the array represents your maximum jump length at that position. 5 | 6 | Determine if you are able to reach the last index. 7 | 8 | Example 1: 9 | 10 | Input: [2,3,1,1,4] 11 | Output: true 12 | Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last index. 13 | Example 2: 14 | 15 | Input: [3,2,1,0,4] 16 | Output: false 17 | Explanation: You will always arrive at index 3 no matter what. Its maximum 18 | jump length is 0, which makes it impossible to reach the last index. 19 | 20 | 给一组数组,返回能不能到达最后的位置。每个位置包含的是从此点出发可走的最远距离,在哪里落脚随意。 21 | 22 | 思路: 23 | 24 | 从 0 开始,找到剩下的里面 下标 + 能走多远 最大的一个。然后一直重复即可。 25 | 26 | 下面的这个代码并不是一遍的 O(n) ,用此思路也可以优化成 O(n),不优化了,没什么优化难点。 27 | 关键字: 28 | current_index 变更为上次range的末尾,并相应的减去。 29 | 30 | beat 66% 31 | 32 | 测试地址: 33 | https://leetcode.com/problems/jump-game/description/ 34 | 35 | """ 36 | class Solution(object): 37 | def canJump(self, nums): 38 | """ 39 | :type nums: List[int] 40 | :rtype: bool 41 | """ 42 | 43 | 44 | dp = [nums[0]] 45 | current_index = 0 46 | 47 | while 1: 48 | if current_index + dp[-1] >= len(nums)-1: 49 | return True 50 | base = 0 51 | index = current_index 52 | for i in range(current_index, current_index+dp[-1]+1): 53 | if nums[i] + i > base: 54 | base = nums[i] + i 55 | index = i 56 | 57 | if current_index == index: 58 | return False 59 | 60 | current_index = index 61 | dp.append(base-index) -------------------------------------------------------------------------------- /Array/JumpGameII.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given an array of non-negative integers, you are initially positioned at the first index of the array. 3 | 4 | Each element in the array represents your maximum jump length at that position. 5 | 6 | Your goal is to reach the last index in the minimum number of jumps. 7 | 8 | Example: 9 | 10 | Input: [2,3,1,1,4] 11 | Output: 2 12 | Explanation: The minimum number of jumps to reach the last index is 2. 13 | Jump 1 step from index 0 to 1, then 3 steps to the last index. 14 | Note: 15 | 16 | You can assume that you can always reach the last index. 17 | 18 | 与 1 差不多,这个需要返回的是最少的可用步数。 19 | 20 | 因为 1 中直接返回的是最大的,所以可以顺便把 2 也给完成。 21 | 22 | beat 66%. 23 | 24 | 测试地址: 25 | https://leetcode.com/problems/jump-game-ii/description/ 26 | 27 | """ 28 | class Solution(object): 29 | def jump(self, nums): 30 | """ 31 | :type nums: List[int] 32 | :rtype: int 33 | """ 34 | if len(nums) == 1: 35 | return 0 36 | 37 | # dp = [nums[0]] 38 | maxes = nums[0] 39 | count = 1 40 | current_index = 0 41 | length = len(nums) - 1 42 | while 1: 43 | if current_index + maxes >= length: 44 | return count 45 | base = 0 46 | index = current_index 47 | for i in xrange(current_index, current_index+maxes+1): 48 | if nums[i] + i > base: 49 | base = nums[i] + i 50 | index = i 51 | 52 | current_index = index 53 | maxes = base-index 54 | count += 1 -------------------------------------------------------------------------------- /Array/KthLargestElementInAnArray.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @param {number} k 4 | * @return {number} 5 | */ 6 | 7 | // 写了个快排和归并。 8 | function sort(arr) { 9 | // 快排 10 | if (arr.length === 0) { 11 | return arr 12 | } 13 | 14 | // 选种 15 | let bean = Math.floor((arr.length-1) / 2) 16 | let base = arr[bean] 17 | let bigger = [] 18 | let smaller = [] 19 | 20 | for (let [index, item] of arr.entries()) { 21 | if (index === bean) { 22 | continue 23 | } 24 | 25 | if (item >= base) { 26 | bigger.push(item) 27 | } else { 28 | smaller.push(item) 29 | } 30 | } 31 | 32 | return [...sort(smaller), base, ...sort(bigger)] 33 | 34 | } 35 | 36 | // 归并 37 | function split(arr) { 38 | let bean = Math.floor((arr.length-1) / 2) 39 | let left = arr.slice(0, bean) 40 | let right = arr.slice(bean) 41 | 42 | return [left, right] 43 | } 44 | 45 | function merge(arr, arr2) { 46 | let result = [] 47 | 48 | let index1 = 0 49 | let index2 = 0 50 | 51 | while (index1 <= arr.length - 1 && index2 <= arr2.length - 1) { 52 | if (arr[index1] < arr2[index2]) { 53 | result.push(arr[index1]) 54 | index1 += 1 55 | } else if (arr[index1] > arr2[index2]) { 56 | result.push(arr2[index2]) 57 | index2 += 1 58 | } else { 59 | result.push(arr[index1], arr2[index2]) 60 | index1 += 1 61 | index2 += 1 62 | } 63 | } 64 | // 如果第一个arr 65 | if (index1 <= arr.length - 1) { 66 | result.push(...arr.slice(index1)) 67 | } 68 | 69 | if (index2 <= arr2.length - 1) { 70 | result.push(...arr2.slice(index2)) 71 | } 72 | 73 | return result 74 | } 75 | 76 | function sort2(arr) { 77 | if (arr.length <= 8) { 78 | return sort(arr) 79 | } 80 | let sp = split(arr) 81 | // return sp.reduce((a,b) => merge(a,b)) 82 | return merge(sort2(sp[0]), sort2(sp[1])) 83 | } 84 | 85 | 86 | 87 | var findKthLargest = function(nums, k) { 88 | // nums = nums.sort((a,b) => b-a) 89 | // nums = sort(nums) 90 | // nums = split(nums) 91 | // nums = merge(nums[0], nums[1]) 92 | nums = sort2(nums) 93 | // console.log(nums) 94 | return nums[nums.length-k] 95 | }; -------------------------------------------------------------------------------- /Array/LargestNumber.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a list of non negative integers, arrange them such that they form the largest number. 3 | 4 | Example 1: 5 | 6 | Input: [10,2] 7 | Output: "210" 8 | Example 2: 9 | 10 | Input: [3,30,34,5,9] 11 | Output: "9534330" 12 | Note: The result may be very large, so you need to return a string instead of an integer. 13 | 14 | 15 | 思路是补位: 16 | 17 | 9 > 34 18 | 19 | 位数不够的补齐。 20 | 21 | 一开始的补位用的是最后一位。测试时发现一个错误: 22 | 23 | 8247 24 | 824 25 | 按照一开始的补位规则: 26 | 824 会补成 8244 27 | 28 | e...虽然调整后通过了测试,不过最终结果是缺少了一些测试例子。 29 | 30 | 我做的调整是,从补位补最后一个变为补最大的一位。但是: 31 | 284 32 | 2847 这种情况下,会以 33 | 284 2847 排,但应该是: 34 | 2847 284 35 | ---- 36 | 所以还是有问题,在Discuss里提个Issue. 37 | --- 38 | 39 | Python2的话可以用 soted的 cmp参数,不过3中已经不存在了。 40 | 41 | 暂时不搞了... 42 | 43 | 测试地址: 44 | https://leetcode.com/problems/largest-number/description/ 45 | 46 | beat 38%~77%. 47 | 48 | """ 49 | class Solution(object): 50 | def largestNumber(self, nums): 51 | """ 52 | :type nums: List[int] 53 | :rtype: str 54 | """ 55 | 56 | if not any(nums): 57 | return '0' 58 | 59 | max_nums = len(str(max(nums))) 60 | 61 | # 2 62 | def mycmp(x, y): 63 | if x + y > y + x: 64 | return 1 65 | else: 66 | return -1 67 | 68 | # 测试用下面的可以跑过 2 & 3。 69 | def makeEqual(s, length=max_nums): 70 | 71 | if len(s) == length: 72 | return s 73 | # 这种补位会通过测试,但是 Leetcode 的测试并没有包含所有的情况。 74 | x = max(s) * (length - len(s)) 75 | return s+x 76 | 77 | # 2 78 | return ''.join(sorted(map(str, nums), cmd=mycmp, reverse=True)) 79 | # 3 80 | return ''.join(sorted(map(str, nums), key=makeEqual, reverse=True)) 81 | 82 | # print(sorted(map(str, nums), key=makeEqual, reverse=True)) 83 | 84 | -------------------------------------------------------------------------------- /Array/LinkedListCycle.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val) { 4 | * this.val = val; 5 | * this.next = null; 6 | * } 7 | */ 8 | 9 | /** 10 | * @param {ListNode} head 11 | * @return {boolean} 12 | */ 13 | 14 | // 两个指针,一个一次走一步,一个一次走两步,如果有环会在某处相遇。 15 | var hasCycle = function(head) { 16 | if (!head) { 17 | return false 18 | } 19 | let oneIndex = head 20 | let twoIndex = head.next 21 | 22 | if (!twoIndex) { 23 | return false 24 | } 25 | 26 | while (oneIndex && twoIndex) { 27 | if (oneIndex === twoIndex) { 28 | return true 29 | } 30 | 31 | oneIndex = oneIndex.next 32 | twoIndex = twoIndex.next 33 | 34 | if (!twoIndex || !twoIndex.next) { 35 | return false 36 | } 37 | 38 | twoIndex = twoIndex.next 39 | } 40 | 41 | return false 42 | }; -------------------------------------------------------------------------------- /Array/LinkedListCycle.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | Given a linked list, determine if it has a cycle in it. 4 | 5 | Follow up: 6 | Can you solve it without using extra space? 7 | 8 | 基本思路: 9 | 10 | 形成环就是后面的节点中的next指向了前面出现过的节点。 11 | 下面这个用了额外空间。 12 | 13 | 改进: 14 | 使用 O(1) 空间的解决方法: 15 | 思路是两个指针: 16 | 一个每次走一步,另一个每次走两步,若有一个环,那么走两步的与走一步的会在走过这个环的长度后相遇。 17 | 相当于两个人跑步,一个每秒跑两米,一个跑一米,绕着100米的圆形跑,100秒过后,一米的这个跑了一圈,二米的这个跑了两圈,但它们相遇了。 18 | 19 | 20 | 测试地址: 21 | https://leetcode.com/problems/linked-list-cycle/description/ 22 | 23 | """ 24 | 25 | # Definition for singly-linked list. 26 | # class ListNode(object): 27 | # def __init__(self, x): 28 | # self.val = x 29 | # self.next = None 30 | 31 | class Solution(object): 32 | def hasCycle(self, head): 33 | """ 34 | :type head: ListNode 35 | :rtype: bool 36 | """ 37 | 38 | # while head: 39 | # if hasattr(head, 'hasVisited'): 40 | # return True 41 | 42 | # head.hasVisited = True 43 | # head = head.next 44 | # return False 45 | 46 | if not head: 47 | return False 48 | 49 | two_head = head.next 50 | 51 | if not two_head: 52 | return False 53 | 54 | while head != None and two_head != None: 55 | 56 | if head == two_head: 57 | return True 58 | 59 | head = head.next 60 | try: 61 | two_head = two_head.next.next 62 | except: 63 | return False 64 | 65 | return False 66 | 67 | -------------------------------------------------------------------------------- /Array/MaxAreaOfIsland.py: -------------------------------------------------------------------------------- 1 | """ 2 | 与今日头条秋招第一题最相似的一道题,只是方向少了四个。 3 | 4 | Given a non-empty 2D array grid of 0's and 1's, an island is a group of 1's (representing land) connected 4-directionally (horizontal or vertical.) You may assume all four edges of the grid are surrounded by water. 5 | 6 | Find the maximum area of an island in the given 2D array. (If there is no island, the maximum area is 0.) 7 | 8 | Example 1: 9 | [[0,0,1,0,0,0,0,1,0,0,0,0,0], 10 | [0,0,0,0,0,0,0,1,1,1,0,0,0], 11 | [0,1,1,0,1,0,0,0,0,0,0,0,0], 12 | [0,1,0,0,1,1,0,0,1,0,1,0,0], 13 | [0,1,0,0,1,1,0,0,1,1,1,0,0], 14 | [0,0,0,0,0,0,0,0,0,0,1,0,0], 15 | [0,0,0,0,0,0,0,1,1,1,0,0,0], 16 | [0,0,0,0,0,0,0,1,1,0,0,0,0]] 17 | Given the above grid, return 6. Note the answer is not 11, because the island must be connected 4-directionally. 18 | Example 2: 19 | [[0,0,0,0,0,0,0,0]] 20 | Given the above grid, return 0. 21 | Note: The length of each dimension in the given grid does not exceed 50. 22 | 23 | passed: 24 | beat 54%. 25 | 26 | 测试地址: 27 | https://leetcode.com/problems/max-area-of-island/description/ 28 | 29 | """ 30 | 31 | class Solution(object): 32 | def makeAroundXY(self, x, y): 33 | return ((x, y-1), 34 | (x, y+1), 35 | (x-1, y), 36 | (x+1, y)) 37 | 38 | def maxAreaOfIsland(self, court): 39 | """ 40 | :type grid: List[List[str]] 41 | :rtype: int 42 | """ 43 | fans_groups = [] 44 | x = 0 45 | y = 0 46 | if not court: 47 | return 0 48 | 49 | x_length = len(court[0]) 50 | y_length = len(court) 51 | 52 | def helper(x, y, result=0): 53 | Xy = self.makeAroundXY(x, y) 54 | for i in Xy: 55 | try: 56 | if i[0] < 0 or i[1] < 0: 57 | continue 58 | 59 | if court[i[1]][i[0]] == 1: 60 | court[i[1]][i[0]] = 0 61 | result += 1 62 | t = helper(i[0], i[1], 0) 63 | result += t 64 | except IndexError: 65 | continue 66 | else: 67 | return result 68 | 69 | 70 | for y in range(y_length): 71 | for x in range(x_length): 72 | if court[y][x] == 1: 73 | court[y][x] = 0 74 | fans_groups.append(helper(x, y, 1)) 75 | 76 | if not fans_groups: 77 | return 0 78 | 79 | return max(fans_groups) 80 | -------------------------------------------------------------------------------- /Array/MaximizeDistanceToClosestPerson.py: -------------------------------------------------------------------------------- 1 | """ 2 | In a row of seats, 1 represents a person sitting in that seat, and 0 represents that the seat is empty. 3 | 4 | There is at least one empty seat, and at least one person sitting. 5 | 6 | Alex wants to sit in the seat such that the distance between him and the closest person to him is maximized. 7 | 8 | Return that maximum distance to closest person. 9 | 10 | Example 1: 11 | 12 | Input: [1,0,0,0,1,0,1] 13 | Output: 2 14 | Explanation: 15 | If Alex sits in the second open seat (seats[2]), then the closest person has distance 2. 16 | If Alex sits in any other open seat, the closest person has distance 1. 17 | Thus, the maximum distance to the closest person is 2. 18 | Example 2: 19 | 20 | Input: [1,0,0,0] 21 | Output: 3 22 | Explanation: 23 | If Alex sits in the last seat, the closest person is 3 seats away. 24 | This is the maximum distance possible, so the answer is 3. 25 | Note: 26 | 27 | 1 <= seats.length <= 20000 28 | seats contains only 0s or 1s, at least one 0, and at least one 1. 29 | 30 | 31 | Alex 要坐在任意一个 0 上,问坐在哪个点上距离最近的 1是最远的。 32 | 33 | 思路: 34 | 1. 处理好边界 35 | 2. 两两相加,用 相加//2 减去前一个,不用后一个减去 相加//2 是因为如果是奇数的话会偏向前一个,偶数无所谓,所以这样做可以少一步判断。 36 | 37 | beat : 38 | 75% 39 | 40 | 测试地址: 41 | https://leetcode.com/contest/weekly-contest-88/problems/maximize-distance-to-closest-person/ 42 | 43 | """ 44 | class Solution(object): 45 | def maxDistToClosest(self, seats): 46 | """ 47 | :type seats: List[int] 48 | :rtype: int 49 | """ 50 | 51 | indexes = [i for i in range(len(seats)) if seats[i] == 1] 52 | x = indexes[0] 53 | 54 | if indexes[0] != 0: 55 | maxes = indexes[0] 56 | else: 57 | maxes = 0 58 | 59 | for i in range(1, len(indexes)): 60 | maxes = max((x + indexes[i]) // 2 - x, maxes) 61 | x = indexes[i] 62 | 63 | if indexes[-1] != len(seats): 64 | maxes = max(len(seats)-indexes[-1]-1, maxes) 65 | return maxes 66 | -------------------------------------------------------------------------------- /Array/MaximumSubarray.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum. 3 | 4 | Example: 5 | 6 | Input: [-2,1,-3,4,-1,2,1,-5,4], 7 | Output: 6 8 | Explanation: [4,-1,2,1] has the largest sum = 6. 9 | Follow up: 10 | 11 | If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle. 12 | 13 | 14 | 思路: 15 | O(n) 16 | 17 | 这个与https://leetcode.com/problems/binary-tree-maximum-path-sum/description/ 18 | 二叉树中最大的路径和相似。 19 | 20 | 到了数组中显得更加清晰: 21 | 每个点都有两个向上返回的状态: 22 | 大于0就向上,否则不向上。 23 | 24 | 不大于0时还要进行一次取最大值。 25 | 26 | 第一次写的时候把路径也带上了,后面发现没有必要。 27 | 28 | 带上路径比较慢 500ms - 700ms. 29 | 30 | 不带的话可以跑 28 ms. 31 | 32 | 测试地址: 33 | https://leetcode.com/problems/maximum-subarray/description/ 34 | 35 | """ 36 | class Solution(object): 37 | def maxSubArray(self, nums): 38 | """ 39 | :type nums: List[int] 40 | :rtype: int 41 | """ 42 | if not nums: 43 | return 0 44 | 45 | maxes = nums[0] 46 | current = nums[0] 47 | 48 | for i in nums[1:]: 49 | maxes = max(maxes, current + i, i) 50 | if current + i < i: 51 | current = i 52 | else: 53 | current = current + i 54 | 55 | return maxes 56 | 57 | # if not nums: 58 | # return 0 59 | 60 | # maxes = ([nums[0]], nums[0]) 61 | # current = ([nums[0]], nums[0]) 62 | 63 | # for i in nums[1:]: 64 | # maxes = max(maxes, (current[0]+[i], current[1] + i), ([i], i), key=lambda x: x[1]) 65 | # if current[1] + i < i: 66 | # current = ([i], i) 67 | # else: 68 | # current = (current[0]+[i], current[1] + i) 69 | 70 | # return maxes[1] 71 | -------------------------------------------------------------------------------- /Array/MergeArray.py: -------------------------------------------------------------------------------- 1 | """ 2 | 好像是今日头条2018 秋招算法题? 3 | 4 | 有m名编辑审核文章,每个编辑独立工作,会把觉得有错误的地方通过下标标注出来: 5 | 6 | [1, 10] 表示1-10个字符应该有问题。 7 | 现在要把多名编辑的结果合并起来: 8 | 9 | [1, 10] [32, 45], 10 | [5, 16] [78, 94] 11 | 12 | 那么合并后是 [1, 16] [32, 45] [78, 94]。 13 | 14 | bug free. 15 | 16 | Leetcode 中也有两个一样的: 17 | https://leetcode.com/problems/merge-intervals/description/ 18 | 19 | 测试通过: 20 | beat 64%~95%... 21 | 22 | 这个更加类似: 23 | https://leetcode.com/problems/insert-interval/description/ 24 | 25 | 这个代码看 InsertInterval.py 26 | """ 27 | 28 | class Solution(object): 29 | def merge(self, _sentences): 30 | """ 31 | :type intervals: List[Interval] 32 | :rtype: List[Interval] 33 | """ 34 | _sentences = sorted(_sentences, key=lambda x: x.start) 35 | 36 | if not _sentences: 37 | return [] 38 | 39 | result = [] 40 | 41 | head = _sentences[0].start 42 | tail = _sentences[0].end 43 | length = len(_sentences) 44 | for x in range(1, length): 45 | i = _sentences[x] 46 | if tail >= i.start: 47 | tail = max(tail, i.end) 48 | else: 49 | result.append([head, tail]) 50 | head = i.start 51 | tail = i.end 52 | 53 | result.append([head, tail]) 54 | return result 55 | 56 | test = ( 57 | [(1, 10), (32, 45)], 58 | [(78, 94), (5, 16)], 59 | [(80, 100), (200, 220), (16, 32)] 60 | ) 61 | 62 | 63 | def mergeArray(sentences): 64 | 65 | """ 66 | 这个测试数据的结构是我自己写的,所以第一步是打散数组。 67 | 1. 根据第一个字符出现的位置进行排序。 68 | 2. 迭代,记录i的头,记录i的末尾,末尾与下一个i的头做比较,若前者记录的大或相等则末尾替换为两者中较大的一个。 69 | 3. 不大的情况添加到结果中,并将头尾替换为此时的数据。 70 | 4. 最后一轮迭代在添加一次。 71 | 72 | """ 73 | 74 | # 打散,相当于原题给的数据中的读入。 75 | _sentences = sorted([y for x in test for y in x], key=lambda x: x[0]) 76 | 77 | if not _sentences: 78 | return [] 79 | 80 | result = [] 81 | 82 | head = _sentences[0][0] 83 | tail = _sentences[0][1] 84 | length = len(_sentences) 85 | for x in range(1, length): 86 | i = _sentences[x] 87 | if tail >= i[0]: 88 | tail = max(tail, i[1]) 89 | else: 90 | result.append([head, tail]) 91 | head = i[0] 92 | tail = i[1] 93 | 94 | result.append([head, tail]) 95 | print(result) 96 | 97 | mergeArray(test) 98 | 99 | -------------------------------------------------------------------------------- /Array/MergerTwoSortedList.py: -------------------------------------------------------------------------------- 1 | """ 2 | 合并两个排序过的数组。 3 | 4 | Input: 1->2->4, 1->3->4 5 | Output: 1->1->2->3->4->4 6 | 基本就是你走一步我走一步,一人一个指向。 7 | 8 | O(n) 9 | 测试用例: 10 | https://leetcode.com/problems/merge-two-sorted-lists/description/ 11 | """ 12 | 13 | # Definition for singly-linked list. 14 | # class ListNode(object): 15 | # def __init__(self, x): 16 | # self.val = x 17 | # self.next = None 18 | 19 | class Solution(object): 20 | 21 | def mergeTwoLists(self, l1, l2): 22 | """ 23 | :type l1: ListNode 24 | :type l2: ListNode 25 | :rtype: ListNode 26 | """ 27 | 28 | head = cur = ListNode(0) 29 | 30 | while l1 and l2: 31 | if l1.val < l2.val: 32 | cur.next = l1 33 | l1 = l1.next 34 | else: 35 | cur.next = l2 36 | l2 = l2.next 37 | 38 | cur = cur.next 39 | 40 | cur.next = l1 or l2 41 | 42 | return head.next 43 | -------------------------------------------------------------------------------- /Array/MinimumFallingPathSum.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a square array of integers A, we want the minimum sum of a falling path through A. 3 | 4 | A falling path starts at any element in the first row, and chooses one element from each row. The next row's choice must be in a column that is different from the previous row's column by at most one. 5 | 6 | 7 | 8 | Example 1: 9 | 10 | Input: [[1,2,3],[4,5,6],[7,8,9]] 11 | Output: 12 12 | Explanation: 13 | The possible falling paths are: 14 | [1,4,7], [1,4,8], [1,5,7], [1,5,8], [1,5,9] 15 | [2,4,7], [2,4,8], [2,5,7], [2,5,8], [2,5,9], [2,6,8], [2,6,9] 16 | [3,5,7], [3,5,8], [3,5,9], [3,6,8], [3,6,9] 17 | The falling path with the smallest sum is [1,4,7], so the answer is 12. 18 | 19 | 20 | 21 | Note: 22 | 23 | 1. 1 <= A.length == A[0].length <= 100 24 | 2. -100 <= A[i][j] <= 100 25 | 26 | 27 | 28 | 从上到下,每下层元素可以选择位于它之上的 左中右 三个元素。 29 | 30 | 直接 Dp 思路: 31 | 从第二层开始,每个元素都选择位于它之上的三个元素中最小的一个元素。 32 | 最后输出最后一层中最小的元素即可。 33 | 34 | 测试地址: 35 | https://leetcode.com/contest/weekly-contest-108/problems/minimum-falling-path-sum/ 36 | 37 | """ 38 | class Solution(object): 39 | def minFallingPathSum(self, A): 40 | """ 41 | :type A: List[List[int]] 42 | :rtype: int 43 | """ 44 | 45 | for y in range(1, len(A)): 46 | for x in range(len(A[0])): 47 | a = A[y-1][x-1] if x-1 >= 0 else float('inf') 48 | b = A[y-1][x+1] if x+1 < len(A[0]) else float('inf') 49 | 50 | A[y][x] += min(A[y-1][x], a, b) 51 | 52 | return min(A[-1]) 53 | -------------------------------------------------------------------------------- /Array/MinimumIndexSumOfTwoLists.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | Suppose Andy and Doris want to choose a restaurant for dinner, and they both have a list of favorite restaurants represented by strings. 4 | 5 | You need to help them find out their common interest with the least list index sum. If there is a choice tie between answers, output all of them with no order requirement. You could assume there always exists an answer. 6 | 7 | Example 1: 8 | Input: 9 | ["Shogun", "Tapioca Express", "Burger King", "KFC"] 10 | ["Piatti", "The Grill at Torrey Pines", "Hungry Hunter Steakhouse", "Shogun"] 11 | Output: ["Shogun"] 12 | Explanation: The only restaurant they both like is "Shogun". 13 | Example 2: 14 | Input: 15 | ["Shogun", "Tapioca Express", "Burger King", "KFC"] 16 | ["KFC", "Shogun", "Burger King"] 17 | Output: ["Shogun"] 18 | Explanation: The restaurant they both like and have the least index sum is "Shogun" with index sum 1 (0+1). 19 | Note: 20 | The length of both lists will be in the range of [1, 1000]. 21 | The length of strings in both lists will be in the range of [1, 30]. 22 | The index is starting from 0 to the list length minus 1. 23 | No duplicates in both lists. 24 | 25 | 给两个列表,求加起来的索引是最小的重合部分,若有多个相同的则输出多个相同的,无顺序要求。 26 | 27 | 思路: 28 | 29 | 直接判断的话是 O(mn),利用哈希表(字典)来减少查询时间。 30 | 31 | 可优化部分: 32 | 第二次不用哈希表,用两个变量,一个代表当前的最小值,一个代表所存数据,不断替换,追加。 33 | 34 | 测试用例: 35 | https://leetcode.com/problems/minimum-index-sum-of-two-lists/description/ 36 | 37 | """ 38 | 39 | class Solution(object): 40 | def findRestaurant(self, list1, list2): 41 | """ 42 | :type list1: List[str] 43 | :type list2: List[str] 44 | :rtype: List[str] 45 | """ 46 | list1_dict = {value:index for index, value in enumerate(list1)} 47 | commonInterest = {} 48 | for index, value in enumerate(list2): 49 | if list1_dict.get(value) is not None: 50 | try: 51 | commonInterest[index + list1_dict.get(value)].append(value) 52 | except KeyError: 53 | commonInterest[index + list1_dict.get(value)] = [value] 54 | 55 | return commonInterest[min(commonInterest)] 56 | 57 | -------------------------------------------------------------------------------- /Array/MinimumPathSum.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path. 3 | 4 | Note: You can only move either down or right at any point in time. 5 | 6 | Example: 7 | 8 | Input: 9 | [ 10 | [1,3,1], 11 | [1,5,1], 12 | [4,2,1] 13 | ] 14 | Output: 7 15 | Explanation: Because the path 1→3→1→1→1 minimizes the sum 16 | 17 | 给一个二维数组,里面全是非负整数,找到一条左上到右下花费最小的路线。 18 | 19 | 思路: 20 | 当前点只要加 up 和 left 中较小的一个即可。 21 | 22 | 效率 O(n) 23 | 24 | 为了判断边界直接顺着思路写了。优化的话可以先把最上面的一排按其左的数相加,最左边的一列按其上面的数相加。 25 | 然后从 [1,1] 开始,这样不需要判断边界,写法上可以少点判断效率能提高10+ms。 26 | 27 | 测试地址: 28 | https://leetcode.com/problems/minimum-path-sum/description/ 29 | 30 | """ 31 | class Solution(object): 32 | def get_up_left(self, x, y): 33 | if y-1 < 0: 34 | up = False 35 | else: 36 | up = (x, y-1) 37 | if x-1 < 0: 38 | left = False 39 | else: 40 | left = (x-1,y) 41 | 42 | # up and left 43 | return (up, left) 44 | 45 | def minPathSum(self, grid): 46 | """ 47 | :type grid: List[List[int]] 48 | :rtype: int 49 | """ 50 | 51 | for i in range(len(grid)): 52 | for j in range(len(grid[0])): 53 | xy = self.get_up_left(j, i) 54 | up = grid[xy[0][1]][xy[0][0]] if xy[0] else float('inf') 55 | left = grid[xy[1][1]][xy[1][0]] if xy[1] else float('inf') 56 | 57 | if up == float('inf') and left == float('inf'): 58 | continue 59 | grid[i][j] = grid[i][j] + min(up, left) 60 | 61 | 62 | return grid[-1][-1] -------------------------------------------------------------------------------- /Array/MissingNumber.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one that is missing from the array. 3 | 4 | Example 1: 5 | 6 | Input: [3,0,1] 7 | Output: 2 8 | Example 2: 9 | 10 | Input: [9,6,4,2,3,5,7,0,1] 11 | Output: 8 12 | Note: 13 | Your algorithm should run in linear runtime complexity. Could you implement it using only constant extra space complexity? 14 | 15 | 给出从 0 - n的数,找出其中缺少的那个。 16 | 17 | 18 | 思路: 19 | 一开始的思路只有 set ... set(n+1),set(nums),然后取差集。 20 | 这种方法固然可以通过测试,不过题目要求使用常数空间也就是 O(1)。 21 | 22 | 后来经过 Discuss 区里的点拨,发现几种有趣的方法: 23 | 24 | 1. 使用异或。 两个相同的数会相互抵消掉。也就是说,从0-n异或一遍。然后在用这个数把nums里的给异或一遍。好了剩下的就是那个缺少的了。 25 | 2. 使用和。思路与异或有异曲同工之妙,0-n加一遍。然后在减去,剩下的也是。 26 | 27 | 运用数学方法,很妙。 28 | 29 | 测试地址: 30 | https://leetcode.com/problems/missing-number/description/ 31 | 32 | 这里用了加。异或一样的。 33 | 34 | beat 88% 28ms. 35 | 36 | """ 37 | class Solution(object): 38 | def missingNumber(self, nums): 39 | """ 40 | :type nums: List[int] 41 | :rtype: int 42 | """ 43 | # x = list(set(range(max(nums)+1)) - set(nums)) 44 | # if x: 45 | # return x.pop() 46 | # else: 47 | # return max(nums)+1 48 | all_nums = sum(range(len(nums)+1)) 49 | 50 | for i in nums: 51 | all_nums -= i 52 | 53 | return all_nums 54 | -------------------------------------------------------------------------------- /Array/NumberOfIslands.py: -------------------------------------------------------------------------------- 1 | """ 2 | 与今日头条的秋招第一题差不多的题: 3 | Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water. 4 | 5 | Example 1: 6 | 7 | Input: 8 | 11110 9 | 11010 10 | 11000 11 | 00000 12 | 13 | Output: 1 14 | Example 2: 15 | 16 | Input: 17 | 11000 18 | 11000 19 | 00100 20 | 00011 21 | 22 | Output: 3 23 | 24 | 分析看 FootbalFans.py 25 | 26 | passed. 27 | 28 | 测试地址: 29 | https://leetcode.com/problems/number-of-islands/description/ 30 | 31 | """ 32 | class Solution(object): 33 | def makeXY(self, x, y): 34 | return ((x, y-1), 35 | (x, y+1), 36 | (x-1, y), 37 | (x+1, y)) 38 | 39 | def numIslands(self, court): 40 | """ 41 | :type grid: List[List[str]] 42 | :rtype: int 43 | """ 44 | fans_groups = [] 45 | x = 0 46 | y = 0 47 | if not court: 48 | return 0 49 | 50 | x_length = len(court[0]) 51 | y_length = len(court) 52 | 53 | def helper(x, y): 54 | Xy = self.makeXY(x, y) 55 | for i in Xy: 56 | try: 57 | if i[1] < 0 or i[0] < 0: 58 | continue 59 | 60 | if court[i[1]][i[0]] == '1': 61 | court[i[1]][i[0]] = '0' 62 | t = helper(i[0], i[1]) 63 | except IndexError: 64 | continue 65 | else: 66 | return 1 67 | 68 | 69 | for y in range(y_length): 70 | for x in range(x_length): 71 | if court[y][x] == '1': 72 | court[y][x] = '0' 73 | fans_groups.append(helper(x, y)) 74 | 75 | 76 | 77 | if not fans_groups: 78 | return 0 79 | 80 | return len(fans_groups) 81 | 82 | -------------------------------------------------------------------------------- /Array/OddEvenLinkedList.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a singly linked list, group all odd nodes together followed by the even nodes. Please note here we are talking about the node number and not the value in the nodes. 3 | 4 | You should try to do it in place. The program should run in O(1) space complexity and O(nodes) time complexity. 5 | 6 | Example 1: 7 | 8 | Input: 1->2->3->4->5->NULL 9 | Output: 1->3->5->2->4->NULL 10 | Example 2: 11 | 12 | Input: 2->1->3->5->6->4->7->NULL 13 | Output: 2->3->6->7->1->5->4->NULL 14 | Note: 15 | 16 | The relative order inside both the even and odd groups should remain as it was in the input. 17 | The first node is considered odd, the second node even and so on ... 18 | 19 | 20 | 给一个单链表,将所有的单数节点和双数节点聚合在一块,双数节点跟在单数节点后面。 21 | 22 | 空间复杂度需要为 O(1) 时间则为 O(n) 23 | 24 | 思路: 25 | 26 | 1. 定义两个开头的节点,odd 和 even,用于区分单双。 27 | odd.next 和 even.next 都同时为 .next.next。 28 | 29 | 不断替换,直到最后,最后不要忘了把 even 连在 odd 后面。 30 | 31 | beat: 32 | 100% 33 | 34 | 测试地址: 35 | https://leetcode.com/problems/odd-even-linked-list/description/ 36 | 37 | """ 38 | # Definition for singly-linked list. 39 | # class ListNode(object): 40 | # def __init__(self, x): 41 | # self.val = x 42 | # self.next = None 43 | 44 | class Solution(object): 45 | def oddEvenList(self, head): 46 | """ 47 | :type head: ListNode 48 | :rtype: ListNode 49 | """ 50 | if not head: 51 | return head 52 | odd = head 53 | even = head.next 54 | even_head = even 55 | 56 | while odd.next and even.next: 57 | odd.next = odd.next.next 58 | even.next = even.next.next 59 | 60 | odd = odd.next 61 | even = even.next 62 | 63 | odd.next = even_head 64 | 65 | return head 66 | -------------------------------------------------------------------------------- /Array/PartitionArrayIntoDisjointIntervals.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given an array A, partition it into two (contiguous) subarrays left and right so that: 3 | 4 | Every element in left is less than or equal to every element in right. 5 | left and right are non-empty. 6 | left has the smallest possible size. 7 | Return the length of left after such a partitioning. It is guaranteed that such a partitioning exists. 8 | 9 | 10 | 11 | Example 1: 12 | 13 | Input: [5,0,3,8,6] 14 | Output: 3 15 | Explanation: left = [5,0,3], right = [8,6] 16 | Example 2: 17 | 18 | Input: [1,1,1,0,6,12] 19 | Output: 4 20 | Explanation: left = [1,1,1,0], right = [6,12] 21 | 22 | 23 | Note: 24 | 25 | 2 <= A.length <= 30000 26 | 0 <= A[i] <= 10^6 27 | It is guaranteed there is at least one way to partition A as described. 28 | 29 | 30 | 给定一个数组,分成两个部分,left 和 right。 31 | left 有以下三个特征: 32 | 1. left 中的每一个元素都小于或等于 right 中的每一个元素。 33 | 2. left 和 right 是非空。 34 | 3. left 尽量小。 35 | 36 | 那么只要 left 中的最大值比 right 中的最小值要小即可。 37 | 38 | [5,0,3,8,6] 39 | 5 0 3 8 6 40 | 5 0 3 8 6 41 | ...... 42 | 43 | 那么只要从左向右过一遍,取最大。 44 | 在从右向左过一遍取最小。 45 | 46 | [5,0,3,8,6] 47 | max -> 5 5 5 8 8 48 | min <- 0 0 3 6 6 49 | 对比时是 max 中的 [i] 与 min中的 i+1对比若 max[i] < min[i+1] 即找到第一个 left 与 right 的分界点了。 50 | 第一个分界点即为left最少的一个点。 51 | 52 | 测试地址: 53 | https://leetcode.com/problems/partition-array-into-disjoint-intervals/description/ 54 | 55 | beat 66.67%. 56 | 57 | """ 58 | class Solution(object): 59 | def partitionDisjoint(self, A): 60 | """ 61 | :type A: List[int] 62 | :rtype: int 63 | """ 64 | maxes = [A[0]] 65 | mines = [A[-1]] 66 | 67 | for i in range(1, len(A)): 68 | if A[i] > maxes[i-1]: 69 | maxes.append(A[i]) 70 | else: 71 | maxes.append(maxes[i-1]) 72 | 73 | A = A[::-1] 74 | 75 | for i in range(1, len(A)): 76 | 77 | if A[i] < mines[i-1]: 78 | mines.append(A[i]) 79 | else: 80 | mines.append(mines[i-1]) 81 | 82 | mines = mines[::-1] 83 | for i in range(len(mines)-1): 84 | if maxes[i] <= mines[i+1]: 85 | return i+1 86 | -------------------------------------------------------------------------------- /Array/PartitionList.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x. 3 | 4 | You should preserve the original relative order of the nodes in each of the two partitions. 5 | 6 | Example: 7 | 8 | Input: head = 1->4->3->2->5->2, x = 3 9 | Output: 1->2->2->4->3->5 10 | 11 | 无脑怼。 12 | 13 | beat: 14 | 99%. 15 | 16 | 测试地址: 17 | https://leetcode.com/problems/partition-list/description/ 18 | """ 19 | # Definition for singly-linked list. 20 | # class ListNode(object): 21 | # def __init__(self, x): 22 | # self.val = x 23 | # self.next = None 24 | 25 | class Solution(object): 26 | def partition(self, head, x): 27 | """ 28 | :type head: ListNode 29 | :type x: int 30 | :rtype: ListNode 31 | """ 32 | 33 | all_nodes = [] 34 | 35 | while head: 36 | all_nodes.append(head.val) 37 | head = head.next 38 | 39 | less_nodes = [] 40 | greater_nodes = [] 41 | 42 | for i in all_nodes: 43 | if i < x: 44 | less_nodes.append(i) 45 | else: 46 | greater_nodes.append(i) 47 | 48 | if less_nodes: 49 | less_head = ListNode(less_nodes[0]) 50 | 51 | head = less_head if less_nodes else None 52 | 53 | for i in less_nodes[1:]: 54 | less_head.next = ListNode(i) 55 | less_head = less_head.next 56 | 57 | if greater_nodes: 58 | greater_head = ListNode(greater_nodes[0]) 59 | 60 | _head = greater_head if greater_nodes else None 61 | 62 | for i in greater_nodes[1:]: 63 | greater_head.next = ListNode(i) 64 | greater_head = greater_head.next 65 | 66 | if head: 67 | less_head.next = _head 68 | 69 | return head 70 | return _head 71 | -------------------------------------------------------------------------------- /Array/Pascal's TriangleI_II.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a non-negative integer numRows, generate the first numRows of Pascal's triangle. 3 | 4 | 5 | In Pascal's triangle, each number is the sum of the two numbers directly above it. 6 | 7 | Example: 8 | 9 | Input: 5 10 | Output: 11 | [ 12 | [1], 13 | [1,1], 14 | [1,2,1], 15 | [1,3,3,1], 16 | [1,4,6,4,1] 17 | ] 18 | 19 | 帕斯卡三角。 20 | 21 | 图看链接: 22 | https://leetcode.com/problems/pascals-triangle/description/ 23 | 24 | 顺着思路来即可。 25 | 26 | I 27 | 测试地址: 28 | https://leetcode.com/problems/pascals-triangle/description/ 29 | 30 | II 31 | 测试地址: 32 | https://leetcode.com/problems/pascals-triangle-ii/description/ 33 | 34 | II 中的要求是返回最后一个,且空间为 O(K)。下面这个空间不是 O(k) 不过只要修改一下即可。 35 | 36 | """ 37 | # I 38 | class Solution(object): 39 | def generate(self, numRows): 40 | """ 41 | :type numRows: int 42 | :rtype: List[List[int]] 43 | """ 44 | result = [] 45 | 46 | for i in range(1, numRows+1): 47 | x = [0 for j in range(i)] 48 | x[0] = 1 49 | x[-1] = 1 50 | for j in range(1, i-1): 51 | x[j] = result[-1][j] + result[-1][j-1] 52 | 53 | result.append(x) 54 | 55 | return result 56 | 57 | # II 58 | class Solution(object): 59 | def generate(self, numRows): 60 | """ 61 | :type numRows: int 62 | :rtype: List[List[int]] 63 | """ 64 | result = [] 65 | 66 | for i in range(1, numRows+2): 67 | x = [0 for j in range(i)] 68 | x[0] = 1 69 | x[-1] = 1 70 | for j in range(1, i-1): 71 | x[j] = result[-1][j] + result[-1][j-1] 72 | 73 | result.append(x) 74 | 75 | return result[-1] 76 | -------------------------------------------------------------------------------- /Array/PlusOne.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a non-empty array of digits representing a non-negative integer, plus one to the integer. 3 | 4 | The digits are stored such that the most significant digit is at the head of the list, and each element in the array contain a single digit. 5 | 6 | You may assume the integer does not contain any leading zero, except the number 0 itself. 7 | 8 | Example 1: 9 | 10 | Input: [1,2,3] 11 | Output: [1,2,4] 12 | Explanation: The array represents the integer 123. 13 | Example 2: 14 | 15 | Input: [4,3,2,1] 16 | Output: [4,3,2,2] 17 | Explanation: The array represents the integer 4321. 18 | 19 | 整数列表 -> 字符串 -> 整数 -> +1 ->字符串 -> 整数列表。 20 | 21 | 有点无脑,效率也可。 22 | 23 | beat 63% 24ms. 24 | 测试地址: 25 | https://leetcode.com/problems/plus-one/description/ 26 | 27 | """ 28 | class Solution(object): 29 | def plusOne(self, digits): 30 | """ 31 | :type digits: List[int] 32 | :rtype: List[int] 33 | """ 34 | 35 | return list(map(int, list(str(int(''.join(map(str, digits)))+1)))) -------------------------------------------------------------------------------- /Array/ProductOfArrayExceptSelf.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given an array nums of n integers where n > 1, return an array output such that output[i] is equal to the product of all the elements of nums except nums[i]. 3 | 4 | Example: 5 | 6 | Input: [1,2,3,4] 7 | Output: [24,12,8,6] 8 | Note: Please solve it without division and in O(n). 9 | 10 | Follow up: 11 | Could you solve it with constant space complexity? (The output array does not count as extra space for the purpose of space complexity analysis.) 12 | 13 | 给一个数组,返回数组中除了这一位的数其他数的乘积。 14 | 15 | 不能用除的,且时间复杂度需要为 O(n)。 16 | 17 | 进阶条件 空间复杂度为常数级别。 18 | 19 | 一刷进阶条件没达成。 20 | 21 | 基本思路是,一左一右两个存储位置的新列表。 22 | 23 | 从左到右过一遍,从右到左过一遍。算出每个数左边和右边的乘积。 24 | 25 | 最后输出每个位置的左*右。 26 | 27 | 效率是 O(n),没用除。但空间是 O(2n)。 28 | 29 | beat 57% ~ 80% (在 2 中需要把 range 变为 xrange). 30 | 前面那几个的思路也是同样的。多测几次应该也能beat 100%... 31 | 32 | 哎哎?突然想到,output 的数组不算在额外空间里的话, 33 | 可以直接把output数组作为 left。然后right的时候直接替换就好了啊。 34 | 35 | 没错,这样就是 O(1) 了,进阶达成。 36 | 37 | beat 98%。 38 | 39 | 测试链接: 40 | https://leetcode.com/problems/product-of-array-except-self/description/ 41 | 42 | """ 43 | class Solution(object): 44 | def productExceptSelf(self, nums): 45 | """ 46 | :type nums: List[int] 47 | :rtype: List[int] 48 | """ 49 | output = [1] 50 | for i in range(len(nums)-1): 51 | output.append(output[-1] * nums[i]) 52 | 53 | right = 1 54 | for i in range(len(nums)-1, -1, -1): 55 | output[i] = right * output[i] 56 | right *= nums[i] 57 | 58 | return output 59 | 60 | # left = [1] 61 | # right = [1] 62 | 63 | 64 | # for i in range(len(nums)-1): 65 | # left.append(left[-1] * nums[i]) 66 | 67 | # for i in range(len(nums)-1, 0, -1): 68 | # right.append(right[-1] * nums[i]) 69 | 70 | # length = len(left) 71 | 72 | # return [left[i] * right[length-1-i] for i in range(length)] 73 | -------------------------------------------------------------------------------- /Array/RemoveDuplicatesFromSortedArray.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a sorted array nums, remove the duplicates in-place such that each element appear only once and return the new length. 3 | 4 | Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory. 5 | 6 | Example 1: 7 | 8 | Given nums = [1,1,2], 9 | 10 | Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively. 11 | 12 | It doesn't matter what you leave beyond the returned length. 13 | Example 2: 14 | 15 | Given nums = [0,0,1,1,1,2,2,3,3,4], 16 | 17 | Your function should return length = 5, with the first five elements of nums being modified to 0, 1, 2, 3, and 4 respectively. 18 | 19 | It doesn't matter what values are set beyond the returned length. 20 | Clarification: 21 | 22 | Confused why the returned value is an integer but your answer is an array? 23 | 24 | Note that the input array is passed in by reference, which means modification to the input array will be known to the caller as well. 25 | 26 | Internally you can think of this: 27 | 28 | // nums is passed in by reference. (i.e., without making a copy) 29 | int len = removeDuplicates(nums); 30 | 31 | // any modification to nums in your function would be known by the caller. 32 | // using the length returned by your function, it prints the first len elements. 33 | for (int i = 0; i < len; i++) { 34 | print(nums[i]); 35 | } 36 | 37 | 删除给定数组的重复的数字,在原数组上操作。 38 | 39 | 这个从后向前,判断是否重复,若重复将下标加入要删除的列表中。 40 | 最后迭代这个要删除的列表,然后将所有下标删除。因为是从后向前所以不会打乱顺序。 41 | 42 | beat 56% 43 | 44 | 测试地址: 45 | https://leetcode.com/problems/remove-duplicates-from-sorted-array/description/ 46 | 47 | 48 | """ 49 | class Solution(object): 50 | def removeDuplicates(self, nums): 51 | """ 52 | :type nums: List[int] 53 | :rtype: int 54 | """ 55 | 56 | if not nums: 57 | return 58 | 59 | length = len(nums)-1 60 | 61 | one = nums[length] 62 | 63 | remove_index = [] 64 | 65 | for i in range(length-1, -1, -1): 66 | if one == nums[i]: 67 | remove_index.append(i) 68 | continue 69 | one = nums[i] 70 | 71 | for i in remove_index: 72 | nums.pop(i) 73 | -------------------------------------------------------------------------------- /Array/RemoveDuplicatesFromSortedArrayII.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a sorted array nums, remove the duplicates in-place such that duplicates appeared at most twice and return the new length. 3 | 4 | Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory. 5 | 6 | Example 1: 7 | 8 | Given nums = [1,1,1,2,2,3], 9 | 10 | Your function should return length = 5, with the first five elements of nums being 1, 1, 2, 2 and 3 respectively. 11 | 12 | It doesn't matter what you leave beyond the returned length. 13 | Example 2: 14 | 15 | Given nums = [0,0,1,1,1,1,2,3,3], 16 | 17 | Your function should return length = 7, with the first seven elements of nums being modified to 0, 0, 1, 1, 2, 3 and 3 respectively. 18 | 19 | It doesn't matter what values are set beyond the returned length. 20 | Clarification: 21 | 22 | Confused why the returned value is an integer but your answer is an array? 23 | 24 | Note that the input array is passed in by reference, which means modification to the input array will be known to the caller as well. 25 | 26 | Internally you can think of this: 27 | 28 | // nums is passed in by reference. (i.e., without making a copy) 29 | int len = removeDuplicates(nums); 30 | 31 | // any modification to nums in your function would be known by the caller. 32 | // using the length returned by your function, it prints the first len elements. 33 | for (int i = 0; i < len; i++) { 34 | print(nums[i]); 35 | } 36 | 37 | 至多出现两次,思路上没有变化,顺手一写。 38 | 39 | beat 91% 40 | 41 | 测试地址: 42 | https://leetcode.com/problems/remove-duplicates-from-sorted-array-ii/description/ 43 | 44 | """ 45 | class Solution(object): 46 | def removeDuplicates(self, nums): 47 | """ 48 | :type nums: List[int] 49 | :rtype: int 50 | """ 51 | 52 | if not nums: 53 | return 54 | 55 | length = len(nums) - 1 56 | one = nums[length] 57 | two = 1 58 | 59 | remove_index = [] 60 | 61 | for i in range(length-1, -1, -1): 62 | if one == nums[i]: 63 | if two == 2: 64 | remove_index.append(i) 65 | else: 66 | two += 1 67 | else: 68 | one = nums[i] 69 | two = 1 70 | 71 | for i in remove_index: 72 | nums.pop(i) 73 | 74 | -------------------------------------------------------------------------------- /Array/RemoveDuplicatesFromSortedList.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a sorted linked list, delete all duplicates such that each element appear only once. 3 | 4 | Example 1: 5 | 6 | Input: 1->1->2 7 | Output: 1->2 8 | Example 2: 9 | 10 | Input: 1->1->2->3->3 11 | Output: 1->2->3 12 | 13 | 14 | 删除链表中重复的节点。 15 | 16 | 一直迭代,若当前 val == next.val,则把 next 与 next.next 相连。 17 | 18 | beat 19 | 100% 20 | 21 | 22 | 测试地址: 23 | https://leetcode.com/problems/remove-duplicates-from-sorted-list/description/ 24 | 25 | 26 | """ 27 | # Definition for singly-linked list. 28 | # class ListNode(object): 29 | # def __init__(self, x): 30 | # self.val = x 31 | # self.next = None 32 | 33 | class Solution(object): 34 | def deleteDuplicates(self, head): 35 | """ 36 | :type head: ListNode 37 | :rtype: ListNode 38 | """ 39 | if not head: 40 | return head 41 | 42 | x = head 43 | 44 | while head.next: 45 | if head.val == head.next.val: 46 | head.next = head.next.next 47 | else: 48 | head = head.next 49 | 50 | return x 51 | -------------------------------------------------------------------------------- /Array/RemoveDuplicatesFromSortedListII.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list. 3 | 4 | Example 1: 5 | 6 | Input: 1->2->3->3->4->4->5 7 | Output: 1->2->5 8 | Example 2: 9 | 10 | Input: 1->1->1->2->3 11 | Output: 2->3 12 | 13 | 这次要把全部的重复都删除。 14 | 15 | 我的思路是利用标记,过一遍,先把重复的删到剩一个,然后把剩下的一个标记为重复。 16 | 17 | 然后做一个新的链表。 18 | 19 | beat 72% 20 | 21 | 测试地址: 22 | https://leetcode.com/problems/remove-duplicates-from-sorted-list-ii/description/ 23 | 24 | 25 | """ 26 | # Definition for singly-linked list. 27 | # class ListNode(object): 28 | # def __init__(self, x): 29 | # self.val = x 30 | # self.next = None 31 | 32 | class Solution(object): 33 | def deleteDuplicates(self, head): 34 | """ 35 | :type head: ListNode 36 | :rtype: ListNode 37 | """ 38 | if not head: 39 | return head 40 | 41 | x = head 42 | 43 | while head.next: 44 | if head.val == head.next.val: 45 | head.next = head.next.next 46 | head.duplicate = True 47 | else: 48 | head = head.next 49 | 50 | while x: 51 | if hasattr(x, 'duplicate'): 52 | x = x.next 53 | else: 54 | break 55 | 56 | if not x: 57 | return None 58 | 59 | new = ListNode(x.val) 60 | x = x.next 61 | _new = new 62 | 63 | while x: 64 | if hasattr(x, 'duplicate'): 65 | x = x.next 66 | else: 67 | new.next = ListNode(x.val) 68 | new = new.next 69 | x = x.next 70 | return _new 71 | -------------------------------------------------------------------------------- /Array/RemoveLinkedListElements.py: -------------------------------------------------------------------------------- 1 | """ 2 | Remove all elements from a linked list of integers that have value val. 3 | 4 | Example: 5 | 6 | Input: 1->2->6->3->4->5->6, val = 6 7 | Output: 1->2->3->4->5 8 | 9 | 删除所有的val。 10 | 11 | 注意下开头即为 val 的情况。 12 | 13 | beat 14 | 90% 15 | 16 | 测试地址: 17 | https://leetcode.com/problems/remove-linked-list-elements/description/ 18 | 19 | """ 20 | # Definition for singly-linked list. 21 | # class ListNode(object): 22 | # def __init__(self, x): 23 | # self.val = x 24 | # self.next = None 25 | 26 | class Solution(object): 27 | def removeElements(self, head, val): 28 | """ 29 | :type head: ListNode 30 | :type val: int 31 | :rtype: ListNode 32 | """ 33 | 34 | while head: 35 | if head.val == val: 36 | head = head.next 37 | else: 38 | break 39 | 40 | _head = head 41 | 42 | if not _head: 43 | return None 44 | 45 | while head and head.next: 46 | if head.next.val == val: 47 | head.next = head.next.next 48 | else: 49 | head = head.next 50 | return _head 51 | -------------------------------------------------------------------------------- /Array/ReverseLinkedList.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val, next) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.next = (next===undefined ? null : next) 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} head 10 | * @return {ListNode} 11 | */ 12 | 13 | // 翻转链表的思路 14 | // 把head取出来,把head.next取出来,head.next.next也取出来。 15 | // head.next = head 16 | // 新的(head.next和head)与head.next.next进行新一轮交换。 17 | // 直至空。 18 | // PS,链表操作好麻烦。 19 | var reverseList = function(head) { 20 | 21 | let newHead = null 22 | 23 | // 先不判断进行一次交换 24 | let nHead = head 25 | if (!nHead) { 26 | return null 27 | } 28 | let next = nHead.next 29 | if (!next) { 30 | return nHead 31 | } 32 | let lNext = next.next 33 | 34 | next.next = nHead 35 | nHead.next = null 36 | 37 | newHead = next 38 | 39 | while (nHead && next && next.next) { 40 | nHead = lNext 41 | if (!nHead) { 42 | return newHead 43 | } 44 | 45 | next = nHead.next 46 | 47 | if (!next) { 48 | nHead.next = newHead 49 | return nHead 50 | } 51 | lNext = next.next 52 | 53 | next.next = nHead 54 | nHead.next = newHead 55 | 56 | newHead = next 57 | 58 | } 59 | }; -------------------------------------------------------------------------------- /Array/RotateList.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a linked list, rotate the list to the right by k places, where k is non-negative. 3 | 4 | Example 1: 5 | 6 | Input: 1->2->3->4->5->NULL, k = 2 7 | Output: 4->5->1->2->3->NULL 8 | Explanation: 9 | rotate 1 steps to the right: 5->1->2->3->4->NULL 10 | rotate 2 steps to the right: 4->5->1->2->3->NULL 11 | Example 2: 12 | 13 | Input: 0->1->2->NULL, k = 4 14 | Output: 2->0->1->NULL 15 | Explanation: 16 | rotate 1 steps to the right: 2->0->1->NULL 17 | rotate 2 steps to the right: 1->2->0->NULL 18 | rotate 3 steps to the right: 0->1->2->NULL 19 | rotate 4 steps to the right: 2->0->1->NULL 20 | 21 | 22 | 旋转链表。 k 非负。 23 | 24 | k 超过链表的最大长度也可。 25 | 26 | 思路: 27 | 28 | 过一遍链表长度,k % length 取个模,防止 k 超级大。 29 | 30 | 之后 slow fast 两个,fast 先走 k 个,然后 slow 与 fast 同时走,走到最后 slow.next 即为从后到前 k 个的起点。 31 | 32 | 剩下的就是把原来的尾置换到前。 33 | 34 | 下面这个可以优化下,不过就测试来说已经可以了。 35 | 36 | beat 100% 37 | 24ms ~ 36ms 38 | 39 | 测试地址: 40 | https://leetcode.com/problems/rotate-list/description/ 41 | 42 | """ 43 | # Definition for singly-linked list. 44 | # class ListNode(object): 45 | # def __init__(self, x): 46 | # self.val = x 47 | # self.next = None 48 | 49 | class Solution(object): 50 | 51 | def rotateRight(self, head, k): 52 | """ 53 | :type head: ListNode 54 | :type k: int 55 | :rtype: ListNode 56 | """ 57 | if not k or not head: 58 | return head 59 | 60 | def getLength(node): 61 | length = 0 62 | 63 | while node: 64 | node = node.next 65 | length += 1 66 | 67 | return length 68 | 69 | length = getLength(head) 70 | k = k % length 71 | 72 | slow = head 73 | fast = head 74 | 75 | while k > 0: 76 | fast = fast.next 77 | 78 | k -= 1 79 | 80 | while fast.next: 81 | slow = slow.next 82 | fast = fast.next 83 | 84 | rotate_head = slow.next 85 | 86 | if not rotate_head: 87 | return head 88 | 89 | slow.next = None 90 | 91 | _rotate_head = rotate_head 92 | while _rotate_head.next: 93 | _rotate_head = _rotate_head.next 94 | 95 | _rotate_head.next = head 96 | 97 | return rotate_head 98 | -------------------------------------------------------------------------------- /Array/ShuffleAnArray.py: -------------------------------------------------------------------------------- 1 | """ 2 | Shuffle a set of numbers without duplicates. 3 | 4 | Example: 5 | 6 | // Init an array with set 1, 2, and 3. 7 | int[] nums = {1,2,3}; 8 | Solution solution = new Solution(nums); 9 | 10 | // Shuffle the array [1,2,3] and return its result. Any permutation of [1,2,3] must equally likely to be returned. 11 | solution.shuffle(); 12 | 13 | // Resets the array back to its original configuration [1,2,3]. 14 | solution.reset(); 15 | 16 | // Returns the random shuffling of array [1,2,3]. 17 | solution.shuffle(); 18 | 19 | 将一个数组洗牌。 20 | 21 | 直接用 random.sample 即可。 22 | 23 | sample 中的算法直接用了 set() 以及无限从数组下标中选择然后判断是否在set中...有点无脑。 24 | 25 | 在后面的例子中看到一种非常有趣的: 26 | 27 | sorted 可以指定key,把这个key指定为 random.random()即可。 28 | 29 | 测试地址: 30 | https://leetcode.com/problems/shuffle-an-array/description/ 31 | 32 | 平均 beat 30% 左右。 33 | 34 | 用 sample 完全取决于运气,因为底层的源码就是取决于运气的... 35 | 36 | """ 37 | import random 38 | 39 | class Solution(object): 40 | 41 | def __init__(self, nums): 42 | """ 43 | :type nums: List[int] 44 | """ 45 | self.nums = nums 46 | 47 | def reset(self): 48 | """ 49 | Resets the array to its original configuration and return it. 50 | :rtype: List[int] 51 | """ 52 | return self.nums 53 | 54 | def shuffle(self): 55 | """ 56 | Returns a random shuffling of the array. 57 | :rtype: List[int] 58 | """ 59 | return random.sample(self.nums, len(self.nums)) 60 | 61 | 62 | 63 | # Your Solution object will be instantiated and called as such: 64 | # obj = Solution(nums) 65 | # param_1 = obj.reset() 66 | # param_2 = obj.shuffle() 67 | -------------------------------------------------------------------------------- /Array/SingleNumber.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a non-empty array of integers, every element appears twice except for one. Find that single one. 3 | 4 | Note: 5 | 6 | Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory? 7 | 8 | Example 1: 9 | 10 | Input: [2,2,1] 11 | Output: 1 12 | Example 2: 13 | 14 | Input: [4,1,2,1,2] 15 | Output: 4 16 | 17 | 18 | 给定一个非空数组,除了一个元素外,其余均出现两次。找出它。 19 | 20 | 需要在线性时间内,且不用额外空间。 21 | 22 | 用到了 missing number 的思路,利用异或的性质,相同的异或会抵消掉。 23 | 24 | 直接在原数组上操作,用了 i 变量,一个变量都不用要怎么写? 25 | Discuss里也没找到相关的。 26 | 27 | 测试地址: 28 | https://leetcode.com/problems/single-number/description/ 29 | 30 | """ 31 | 32 | class Solution(object): 33 | def singleNumber(self, nums): 34 | """ 35 | :type nums: List[int] 36 | :rtype: int 37 | """ 38 | 39 | for i in range(1, len(nums)): 40 | nums[i] = nums[i] ^ nums[i-1] 41 | 42 | return nums[-1] 43 | 44 | -------------------------------------------------------------------------------- /Array/SlidingWindowMaximum.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position. Return the max sliding window. 3 | 4 | Example: 5 | 6 | Input: nums = [1,3,-1,-3,5,3,6,7], and k = 3 7 | Output: [3,3,5,5,6,7] 8 | Explanation: 9 | 10 | Window position Max 11 | --------------- ----- 12 | [1 3 -1] -3 5 3 6 7 3 13 | 1 [3 -1 -3] 5 3 6 7 3 14 | 1 3 [-1 -3 5] 3 6 7 5 15 | 1 3 -1 [-3 5 3] 6 7 5 16 | 1 3 -1 -3 [5 3 6] 7 6 17 | 1 3 -1 -3 5 [3 6 7] 7 18 | Note: 19 | You may assume k is always valid, 1 ≤ k ≤ input array's size for non-empty array. 20 | 21 | Follow up: 22 | Could you solve it in linear time? 23 | 24 | 这个我的思路是: 25 | 26 | 1. 先把前 k 个数取出来,然后排序一组,不排序一组。 27 | 2. 排序的一组作为查找使用。 不排序的一组作为删除增加会用。 28 | 3. 这里也可以使用堆代替排序,红黑树应该最好不过了。 29 | 4. 这里使用排序过的列表是为了能够使用二分法,从而达到 log n 级别的查找和后续添加。 30 | 但同时因为即使在 log n级别查找到要添加删除的位置,进行列表的添加和删除仍然是一个 O(n) 级别的事情... 31 | 所以使用堆或者红黑树是最好的,添加和删除都是 log n 级别的。 32 | 33 | 5. sorted list 主要是进行获取最大与删除冗余,这里使用二分法来删除冗余。 34 | 6. unsorted list 用于知道要删除和添加的都是哪一个。 35 | 36 | beat 31% 176ms. 37 | 38 | 测试地址: 39 | https://leetcode.com/problems/sliding-window-maximum/description/ 40 | 41 | 42 | """ 43 | from collections import deque 44 | import bisect 45 | 46 | class Solution(object): 47 | def find_bi(self, nums, target): 48 | lo = 0 49 | hi = len(nums) 50 | 51 | while lo < hi: 52 | mid = (lo + hi) // 2 53 | 54 | if nums[mid] == target: 55 | return mid 56 | 57 | if nums[mid] < target: 58 | lo = mid + 1 59 | else: 60 | hi = mid 61 | 62 | def maxSlidingWindow(self, nums, k): 63 | """ 64 | :type nums: List[int] 65 | :type k: int 66 | :rtype: List[int] 67 | """ 68 | if not nums: 69 | return [] 70 | 71 | x = nums[:k] 72 | y = sorted(x) 73 | x = deque(x) 74 | 75 | maxes = max(x) 76 | result = [maxes] 77 | 78 | for i in nums[k:]: 79 | pop = x.popleft() 80 | x.append(i) 81 | 82 | index = self.find_bi(y, pop) 83 | y.pop(index) 84 | 85 | bisect.insort_left(y, i) 86 | 87 | result.append(y[-1]) 88 | return result 89 | -------------------------------------------------------------------------------- /Array/SortArrayByParity.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given an array A of non-negative integers, return an array consisting of all the even elements of A, followed by all the odd elements of A. 3 | 4 | You may return any answer array that satisfies this condition. 5 | 6 | 7 | 8 | Example 1: 9 | 10 | Input: [3,1,2,4] 11 | Output: [2,4,3,1] 12 | The outputs [4,2,3,1], [2,4,1,3], and [4,2,1,3] would also be accepted. 13 | 14 | 15 | Note: 16 | 17 | 1 <= A.length <= 5000 18 | 0 <= A[i] <= 5000 19 | 20 | 21 | 开胃菜,偶数放一堆,奇数放一堆。 22 | O(n). 23 | 24 | 测试链接: 25 | https://leetcode.com/contest/weekly-contest-102/problems/sort-array-by-parity/ 26 | 27 | contest. 28 | 29 | """ 30 | class Solution(object): 31 | def sortArrayByParity(self, A): 32 | """ 33 | :type A: List[int] 34 | :rtype: List[int] 35 | """ 36 | even = [] 37 | odd = [] 38 | for i in A: 39 | if i % 2 == 0: 40 | even.append(i) 41 | else: 42 | odd.append(i) 43 | 44 | return even + odd 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /Array/SortArrayByParityII.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given an array A of non-negative integers, half of the integers in A are odd, and half of the integers are even. 3 | 4 | Sort the array so that whenever A[i] is odd, i is odd; and whenever A[i] is even, i is even. 5 | 6 | You may return any answer array that satisfies this condition. 7 | 8 | 9 | 10 | Example 1: 11 | 12 | Input: [4,2,5,7] 13 | Output: [4,5,2,7] 14 | Explanation: [4,7,2,5], [2,5,4,7], [2,7,4,5] would also have been accepted. 15 | 16 | 17 | Note: 18 | 19 | 2 <= A.length <= 20000 20 | A.length % 2 == 0 21 | 0 <= A[i] <= 1000 22 | 23 | 根据单双排列,一个双一个单。 24 | 25 | """ 26 | class Solution(object): 27 | def sortArrayByParityII(self, A): 28 | """ 29 | :type A: List[int] 30 | :rtype: List[int] 31 | """ 32 | 33 | odd = [] 34 | even = [] 35 | 36 | for i in A: 37 | if i%2 == 0: 38 | even.append(i) 39 | else: 40 | odd.append(i) 41 | 42 | result = [] 43 | for j, k in zip(even, odd): 44 | result.append(j) 45 | result.append(k) 46 | return result 47 | -------------------------------------------------------------------------------- /Array/SortColors.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | Given an array with n objects colored red, white or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white and blue. 4 | 5 | Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively. 6 | 7 | Note: You are not suppose to use the library's sort function for this problem. 8 | 9 | Example: 10 | 11 | Input: [2,0,2,1,1,0] 12 | Output: [0,0,1,1,2,2] 13 | Follow up: 14 | 15 | A rather straight forward solution is a two-pass algorithm using counting sort. 16 | First, iterate the array counting number of 0's, 1's, and 2's, then overwrite array with total number of 0's, then 1's and followed by 2's. 17 | Could you come up with a one-pass algorithm using only constant space? 18 | 19 | 20 | 给一个放置了颜色的数组,里面包含三种颜色分别为 红 白 蓝,用 0 1 2 表示,它们在数组中是无序的,现在要把它们进行排序。 21 | 22 | 要求是: 23 | 原数组排序。 24 | 25 | 进阶条件是: 26 | 1. one-pass. 27 | 2. 使用常数空间。O(1)空间。 28 | 29 | 直接.sort排序是作弊行为。 30 | 31 | 进阶条件里给出一个直接的方法: 32 | 33 | 过一遍,分别记录出 0 1 2 的个数,然后按个数将它们分别替换。 34 | 35 | 这样做虽然是 O(1) 空间,不过不是 one-pass。 36 | 37 | 自己的思路: 38 | 39 | 由于只有三种要排序的,以1为中心点,那么出现0放到最左边即可,出现2放到最右边即可。 40 | 41 | 那么设置一个指针。从 0 开始,若为0则将它从原数组弹出,然后放到0的位置,若是2则放到末尾。若是1则不变。 42 | 43 | 1. 出现0和1的情况都将index向前推进1,2的话则不推进。 44 | 45 | 这样做是one-pass,O(1),符合进阶条件。缺点是 insert和pop都是 O(n) 时间复杂度的算法。使用deque会快一些,现在也可以。 46 | 47 | 48 | beat: 49 | 64% 50 | 51 | 测试地址: 52 | https://leetcode.com/problems/sort-colors/description/ 53 | 54 | """ 55 | class Solution(object): 56 | def sortColors(self, nums): 57 | """ 58 | :type nums: List[int] 59 | :rtype: void Do not return anything, modify nums in-place instead. 60 | """ 61 | 62 | index = 0 63 | times = 0 64 | length = len(nums) 65 | 66 | for i in range(length): 67 | if nums[index] == 0: 68 | x = nums.pop(index) 69 | nums.insert(0, x) 70 | index += 1 71 | elif nums[index] == 2: 72 | x = nums.pop(index) 73 | nums.append(x) 74 | else: 75 | index += 1 76 | -------------------------------------------------------------------------------- /Array/SubarraySumEqualsK.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given an array of integers and an integer k, you need to find the total number of continuous subarrays whose sum equals to k. 3 | 4 | Example 1: 5 | Input:nums = [1,1,1], k = 2 6 | Output: 2 7 | Note: 8 | The length of the array is in range [1, 20,000]. 9 | The range of numbers in the array is [-1000, 1000] and the range of the integer k is [-1e7, 1e7]. 10 | 11 | 12 | 思路: 13 | 1. 直接用了暴力的搜索法,TLE。 14 | 2. Discuss 里用的哈希 + 保留和的方式。 15 | 具体的是: 16 | pre 一直累加。 17 | 如果 pre - k 存在于保存的字典中,那么结果里加上这个次数即可。 18 | 19 | 这种方法可行。但暂时没搞明白具体的原理。 20 | 21 | 22 | 测试地址: 23 | https://leetcode.com/problems/subarray-sum-equals-k/description/ 24 | 25 | """ 26 | class Solution(object): 27 | def subarraySum(self, nums, k): 28 | """ 29 | :type nums: List[int] 30 | :type k: int 31 | :rtype: int 32 | """ 33 | dicts = {0:1} 34 | 35 | result = 0 36 | 37 | pre_sum = 0 38 | 39 | for i in nums: 40 | pre_sum += i 41 | 42 | result += dicts.get(pre_sum-k, 0) 43 | 44 | dicts[pre_sum] = dicts.get(pre_sum, 0) + 1 45 | 46 | return result 47 | -------------------------------------------------------------------------------- /Array/SurfaceAreaOf3DShapes.py: -------------------------------------------------------------------------------- 1 | """ 2 | Contest 1: 3 | 4 | On a N * N grid, we place some 1 * 1 * 1 cubes. 5 | 6 | Each value v = grid[i][j] represents a tower of v cubes placed on top of grid cell (i, j). 7 | 8 | Return the total surface area of the resulting shapes. 9 | 10 | 11 | 12 | Example 1: 13 | 14 | Input: [[2]] 15 | Output: 10 16 | Example 2: 17 | 18 | Input: [[1,2],[3,4]] 19 | Output: 34 20 | Example 3: 21 | 22 | Input: [[1,0],[0,2]] 23 | Output: 16 24 | Example 4: 25 | 26 | Input: [[1,1,1],[1,0,1],[1,1,1]] 27 | Output: 32 28 | Example 5: 29 | 30 | Input: [[2,2,2],[2,1,2],[2,2,2]] 31 | Output: 46 32 | 33 | 34 | Note: 35 | 36 | 1 <= N <= 50 37 | 0 <= grid[i][j] <= 50 38 | 39 | 40 | 测试地址: 41 | https://leetcode.com/contest/weekly-contest-99/problems/surface-area-of-3d-shapes/ 42 | 43 | 每个叠起来的正方体面数有 44 | 6 * x - 2 * (x-1)个。 45 | 确定好上下左右每个被覆盖的面减去即可。 46 | 47 | 48 | """ 49 | 50 | class Solution(object): 51 | def surfaceArea(self, grid): 52 | """ 53 | :type grid: List[List[int]] 54 | :rtype: int 55 | """ 56 | 57 | result = 0 58 | 59 | lengthY = len(grid) 60 | lengthX = len(grid[0]) 61 | 62 | for i in range(lengthY): 63 | for j in range(lengthX): 64 | if grid[i][j] != 0: 65 | temp_result = 6 * grid[i][j] - 2 * (grid[i][j] - 1) 66 | left = min(grid[i][j-1], grid[i][j]) if j-1 >= 0 else 0 67 | right = min(grid[i][j+1], grid[i][j]) if j+1 <= lengthX-1 else 0 68 | up = min(grid[i-1][j], grid[i][j]) if i-1 >= 0 else 0 69 | down = min(grid[i+1][j], grid[i][j]) if i+1 <= lengthY-1 else 0 70 | result += (temp_result - sum([left, right, up, down])) 71 | return result 72 | -------------------------------------------------------------------------------- /Array/ThirdMaximumNumbers.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a non-empty array of integers, return the third maximum number in this array. If it does not exist, return the maximum number. The time complexity must be in O(n). 3 | 4 | Example 1: 5 | Input: [3, 2, 1] 6 | 7 | Output: 1 8 | 9 | Explanation: The third maximum is 1. 10 | Example 2: 11 | Input: [1, 2] 12 | 13 | Output: 2 14 | 15 | Explanation: The third maximum does not exist, so the maximum (2) is returned instead. 16 | Example 3: 17 | Input: [2, 2, 3, 1] 18 | 19 | Output: 1 20 | 21 | Explanation: Note that the third maximum here means the third maximum distinct number. 22 | Both numbers with value 2 are both considered as second maximum. 23 | 24 | 返回第三大的数,如果不存在则返回最大的,重复的算一个。 25 | https://leetcode.com/problems/third-maximum-number/description/ 26 | 27 | 找到第 k 大个数一般的思路有: 28 | 1. 排序后放到数组中,排序算法使用归并和快排在理想情况下都是O(nlogn),归并比较稳定一些。之后的索引是O(1)。 29 | 这种的适合并不需要插入的情况,因为每次插入的时间复杂度为 O(n)。 30 | 31 | 2. 建立二叉搜索树,进阶的话红黑树或AVL树。 32 | 这种情况下搜索和插入在理想情况下都是O(logn)。 33 | 34 | 3. 就此题来说的O(n)思路: 35 | 建立三个变量,first,second,third,首先确保不是None,然后挨个放数据,最后输出结果。 36 | 37 | 这里直接用排序了。 38 | 39 | 40 | """ 41 | class Solution(object): 42 | def thirdMax(self, nums): 43 | """ 44 | :type nums: List[int] 45 | :rtype: int 46 | """ 47 | nums = set(nums) 48 | if len(nums) < 3: 49 | return max(nums) 50 | 51 | return sorted(nums, reverse=True)[2] 52 | -------------------------------------------------------------------------------- /Array/TopKFrequentElements.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a non-empty array of integers, return the k most frequent elements. 3 | 4 | Example 1: 5 | 6 | Input: nums = [1,1,1,2,2,3], k = 2 7 | Output: [1,2] 8 | Example 2: 9 | 10 | Input: nums = [1], k = 1 11 | Output: [1] 12 | Note: 13 | 14 | You may assume k is always valid, 1 ≤ k ≤ number of unique elements. 15 | Your algorithm's time complexity must be better than O(n log n), where n is the array's size. 16 | 17 | 思路: 18 | 首先是计算出每个数字出现的频率,之后排序频率,输出最高的k位。 19 | 20 | 字典(哈希表),sorted(排序)。 21 | 22 | beat 88% 23 | 24 | 测试用例: 25 | https://leetcode.com/problems/top-k-frequent-elements/description/ 26 | 27 | """ 28 | class Solution(object): 29 | def topKFrequent(self, nums, k): 30 | """ 31 | :type nums: List[int] 32 | :type k: int 33 | :rtype: List[int] 34 | """ 35 | 36 | nums_dict = {} 37 | 38 | for i in nums: 39 | try: 40 | nums_dict[i] += 1 41 | except KeyError: 42 | nums_dict[i] = 1 43 | 44 | return sorted(nums_dict, key=lambda x: nums_dict[x], reverse=True)[:k] 45 | -------------------------------------------------------------------------------- /Array/Triangle.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below. 3 | 4 | For example, given the following triangle 5 | 6 | [ 7 | [2], 8 | [3,4], 9 | [6,5,7], 10 | [4,1,8,3] 11 | ] 12 | The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11). 13 | 14 | Note: 15 | 16 | Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the triangle. 17 | 18 | 从底到顶,min(self+right)。 19 | 20 | O(1) 空间。 21 | 22 | beat 23 | 99% 24 | 25 | 测试地址: 26 | https://leetcode.com/problems/triangle/description/ 27 | 28 | 29 | 30 | """ 31 | class Solution(object): 32 | def minimumTotal(self, triangle): 33 | """ 34 | :type triangle: List[List[int]] 35 | :rtype: int 36 | """ 37 | 38 | for i in range(len(triangle)-2, -1, -1): 39 | length = len(triangle[i]) 40 | for j in range(length): 41 | 42 | _right = triangle[i+1][j+1] 43 | _self = triangle[i+1][j] 44 | mins = min(_right, _self) 45 | triangle[i][j] += mins 46 | return min(triangle[0]) 47 | -------------------------------------------------------------------------------- /Array/TwoSumIIAlreadySorted.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number. 3 | 4 | The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. 5 | 6 | Note: 7 | 8 | Your returned answers (both index1 and index2) are not zero-based. 9 | You may assume that each input would have exactly one solution and you may not use the same element twice. 10 | Example: 11 | 12 | Input: numbers = [2,7,11,15], target = 9 13 | Output: [1,2] 14 | Explanation: The sum of 2 and 7 is 9. Therefore index1 = 1, index2 = 2. 15 | 16 | Two Sum 已经排序后的输出,直接可以O(n): 17 | 18 | 解释传送门: 19 | TwoSum. 20 | ThreeSum. 21 | 22 | """ 23 | class Solution(object): 24 | def twoSum(self, sortedNums, target): 25 | """ 26 | :type numbers: List[int] 27 | :type target: int 28 | :rtype: List[int] 29 | """ 30 | 31 | start = 0 32 | end = len(sortedNums) - 1 33 | while start <= end: 34 | # print(nums[start] + nums[end]) 35 | if sortedNums[start] + sortedNums[end] == target: 36 | return start+1, end+1 37 | 38 | if sortedNums[start] + sortedNums[end] > target: 39 | end -= 1 40 | else: 41 | start += 1 42 | 43 | -------------------------------------------------------------------------------- /Array/WordSubsets.py: -------------------------------------------------------------------------------- 1 | """ 2 | We are given two arrays A and B of words. Each word is a string of lowercase letters. 3 | 4 | Now, say that word b is a subset of word a if every letter in b occurs in a, including multiplicity. For example, "wrr" is a subset of "warrior", but is not a subset of "world". 5 | 6 | Now say a word a from A is universal if for every b in B, b is a subset of a. 7 | 8 | Return a list of all universal words in A. You can return the words in any order. 9 | 10 | 11 | 12 | Example 1: 13 | 14 | Input: A = ["amazon","apple","facebook","google","leetcode"], B = ["e","o"] 15 | Output: ["facebook","google","leetcode"] 16 | Example 2: 17 | 18 | Input: A = ["amazon","apple","facebook","google","leetcode"], B = ["l","e"] 19 | Output: ["apple","google","leetcode"] 20 | Example 3: 21 | 22 | Input: A = ["amazon","apple","facebook","google","leetcode"], B = ["e","oo"] 23 | Output: ["facebook","google"] 24 | Example 4: 25 | 26 | Input: A = ["amazon","apple","facebook","google","leetcode"], B = ["lo","eo"] 27 | Output: ["google","leetcode"] 28 | Example 5: 29 | 30 | Input: A = ["amazon","apple","facebook","google","leetcode"], B = ["ec","oc","ceo"] 31 | Output: ["facebook","leetcode"] 32 | 33 | 34 | Note: 35 | 36 | 1 <= A.length, B.length <= 10000 37 | 1 <= A[i].length, B[i].length <= 10 38 | A[i] and B[i] consist only of lowercase letters. 39 | All words in A[i] are unique: there isn't i != j with A[i] == A[j]. 40 | 41 | 42 | 如果 B 中每一个元素出现的字符均在 A 中某一个元素中出现,则视为子单词,给一个A 和 B求子单词数量。 43 | 44 | 思路: 45 | 哈希 A, 46 | 哈希 B。 47 | 48 | B 哈希的时候要注意,有重复。 49 | 50 | 比如["ec","oc","ceo"] 51 | 只要有 c e o 各一次即可。不需要每个都判断一次。 52 | 53 | 测试地址: 54 | https://leetcode.com/problems/word-subsets/description/ 55 | 56 | 这个写法比较慢,前面的思路基本都是哈希。 57 | 58 | """ 59 | from collections import Counter 60 | 61 | class Solution(object): 62 | def wordSubsets(self, A, B): 63 | """ 64 | :type A: List[str] 65 | :type B: List[str] 66 | :rtype: List[str] 67 | """ 68 | dict_A = {i:Counter(i) for i in A} 69 | dict_B = {} 70 | 71 | for i in B: 72 | c = Counter(i) 73 | for j in c: 74 | if c.get(j) > dict_B.get(j, 0): 75 | dict_B[j] = c.get(j) 76 | 77 | result = [] 78 | 79 | for i in dict_A: 80 | for j in dict_B: 81 | if dict_B[j] > dict_A[i].get(j): 82 | break 83 | else: 84 | result.append(i) 85 | 86 | return result 87 | -------------------------------------------------------------------------------- /Array/max_increase_to_keep_city_skyline.py: -------------------------------------------------------------------------------- 1 | """ 2 | Example: 3 | Input: grid = [[3,0,8,4],[2,4,5,7],[9,2,6,3],[0,3,1,0]] 4 | Output: 35 5 | Explanation: 6 | The grid is: 7 | [ [3, 0, 8, 4], 8 | [2, 4, 5, 7], 9 | [9, 2, 6, 3], 10 | [0, 3, 1, 0] ] 11 | 12 | The skyline viewed from top or bottom is: [9, 4, 8, 7] 13 | The skyline viewed from left or right is: [8, 7, 9, 3] 14 | 15 | The grid after increasing the height of buildings without affecting skylines is: 16 | 17 | gridNew = [ [8, 4, 8, 7], 18 | [7, 4, 7, 7], 19 | [9, 4, 8, 7], 20 | [3, 3, 3, 3] ] 21 | 22 | 测试用例: 23 | https://leetcode.com/problems/max-increase-to-keep-city-skyline/description/ 24 | 25 | 整体思路: 26 | 获取出x和y轴的最大值,然后逐个遍历。 27 | 28 | 时间复杂度 O(mn)。 29 | 30 | """ 31 | 32 | class Solution(object): 33 | def maxIncreaseKeepingSkyline(self, grid): 34 | """ 35 | :type grid: List[List[int]] 36 | :rtype: int 37 | """ 38 | length = len(grid[0]) 39 | 40 | # Get line max. 41 | line_dict = {str(index):max(data) for index, data in enumerate(grid)} 42 | # Get column max. 43 | column_dict = {str(index):max((grid[index2][index] for index2 in range(len(grid)))) for index in range(length)} 44 | 45 | total_increases = 0 46 | 47 | for index, line in enumerate(grid): 48 | for index2, cell in enumerate(line): 49 | total_increases += min([line_dict[str(index)], column_dict[str(index2)]]) - cell 50 | 51 | return total_increases -------------------------------------------------------------------------------- /Array/twoSum.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @param {number} target 4 | * @return {number[]} 5 | */ 6 | // 简单的O(1)查找。 7 | var twoSum = function(nums, target) { 8 | let dicts = {} 9 | 10 | for (let [index, data] of nums.entries()) { 11 | dicts[data] ? dicts[data].push(index) : (dicts[data] = [index]) 12 | } 13 | 14 | 15 | for (let i of nums) { 16 | if (dicts[target - i]) { 17 | if (target-i === i) { 18 | if (dicts[i].length === 2) { 19 | return [dicts[i][0], dicts[i][1]] 20 | } else { 21 | continue 22 | } 23 | 24 | } 25 | 26 | return [dicts[i][0], dicts[target-i][0]] 27 | } 28 | } 29 | }; -------------------------------------------------------------------------------- /BFS/BinaryTreeLevelOrderTraversal.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level). 3 | 4 | For example: 5 | Given binary tree [3,9,20,null,null,15,7], 6 | 3 7 | / \ 8 | 9 20 9 | / \ 10 | 15 7 11 | return its level order traversal as: 12 | [ 13 | [3], 14 | [9,20], 15 | [15,7] 16 | ] 17 | 18 | 19 | 迭代出二叉树层级别的节点值。 20 | 直接用 BFS 即可. 21 | 22 | 下面是一个用双端列表的迭代方式实现。 23 | 24 | 用递归更好写一些。 25 | 26 | 测试地址: 27 | https://leetcode.com/problems/binary-tree-level-order-traversal/description/ 28 | 29 | beat 92% 28ms. 30 | 31 | """ 32 | 33 | # Definition for a binary tree node. 34 | # class TreeNode(object): 35 | # def __init__(self, x): 36 | # self.val = x 37 | # self.left = None 38 | # self.right = None 39 | 40 | from collections import deque 41 | 42 | class Solution(object): 43 | def levelOrder(self, root): 44 | """ 45 | :type root: TreeNode 46 | :rtype: List[List[int]] 47 | """ 48 | if not root: 49 | return [] 50 | 51 | result = [] 52 | 53 | temp = deque([root]) 54 | next_temp = deque() 55 | _result = [] 56 | while 1: 57 | if temp: 58 | node = temp.popleft() 59 | _result.append(node.val) 60 | if node.left: 61 | next_temp.append(node.left) 62 | 63 | if node.right: 64 | next_temp.append(node.right) 65 | else: 66 | result.append(_result) 67 | _result = [] 68 | temp = next_temp 69 | next_temp = deque() 70 | 71 | if not temp and not next_temp: 72 | if _result: 73 | result.append(_result) 74 | return result 75 | 76 | 77 | -------------------------------------------------------------------------------- /BFS/BinaryTreeLevelOrderTraversalII.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left to right, level by level from leaf to root). 3 | 4 | For example: 5 | Given binary tree [3,9,20,null,null,15,7], 6 | 3 7 | / \ 8 | 9 20 9 | / \ 10 | 15 7 11 | return its bottom-up level order traversal as: 12 | [ 13 | [15,7], 14 | [9,20], 15 | [3] 16 | ] 17 | 18 | 19 | 无难度..做了1的话直接把返回结果倒置即可。 20 | 21 | beat 94% 22 | 28ms 23 | 24 | 测试地址: 25 | https://leetcode.com/problems/binary-tree-level-order-traversal-ii/description/ 26 | 27 | """ 28 | # Definition for a binary tree node. 29 | # class TreeNode(object): 30 | # def __init__(self, x): 31 | # self.val = x 32 | # self.left = None 33 | # self.right = None 34 | 35 | from collections import deque 36 | 37 | class Solution(object): 38 | def levelOrderBottom(self, root): 39 | """ 40 | :type root: TreeNode 41 | :rtype: List[List[int]] 42 | """ 43 | if not root: 44 | return [] 45 | 46 | result = [] 47 | 48 | temp = deque([root]) 49 | next_temp = deque() 50 | _result = [] 51 | while 1: 52 | if temp: 53 | node = temp.popleft() 54 | _result.append(node.val) 55 | if node.left: 56 | next_temp.append(node.left) 57 | 58 | if node.right: 59 | next_temp.append(node.right) 60 | else: 61 | result.append(_result) 62 | _result = [] 63 | temp = next_temp 64 | next_temp = deque() 65 | 66 | if not temp and not next_temp: 67 | if _result: 68 | result.append(_result) 69 | return result[::-1] 70 | -------------------------------------------------------------------------------- /BFS/BinaryTreeZigzagLevelOrderTraversal.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between). 3 | 4 | For example: 5 | Given binary tree [3,9,20,null,null,15,7], 6 | 3 7 | / \ 8 | 9 20 9 | / \ 10 | 15 7 11 | return its zigzag level order traversal as: 12 | [ 13 | [3], 14 | [20,9], 15 | [15,7] 16 | ] 17 | 18 | 19 | 与 Binary tree order traversal 非常相似,不同的是这个是一层 左->右,一层 右->左。 20 | 21 | 同样的思路,加一个标记,若是RIGHT的层就倒过来。 22 | 23 | beat 99.94%. 24 | 24ms 25 | 26 | 测试地址: 27 | https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/description/ 28 | 29 | """ 30 | # Definition for a binary tree node. 31 | # class TreeNode(object): 32 | # def __init__(self, x): 33 | # self.val = x 34 | # self.left = None 35 | # self.right = None 36 | 37 | from collections import deque 38 | 39 | class Solution(object): 40 | def zigzagLevelOrder(self, root): 41 | """ 42 | :type root: TreeNode 43 | :rtype: List[List[int]] 44 | """ 45 | if not root: 46 | return [] 47 | 48 | result = [] 49 | 50 | temp = deque([root]) 51 | next_temp = deque() 52 | _result = [] 53 | LEFT = True 54 | RIGHT = False 55 | currentDirection = LEFT 56 | 57 | while 1: 58 | if temp: 59 | node = temp.popleft() 60 | _result.append(node.val) 61 | 62 | 63 | if node.left: 64 | next_temp.append(node.left) 65 | 66 | if node.right: 67 | next_temp.append(node.right) 68 | 69 | 70 | else: 71 | if currentDirection == LEFT: 72 | result.append(_result) 73 | currentDirection = RIGHT 74 | else: 75 | _result.reverse() 76 | result.append(_result) 77 | currentDirection = LEFT 78 | _result = [] 79 | temp = next_temp 80 | next_temp = deque() 81 | 82 | 83 | if not temp and not next_temp: 84 | if _result: 85 | if currentDirection == LEFT: 86 | result.append(_result) 87 | currentDirection = RIGHT 88 | else: 89 | _result.reverse() 90 | result.append(_result) 91 | 92 | return result 93 | -------------------------------------------------------------------------------- /BFS/FindBottomLeftTreeValue.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a binary tree, find the leftmost value in the last row of the tree. 3 | 4 | Example 1: 5 | Input: 6 | 7 | 2 8 | / \ 9 | 1 3 10 | 11 | Output: 12 | 1 13 | Example 2: 14 | Input: 15 | 16 | 1 17 | / \ 18 | 2 3 19 | / / \ 20 | 4 5 6 21 | / 22 | 7 23 | 24 | Output: 25 | 7 26 | 27 | 返回最底层最左边的一个节点的值。 28 | 29 | 思路: 30 | 31 | 使用广度优先算法: 32 | 1. 也可以用深度优先算法,不过广度优先的话所需代码更少,更好理解。 33 | 2. 广度优先: 34 | 1 遍历1 35 | / \ 36 | 2 3 遍历 2 3 37 | / / \ 38 | 4 5 6 遍历 4 5 6 39 | / 40 | 7 遍历 7 41 | 42 | 深度优先: 43 | 1 遍历1 44 | / \ 45 | 2 3 遍历2 -> 4 46 | / / \ 47 | 4 5 6 遍历 3 -> 5 -> 7,3 -> 6 48 | / 49 | 7 50 | 51 | 3. 广度优先运用在此处是以「层」为概念的,遍历完一层,再遍历一层。 52 | 由于是返回最左边,所以从右向左。 53 | 用两个列表,一个存放本层所有节点,一个存放本层所有节点的下层所有节点。 54 | 遍历完本层后合并存放下层的列表,如果没有节点则返回结果。 55 | 遍历本层时遵从 right to left. 有值就保存为结果。 56 | 57 | 测试用例: 58 | 59 | https://leetcode.com/problems/find-bottom-left-tree-value/description/ 60 | 61 | 40ms beat 74%. 62 | 63 | """ 64 | # Definition for a binary tree node. 65 | # class TreeNode(object): 66 | # def __init__(self, x): 67 | # self.val = x 68 | # self.left = None 69 | # self.right = None 70 | 71 | class Solution(object): 72 | def findBottomLeftValue(self, root): 73 | """ 74 | :type root: TreeNode 75 | :rtype: int 76 | """ 77 | waiting_for_access = [root] 78 | new_waiting_for_access = [] 79 | result = root.val 80 | 81 | while 1: 82 | while waiting_for_access: 83 | node = waiting_for_access.pop() 84 | 85 | if node.right: 86 | new_waiting_for_access.append(node.right) 87 | result = node.right.val 88 | if node.left: 89 | new_waiting_for_access.append(node.left) 90 | result = node.left.val 91 | if not new_waiting_for_access: 92 | return result 93 | waiting_for_access.extend(new_waiting_for_access[::-1]) 94 | new_waiting_for_access = [] 95 | -------------------------------------------------------------------------------- /BFS/MaximumDepthOfBinaryTree.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a binary tree, find its maximum depth. 3 | 4 | The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node. 5 | 6 | Note: A leaf is a node with no children. 7 | 8 | Example: 9 | 10 | Given binary tree [3,9,20,null,null,15,7], 11 | 12 | 3 13 | / \ 14 | 9 20 15 | / \ 16 | 15 7 17 | return its depth = 3. 18 | 19 | 找到二叉树的最大深度。 20 | 21 | 思路: 22 | 23 | 按层进行广度优先搜索即可。 24 | 25 | beat 99% 32ms. 26 | 27 | 测试地址: 28 | https://leetcode.com/problems/maximum-depth-of-binary-tree/description/ 29 | 30 | """ 31 | class Solution: 32 | 33 | def maxDepth(self, root: TreeNode) -> int: 34 | if root is None: 35 | return 0 36 | else: 37 | left_height = self.maxDepth(root.left) 38 | right_height = self.maxDepth(root.right) 39 | return max(left_height, right_height) + 1 40 | 41 | -------------------------------------------------------------------------------- /BFS/WordLadder.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence from beginWord to endWord, such that: 3 | 4 | Only one letter can be changed at a time. 5 | Each transformed word must exist in the word list. Note that beginWord is not a transformed word. 6 | Note: 7 | 8 | Return 0 if there is no such transformation sequence. 9 | All words have the same length. 10 | All words contain only lowercase alphabetic characters. 11 | You may assume no duplicates in the word list. 12 | You may assume beginWord and endWord are non-empty and are not the same. 13 | Example 1: 14 | 15 | Input: 16 | beginWord = "hit", 17 | endWord = "cog", 18 | wordList = ["hot","dot","dog","lot","log","cog"] 19 | 20 | Output: 5 21 | 22 | Explanation: As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog", 23 | return its length 5. 24 | Example 2: 25 | 26 | Input: 27 | beginWord = "hit" 28 | endWord = "cog" 29 | wordList = ["hot","dot","dog","lot","log"] 30 | 31 | Output: 0 32 | 33 | Explanation: The endWord "cog" is not in wordList, therefore no possible transformation. 34 | 35 | 36 | 这个BFS有点... 37 | 38 | 一开始的思路就是 BFS,写法不同。 39 | 40 | 一开始的写法是每次都从 wordList 里找单词,结果是有一个case跑不通。 41 | 42 | 后来实在没思路学习 Discuss 里的内容,Discuss 里的 BFS 是每一个都生成26个新的单词,然后判断是否在 wordList 中。 43 | 44 | 这种方法可以全部跑通... 45 | 46 | 可优化的点在于如何高效的找到存在于 _wordList 中可变换的值。 47 | 48 | beat 66% 49 | 50 | 测试地址: 51 | https://leetcode.com/problems/word-ladder/description/ 52 | 53 | """ 54 | from collections import deque 55 | class Solution(object): 56 | def ladderLength(self, beginWord, endWord, wordList): 57 | """ 58 | :type beginWord: str 59 | :type endWord: str 60 | :type wordList: List[str] 61 | :rtype: int 62 | """ 63 | 64 | if len(beginWord) == 1: 65 | return 2 66 | 67 | _wordList = set(wordList) 68 | 69 | result = deque([[beginWord, 1]]) 70 | 71 | while result: 72 | word, length = result.popleft() 73 | 74 | if word == endWord: 75 | return length 76 | 77 | _length = length + 1 78 | 79 | for i in range(len(word)): 80 | for c in 'qwertyuiopasdfghjklzxcvbnm': 81 | new = word[:i]+c+word[i+1:] 82 | 83 | if new in _wordList: 84 | _wordList.remove(new) 85 | result.append([new, _length]) 86 | 87 | return 0 88 | -------------------------------------------------------------------------------- /Backtracking/GenerateParentheses.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses. 3 | 4 | For example, given n = 3, a solution set is: 5 | 6 | [ 7 | "((()))", 8 | "(()())", 9 | "(())()", 10 | "()(())", 11 | "()()()" 12 | ] 13 | 14 | 生成有效的括号对。 15 | 16 | 关键字: 17 | 递归 18 | 19 | beat 20 | 100% 21 | 22 | 测试地址: 23 | https://leetcode.com/problems/generate-parentheses/description/ 24 | """ 25 | class Solution(object): 26 | def generateParenthesis(self, n): 27 | """ 28 | :type n: int 29 | :rtype: List[str] 30 | """ 31 | result = [] 32 | 33 | def _generateParenthesis(x, y, parenthesis): 34 | if not x and not y: 35 | result.append(parenthesis) 36 | return 37 | 38 | if y > x: 39 | _generateParenthesis(x, y-1, parenthesis=parenthesis+')') 40 | 41 | if x: 42 | _generateParenthesis(x-1, y, parenthesis=parenthesis+'(') 43 | 44 | _generateParenthesis(n-1, n, '(') 45 | 46 | return result 47 | -------------------------------------------------------------------------------- /Backtracking/subsets.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a set of distinct integers, nums, return all possible subsets (the power set). 3 | 4 | Note: The solution set must not contain duplicate subsets. 5 | 6 | Example: 7 | 8 | Input: nums = [1,2,3] 9 | Output: 10 | [ 11 | [3], 12 | [1], 13 | [2], 14 | [1,2,3], 15 | [1,3], 16 | [2,3], 17 | [1,2], 18 | [] 19 | ] 20 | 21 | 直接上递归,每条线都有两个决策: 22 | 1. 加上。 23 | 2. 不加。 24 | 25 | beat 96% 26 | 27 | 测试地址: 28 | https://leetcode.com/problems/subsets/description/ 29 | 30 | """ 31 | class Solution(object): 32 | def subsets(self, nums): 33 | """ 34 | :type nums: List[int] 35 | :rtype: List[List[int]] 36 | """ 37 | result = [] 38 | 39 | length = len(nums) 40 | 41 | def makeSubsets(index, current_subsets): 42 | if index == length: 43 | return 44 | 45 | result.append(current_subsets+[nums[index]]) 46 | 47 | makeSubsets(index+1, current_subsets+[nums[index]]) 48 | makeSubsets(index+1, current_subsets) 49 | 50 | 51 | makeSubsets(0, []) 52 | 53 | return result+[[]] 54 | -------------------------------------------------------------------------------- /DFS/PathSum.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum. 3 | 4 | Note: A leaf is a node with no children. 5 | 6 | Example: 7 | 8 | Given the below binary tree and sum = 22, 9 | 10 | 5 11 | / \ 12 | 4 8 13 | / / \ 14 | 11 13 4 15 | / \ \ 16 | 7 2 1 17 | return true, as there exist a root-to-leaf path 5->4->11->2 which sum is 22. 18 | 19 | 给一颗二叉树和一个值,找到从根到叶的所有路径的和中是否有一个与给定的值相当。 20 | 21 | 因为只要有一个就可以了,所以直接用深度优先,最差是 O(n)。 22 | 23 | 测试用例: 24 | https://leetcode.com/problems/path-sum/description/ 25 | 26 | """ 27 | # Definition for a binary tree node. 28 | # class TreeNode(object): 29 | # def __init__(self, x): 30 | # self.val = x 31 | # self.left = None 32 | # self.right = None 33 | 34 | class Solution(object): 35 | def hasPathSum(self, root, sum): 36 | """ 37 | :type root: TreeNode 38 | :type sum: int 39 | :rtype: bool 40 | """ 41 | if not root: 42 | return False 43 | 44 | def helper(prev, root, sum): 45 | if prev + root.val == sum: 46 | if not root.left and not root.right: 47 | return True 48 | 49 | if root.left: 50 | if helper(prev + root.val, root.left, sum): 51 | return True 52 | 53 | if root.right: 54 | if helper(prev + root.val, root.right, sum): 55 | return True 56 | 57 | return False 58 | 59 | return helper(0, root, sum) 60 | -------------------------------------------------------------------------------- /DP/BitwiseORsOfSubarray.py: -------------------------------------------------------------------------------- 1 | """ 2 | We have an array A of non-negative integers. 3 | 4 | For every (contiguous) subarray B = [A[i], A[i+1], ..., A[j]] (with i <= j), we take the bitwise OR of all the elements in B, obtaining a result A[i] | A[i+1] | ... | A[j]. 5 | 6 | Return the number of possible results. (Results that occur more than once are only counted once in the final answer.) 7 | 8 | 9 | 10 | Example 1: 11 | 12 | Input: [0] 13 | Output: 1 14 | Explanation: 15 | There is only one possible result: 0. 16 | Example 2: 17 | 18 | Input: [1,1,2] 19 | Output: 3 20 | Explanation: 21 | The possible subarrays are [1], [1], [2], [1, 1], [1, 2], [1, 1, 2]. 22 | These yield the results 1, 1, 2, 1, 3, 3. 23 | There are 3 unique values, so the answer is 3. 24 | Example 3: 25 | 26 | Input: [1,2,4] 27 | Output: 6 28 | Explanation: 29 | The possible results are 1, 2, 3, 4, 6, and 7. 30 | 31 | 32 | 对子数组进行或运算,最后结果是有多少个唯一的解。 33 | 思路是DP: 34 | 走的弯路: 35 | 一开始写的: 36 | [1, 1, 2, 2, 4] 37 | A[0] = {1} 38 | 基于A[0],判断是否在A[0]里,不在的话在添加,在的话就继承A[0]。 39 | A[1] = {1} 40 | A[2] = {1, 2, 3} 41 | A[3] = {1, 2 ,3} 42 | 运行到这里都没什么错误,因为就碰巧进行了一次相邻的或运算。 43 | A[4] = {1, 2, 3, 4, 5, 6, 7} 44 | 到了这里就有了错误,4不应该与这么多进行或运算。 45 | 46 | 这里就不知道怎么做了,如果要把上一次的结果也加到里面,怎么才能保证所进行的或运算不包含不相邻的两个点如: 47 | [1, 2, 4] 48 | 不会进行 [1,4]的运算。 49 | 50 | 重新的梳理应该是: 51 | [1] 52 | A[0] = {1} 53 | [ 1] [1, 1] 54 | A[1] = {1} 55 | 注意,这里与上一个进行或运算,但不把上一个也存到A[2]里面, 56 | [ 2] [1, 1, 2] [ 1, 2] 57 | A[2] = {2, 3} 58 | 基于上一个,但不会将上一个的结果加到本次里影响最终运算。 59 | --- 60 | 最终输出结果时,进行一次全部的set整理。 61 | 62 | 测试地址: 63 | https://leetcode.com/contest/weekly-contest-100/problems/bitwise-ors-of-subarrays/ 64 | 65 | Accepted. 66 | 67 | 68 | """ 69 | class Solution(object): 70 | def subarrayBitwiseORs(self, A): 71 | """ 72 | :type A: List[int] 73 | :rtype: int 74 | """ 75 | if not A: 76 | return 0 77 | 78 | dp = [{A[0]}] 79 | 80 | for i in range(1, len(A)): 81 | new = {A[i]} 82 | for j in dp[i-1]: 83 | new.add(j|A[i]) 84 | dp.append(new) 85 | 86 | return len(set.union(*dp)) 87 | 88 | -------------------------------------------------------------------------------- /DP/ClimbingStairs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} n 3 | * @return {number} 4 | */ 5 | var climbStairs = function(n) { 6 | let dp = [ 7 | 1, 8 | 2 9 | ] 10 | 11 | if (n <= 2) { 12 | return dp[n-1] 13 | } 14 | 15 | for (let i=2;i 0 57 | for i in range(1, len(S)): 58 | if S[i] == '1': 59 | x.append(x[-1]+1) 60 | else: 61 | x.append(x[-1]) 62 | 63 | # right to left 64 | # 0 -> 1 65 | S = S[::-1] 66 | y = [0] if S[0] == '1' else [1] 67 | for i in range(1, len(S)): 68 | if S[i] == '0': 69 | y.append(y[-1]+1) 70 | else: 71 | y.append(y[-1]) 72 | 73 | y.reverse() 74 | 75 | return min([i+j for i,j in zip(x,y)]) - 1 76 | 77 | -------------------------------------------------------------------------------- /DP/HouseRobber.py: -------------------------------------------------------------------------------- 1 | """ 2 | You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night. 3 | 4 | Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police. 5 | 6 | Example 1: 7 | 8 | Input: [1,2,3,1] 9 | Output: 4 10 | Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3). 11 | Total amount you can rob = 1 + 3 = 4. 12 | Example 2: 13 | 14 | Input: [2,7,9,3,1] 15 | Output: 12 16 | Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1). 17 | Total amount you can rob = 2 + 9 + 1 = 12. 18 | 19 | 你是专业强盗计划偷钱。每个房子都有钱,不能连续偷,否则会触发警报,计划能偷的最多的钱,要偷哪些房子。 20 | 21 | 用Dp的子问题思路: 22 | 不能连续的偷: 23 | 24 | 1 和 2只能偷这两个,没得选择。 25 | 3 能顺带偷1。 26 | 4 则需要在 1 和 2 中抉择。 27 | 5 则需要在 2 和 3 中抉择。 28 | 所以 29 | 30 | 子问题则是每个点能偷到的最大数。 31 | 32 | 初始化3个 33 | 例 34 | [2,7,9,3,1] 35 | dp = [2,7,11(9+2)] 36 | max(3+7, 3+2) 37 | dp = [2,7,11(9+2),10(3+7)] 38 | max(1+11,1+7) 39 | dp = [2,7,11(9+2),10(3+7),12(1+11)] 40 | 41 | 可以中途记录,也可以最后max,当然中途记录的话效率的最高的。 42 | 43 | 就这个测试来说max也没差。 44 | 45 | 测试地址: 46 | https://leetcode.com/problems/house-robber/description/ 47 | 48 | beat 99% 20ms 49 | 50 | """ 51 | class Solution(object): 52 | def rob(self, nums): 53 | """ 54 | :type nums: List[int] 55 | :rtype: int 56 | """ 57 | if not nums: 58 | return 0 59 | 60 | if len(nums) <= 2: 61 | return max(nums) 62 | 63 | robber = [nums[0], nums[1], nums[2] + nums[0]] 64 | 65 | for i in range(3, len(nums)): 66 | robber.append(max(nums[i] + robber[i-2], nums[i] + robber[i-3])) 67 | 68 | return max(robber) 69 | -------------------------------------------------------------------------------- /DP/HouseRobberII.py: -------------------------------------------------------------------------------- 1 | """ 2 | You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed. All houses at this place are arranged in a circle. That means the first house is the neighbor of the last one. Meanwhile, adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night. 3 | 4 | Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police. 5 | 6 | Example 1: 7 | 8 | Input: [2,3,2] 9 | Output: 3 10 | Explanation: You cannot rob house 1 (money = 2) and then rob house 3 (money = 2), 11 | because they are adjacent houses. 12 | Example 2: 13 | 14 | Input: [1,2,3,1] 15 | Output: 4 16 | Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3). 17 | Total amount you can rob = 1 + 3 = 4. 18 | 19 | 20 | 与1不同的是这个首尾相连,是个环。 21 | 22 | 1 23 | 3 2 24 | 1 25 | 26 | 只有3户人家时只能抢一户。 27 | 只有4户人家时能抢其中的两户。 28 | 29 | 5户以上时可以应用1时的规则,不过这次不要把最后一户算进来。 30 | 进行两次,一次以 0 为首,第二次以 -1 为首。 31 | 32 | 两次即可包含所有结果了。 33 | 34 | 效率 O(n)。 35 | 36 | beat 100% 20ms 37 | 38 | 测试地址: 39 | https://leetcode.com/problems/house-robber-ii/description/ 40 | 41 | 42 | 43 | """ 44 | class Solution(object): 45 | def rob(self, nums): 46 | """ 47 | :type nums: List[int] 48 | :rtype: int 49 | """ 50 | if not nums: 51 | return 0 52 | 53 | if len(nums) <= 3: 54 | return max(nums) 55 | 56 | if len(nums) <= 4: 57 | return max(max(nums), nums[1]+nums[-1], nums[2]+nums[0]) 58 | 59 | robber = [nums[0], nums[1], nums[2]+nums[0]] 60 | 61 | for i in range(3, len(nums)-1): 62 | robber.append(max(nums[i] + robber[i-2], nums[i] + robber[i-3])) 63 | 64 | maxes = max(robber) 65 | 66 | nums = [nums[-1]] + nums 67 | nums.pop() 68 | 69 | robber = [nums[0], nums[1], nums[2]+nums[0]] 70 | 71 | for i in range(3, len(nums)-1): 72 | robber.append(max(nums[i] + robber[i-2], nums[i] + robber[i-3])) 73 | 74 | 75 | return max(robber+[maxes]) 76 | -------------------------------------------------------------------------------- /DP/LongestContinuousIncreasingSubsequence.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given an unsorted array of integers, find the length of longest continuous increasing subsequence (subarray). 3 | 4 | Example 1: 5 | Input: [1,3,5,4,7] 6 | Output: 3 7 | Explanation: The longest continuous increasing subsequence is [1,3,5], its length is 3. 8 | Even though [1,3,5,7] is also an increasing subsequence, it's not a continuous one where 5 and 7 are separated by 4. 9 | Example 2: 10 | Input: [2,2,2,2,2] 11 | Output: 1 12 | Explanation: The longest continuous increasing subsequence is [2], its length is 1. 13 | Note: Length of the array will not exceed 10,000. 14 | 15 | easy: 16 | Dp, 子问题是前一个点所累积的数量。 17 | 18 | 测试地址: 19 | https://leetcode.com/problems/longest-continuous-increasing-subsequence/description/ 20 | 21 | 22 | 今日的零启动算法。 23 | """ 24 | class Solution(object): 25 | def findLengthOfLCIS(self, nums): 26 | """ 27 | :type nums: List[int] 28 | :rtype: int 29 | """ 30 | if not nums: 31 | return 0 32 | 33 | dp = [1] 34 | 35 | for i in range(1, len(nums)): 36 | if nums[i] > nums[i-1]: 37 | dp.append(dp[i-1]+1) 38 | else: 39 | dp.append(1) 40 | return max(dp) 41 | 42 | 43 | -------------------------------------------------------------------------------- /DP/MinCostClimbingStairs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} cost 3 | * @return {number} 4 | * 5 | * 6 | * 7 | * 数组的每个下标作为一个阶梯,第 i 个阶梯对应着一个非负数的体力花费值 cost[i](下标从 0 开始)。 8 | 9 | 每当你爬上一个阶梯你都要花费对应的体力值,一旦支付了相应的体力值,你就可以选择向上爬一个阶梯或者爬两个阶梯。 10 | 11 | 请你找出达到楼层顶部的最低花费。在开始时,你可以选择从下标为 0 或 1 的元素作为初始阶梯。 12 | 13 |   14 | 15 | 示例 1: 16 | 17 | 输入:cost = [10, 15, 20] 18 | 输出:15 19 | 解释:最低花费是从 cost[1] 开始,然后走两步即可到阶梯顶,一共花费 15 。 20 |  示例 2: 21 | 22 | 输入:cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1] 23 | 输出:6 24 | 解释:最低花费方式是从 cost[0] 开始,逐个经过那些 1 ,跳过 cost[3] ,一共花费 6 。 25 |   26 | 27 | 提示: 28 | 29 | cost 的长度范围是 [2, 1000]。 30 | cost[i] 将会是一个整型数据,范围为 [0, 999] 。 31 | 32 | */ 33 | var minCostClimbingStairs = function(cost) { 34 | let dp = [ 35 | cost[0], 36 | cost[1] 37 | ] 38 | 39 | if (cost.length === 2) { 40 | return cost[0] < cost[1] ? cost[0] : cost[1] 41 | } 42 | 43 | for (let i=2;i target: 94 | return False 95 | 96 | if cards[0][0] < target: 97 | # init = target - cards[0][0] 98 | dp = {-1: [target]} 99 | 100 | for i, d in enumerate(cards): 101 | temp = dp[i-1].copy() 102 | for x in dp[i-1]: 103 | if x - d[0] == 0: 104 | return True 105 | 106 | if x - d[0] > 0: 107 | temp.append(x - d[0]) 108 | dp[i] = temp 109 | 110 | return False 111 | 112 | 113 | print(maxCardsScope(test2)) 114 | -------------------------------------------------------------------------------- /DP/ReversePairs.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given an array nums, we call (i, j) an important reverse pair if i < j and nums[i] > 2*nums[j]. 3 | 4 | You need to return the number of important reverse pairs in the given array. 5 | 6 | Example1: 7 | 8 | Input: [1,3,2,3,1] 9 | Output: 2 10 | Example2: 11 | 12 | Input: [2,4,3,5,1] 13 | Output: 3 14 | Note: 15 | 1. The length of the given array will not exceed 50,000. 16 | 2. All the numbers in the input array are in the range of 32-bit integer. 17 | 18 | 如果索引 i < j 并且 nums[i] > 2 * nums[j],那么就称它为牛波翻转对。 19 | 20 | 给一个数组,返回里面有几个牛波翻转对。 21 | 22 | 思路: 23 | 24 | 一个 Dp 思路,从后向前,解出每一个点若要达成牛波翻转对所需要的值是多少。 25 | 26 | 比如 1 , 要达成需要 2 以上。 27 | 3, 则需要 6 以上。 28 | 29 | 将这些放到一个列表里,然后来新值之后判断若将它插入这个列表的话所插入的位置(下标), 30 | 这个位置即为已经判断过的能与它达成牛波翻转对的位置。 31 | 32 | 用二分法可以达成 n log n 的查询,美中不足的是列表的插入仍需要 O(n)。 33 | 34 | beat 17% 35 | 36 | 测试地址: 37 | https://leetcode.com/problems/reverse-pairs/description/ 38 | 39 | 40 | """ 41 | import bisect 42 | 43 | class Solution(object): 44 | def reversePairs(self, nums): 45 | """ 46 | :type nums: List[int] 47 | :rtype: int 48 | """ 49 | _base = [] 50 | 51 | result = 0 52 | 53 | for i in range(len(nums)-1,-1,-1): 54 | index = bisect.bisect_left(_base, nums[i]) 55 | result += index 56 | bisect.insort_right(_base, nums[i]*2) 57 | 58 | return result 59 | -------------------------------------------------------------------------------- /DP/SubarrayProductLessThanK.py: -------------------------------------------------------------------------------- 1 | """ 2 | Your are given an array of positive integers nums. 3 | 4 | Count and print the number of (contiguous) subarrays where the product of all the elements in the subarray is less than k. 5 | 6 | Example 1: 7 | Input: nums = [10, 5, 2, 6], k = 100 8 | Output: 8 9 | Explanation: The 8 subarrays that have product less than 100 are: [10], [5], [2], [6], [10, 5], [5, 2], [2, 6], [5, 2, 6]. 10 | Note that [10, 5, 2] is not included as the product of 100 is not strictly less than k. 11 | Note: 12 | 13 | 0 < nums.length <= 50000. 14 | 0 < nums[i] < 1000. 15 | 0 <= k < 10^6. 16 | 17 | 思路 Dp,处理下 1 即可。 不考虑 0,nums[i] 不会为 0。 18 | 19 | beat 19% 20 | 21 | 测试地址: 22 | https://leetcode.com/problems/subarray-product-less-than-k/description/ 23 | 24 | 可剪枝优化。 25 | """ 26 | class Solution(object): 27 | def numSubarrayProductLessThanK(self, nums, k): 28 | """ 29 | :type nums: List[int] 30 | :type k: int 31 | :rtype: int 32 | """ 33 | 34 | dp = [] 35 | result = 0 36 | start = 0 37 | for i in range(len(nums)): 38 | if nums[i] < k: 39 | result += 1 40 | dp = [nums[i]] 41 | start = i 42 | break 43 | 44 | for i in range(start+1, len(nums)): 45 | if nums[i] == 1 and nums[i] < k: 46 | dp.append(1) 47 | result += len(dp) 48 | continue 49 | 50 | new = [] 51 | 52 | if nums[i] < k: 53 | result += 1 54 | new.append(nums[i]) 55 | 56 | 57 | for j in dp: 58 | if j * nums[i] < k: 59 | result += 1 60 | new.append(j * nums[i]) 61 | 62 | dp = new 63 | return result 64 | -------------------------------------------------------------------------------- /DP/UniquePath.py: -------------------------------------------------------------------------------- 1 | """ 2 | A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). 3 | 4 | The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below). 5 | 6 | How many possible unique paths are there? 7 | 8 | 9 | Above is a 7 x 3 grid. How many possible unique paths are there? 10 | 11 | Note: m and n will be at most 100. 12 | 13 | Example 1: 14 | 15 | Input: m = 3, n = 2 16 | Output: 3 17 | Explanation: 18 | From the top-left corner, there are a total of 3 ways to reach the bottom-right corner: 19 | 1. Right -> Right -> Down 20 | 2. Right -> Down -> Right 21 | 3. Down -> Right -> Right 22 | Example 2: 23 | 24 | Input: m = 7, n = 3 25 | Output: 28 26 | 27 | 28 | 思路: 29 | 直接DP。子问题: 30 | 经过当前点的路径一共有多少条。 31 | 由于只能向右或者向下且不可返回,每一个点的路径可由左和右的点的路径数相加得来。 32 | 边界: 33 | 无则为0。 34 | 35 | 1 1 1 36 | 1 2 3 37 | 38 | 初始化一个 x * x 的列表,并将0, 0设置为1。 39 | 之后将每个点的路径数等于左+上。 40 | 效率为O(mn)。 41 | 42 | 2 43 | 数学方法暂且跳过。 44 | 45 | 测试地址: 46 | https://leetcode.com/problems/unique-paths/description/ 47 | 48 | beat 100%. 49 | 50 | """ 51 | 52 | 53 | class Solution(object): 54 | def uniquePaths(self, m, n): 55 | """ 56 | :type m: int 57 | :type n: int 58 | :rtype: int 59 | """ 60 | 61 | _map = [[0 for _ in range(m)] for _ in range(n)] 62 | # _map[0][0] = 1 63 | 64 | for i in range(n): 65 | for j in range(m): 66 | x = _map[i-1][j] if i - 1 >= 0 else 0 67 | y = _map[i][j-1] if j - 1 >= 0 else 0 68 | 69 | if x + y == 0: 70 | _map[i][j] = 1 71 | else: 72 | _map[i][j] = x + y 73 | 74 | return _map[n-1][m-1] 75 | 76 | -------------------------------------------------------------------------------- /DP/WordBreak.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine if s can be segmented into a space-separated sequence of one or more dictionary words. 3 | 4 | Note: 5 | 6 | The same word in the dictionary may be reused multiple times in the segmentation. 7 | You may assume the dictionary does not contain duplicate words. 8 | Example 1: 9 | 10 | Input: s = "leetcode", wordDict = ["leet", "code"] 11 | Output: true 12 | Explanation: Return true because "leetcode" can be segmented as "leet code". 13 | Example 2: 14 | 15 | Input: s = "applepenapple", wordDict = ["apple", "pen"] 16 | Output: true 17 | Explanation: Return true because "applepenapple" can be segmented as "apple pen apple". 18 | Note that you are allowed to reuse a dictionary word. 19 | Example 3: 20 | 21 | Input: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"] 22 | Output: false 23 | 24 | 给一个非空字符串和一个包含单词的非空字典。判断是否能用字典里的单词组合成给定的字符串。 25 | 26 | 思路: 27 | Dp: 28 | 从0开始,若此分隔存在于给定字典中,则可以断开。 29 | 30 | s = "leetcode", wordDict = ["leet", "code"] 31 | 32 | leetcode 33 | l e e t c o d e 34 | T F F F F F F F F 35 | 36 | leet 37 | s[0:0+4] in wordDict 38 | 39 | s[0+4] = True 40 | 41 | l e e t c o d e 42 | T F F F T F F F F 43 | 当搜索到这里时会再次进行重复的搜索。 44 | 45 | 46 | --- 47 | emmm, 写法待改进。 48 | 这个写法思路一样,不过效率会低。 49 | 50 | beat 3%. 51 | 52 | 测试地址: 53 | https://leetcode.com/problems/word-break/description/ 54 | 55 | """ 56 | class Solution(object): 57 | def wordBreak(self, s, wordDict): 58 | """ 59 | :type s: str 60 | :type wordDict: List[str] 61 | :rtype: bool 62 | """ 63 | 64 | dp = [True] + [False] * len(s) 65 | 66 | for i in range(len(s)): 67 | for j in range(i+1): 68 | if dp[j] == True: 69 | for x in wordDict: 70 | if x == s[j:j+len(x)]: 71 | dp[j+len(x)] = True 72 | 73 | return dp[-1] 74 | -------------------------------------------------------------------------------- /DP/longesSubsequence.py: -------------------------------------------------------------------------------- 1 | """ 2 | 整体思路是使用 DP。 3 | DP 的核心是找到子问题。 4 | 该问题的子问题当前从此点向前与哪些组合可以形成最长的子串。 5 | 但与初级的抛硬币不同(要判断的只有3个),判断的点为从此点向前的所有点(子问题)。 6 | 时间复杂度 O(n**2)。 7 | 测试用例: 8 | https://leetcode.com/problems/longest-increasing-subsequence/description/ 9 | 10 | 另:有一个 O(nlogn) 的算法,暂未研究。 11 | 12 | """ 13 | 14 | """ 15 | 牛刀小试,DP 抛硬币,1 3 5 最少凑11。 16 | def coins(num): 17 | 18 | coins_result = {'0': 0} 19 | for i in range(1, num+1): 20 | coins_5, coins_3, coins_1 = float('inf'), float('inf'), float('inf') 21 | if i-5 >= 0: 22 | coins_5 = coins_result[str(i-5)] + 1 23 | if i-3 >= 0: 24 | coins_3 = coins_result[str(i-3)] + 1 25 | if i-1 >= 0: 26 | coins_1 = coins_result[str(i-1)] + 1 27 | 28 | coins_result[str(i)] = min([coins_5, coins_3, coins_1]) 29 | print(coins_result) 30 | print(coins_result[str(num)]) 31 | 32 | # coins(100) 33 | """ 34 | 35 | class Solution(object): 36 | def lengthOfLIS(self, strings): 37 | """ 38 | :type nums: List[int] 39 | :rtype: int 40 | """ 41 | if not strings: 42 | return 0 43 | long_ss = [] 44 | 45 | for i in strings: 46 | if not long_ss: 47 | long_ss.append(([i], 1)) 48 | continue 49 | maxs = max(long_ss, key=lambda x: x[0][-1] < i and x[1]+1) 50 | if maxs[0][-1] >= i: 51 | long_ss.append(([i], 1)) 52 | else: 53 | long_ss.append((maxs[0]+[i], maxs[1]+1)) 54 | 55 | return max(long_ss, key=lambda x: x[1])[1] -------------------------------------------------------------------------------- /Heap/MergeKSortedLists.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val, next) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.next = (next===undefined ? null : next) 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode[]} lists 10 | * @return {ListNode} 11 | */ 12 | 13 | 14 | var mergeKLists = function(lists) { 15 | // 这个思路是打散之后又重新生成整个ListNode。 16 | // 参考价值不大。 17 | if (!lists.length) { 18 | return null 19 | } 20 | 21 | let newLists = [] 22 | 23 | for (let i of lists) { 24 | let l = [] 25 | while (i && i.next) { 26 | l.push(i.val) 27 | i = i.next 28 | } 29 | 30 | i && l.push(i.val) 31 | newLists.push(l) 32 | } 33 | 34 | 35 | let x = newLists.flat().sort((a,b) => a-b) 36 | if (!x.length) { 37 | return null 38 | } 39 | let resultNode = new ListNode(x[0]) 40 | let indexNode = resultNode 41 | x.shift() 42 | while (x.length) { 43 | indexNode.next = new ListNode(x[0]) 44 | x.shift() 45 | indexNode = indexNode.next 46 | } 47 | 48 | return resultNode 49 | }; -------------------------------------------------------------------------------- /Heap/MergeKSortedLists.py: -------------------------------------------------------------------------------- 1 | """ 2 | Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. 3 | 4 | Example: 5 | 6 | Input: 7 | [ 8 | 1->4->5, 9 | 1->3->4, 10 | 2->6 11 | ] 12 | Output: 1->1->2->3->4->4->5->6 13 | 14 | 合并 k 个有序链表。 15 | 16 | 用了最小堆: 17 | 18 | 把所有的链表节点入堆,然后出堆形成新的链表即可。 19 | 20 | 依然依靠了内置模块,待自己书写堆。 21 | 22 | 测试地址: 23 | https://leetcode.com/problems/merge-k-sorted-lists/description/ 24 | 25 | """ 26 | # Definition for singly-linked list. 27 | # class ListNode(object): 28 | # def __init__(self, x): 29 | # self.val = x 30 | # self.next = None 31 | import heapq 32 | 33 | class Solution(object): 34 | def mergeKLists(self, lists): 35 | """ 36 | :type lists: List[ListNode] 37 | :rtype: ListNode 38 | """ 39 | a = [] 40 | 41 | heapq.heapify(a) 42 | 43 | for i in lists: 44 | while i: 45 | heapq.heappush(a, i.val) 46 | i = i.next 47 | if not a: 48 | return None 49 | 50 | root = ListNode(heapq.heappop(a)) 51 | head = root 52 | 53 | while a: 54 | root.next = ListNode(heapq.heappop(a)) 55 | root = root.next 56 | 57 | return head 58 | 59 | -------------------------------------------------------------------------------- /Number/DivideTwoIntegers.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given two integers dividend and divisor, divide two integers without using multiplication, division and mod operator. 3 | 4 | Return the quotient after dividing dividend by divisor. 5 | 6 | The integer division should truncate toward zero. 7 | 8 | Example 1: 9 | 10 | Input: dividend = 10, divisor = 3 11 | Output: 3 12 | Example 2: 13 | 14 | Input: dividend = 7, divisor = -3 15 | Output: -2 16 | Note: 17 | 18 | Both dividend and divisor will be 32-bit signed integers. 19 | The divisor will never be 0. 20 | Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [−231, 231 − 1]. For the purpose of this problem, assume that your function returns 231 − 1 when the division result overflows. 21 | 22 | 除以某数,其结果要尽可能趋向0的,且为整数。 23 | 24 | 直接用Python 中的地板除 // 即可。 25 | 26 | 判断两个数的符号是否相同和处理 2**31-1 和 -2**31 即可。 27 | 28 | 测试链接: 29 | https://leetcode.com/problems/divide-two-integers/description/ 30 | 31 | beat 100% 28ms. 32 | 33 | 这个题没什么意思...应该作为第二天的零启动任务来做,但已经做了,换一个零启动任务吧。 34 | 35 | """ 36 | class Solution(object): 37 | def divide(self, dividend, divisor): 38 | """ 39 | :type dividend: int 40 | :type divisor: int 41 | :rtype: int 42 | """ 43 | 44 | x = abs(dividend) // abs(divisor) 45 | if (dividend < 0 and divisor > 0) or (dividend > 0 and divisor < 0): 46 | 47 | if -x < -2**31: 48 | return -2**31 49 | return -x 50 | 51 | if x > 2**31-1: 52 | return 2**31-1 53 | return x 54 | 55 | -------------------------------------------------------------------------------- /Number/Sqrt(x).py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | Implement int sqrt(int x). 4 | 5 | Compute and return the square root of x, where x is guaranteed to be a non-negative integer. 6 | 7 | Since the return type is an integer, the decimal digits are truncated and only the integer part of the result is returned. 8 | 9 | Example 1: 10 | 11 | Input: 4 12 | Output: 2 13 | Example 2: 14 | 15 | Input: 8 16 | Output: 2 17 | Explanation: The square root of 8 is 2.82842..., and since 18 | the decimal part is truncated, 2 is returned. 19 | 20 | 顺手一写,直接用库... 21 | 22 | 测试地址: 23 | https://leetcode.com/problems/sqrtx/description/ 24 | 25 | """ 26 | import math 27 | 28 | class Solution(object): 29 | def mySqrt(self, x): 30 | """ 31 | :type x: int 32 | :rtype: int 33 | """ 34 | return int(math.sqrt(x)) 35 | -------------------------------------------------------------------------------- /Sorted/WiggleSortII.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given an unsorted array nums, reorder it such that nums[0] < nums[1] > nums[2] < nums[3].... 3 | 4 | Example 1: 5 | 6 | Input: nums = [1, 5, 1, 1, 6, 4] 7 | Output: One possible answer is [1, 4, 1, 5, 1, 6]. 8 | Example 2: 9 | 10 | Input: nums = [1, 3, 2, 2, 3, 1] 11 | Output: One possible answer is [2, 3, 1, 3, 1, 2]. 12 | Note: 13 | You may assume all input has valid answer. 14 | 15 | Follow Up: 16 | Can you do it in O(n) time and/or in-place with O(1) extra space? 17 | 18 | 1 锁了,暂不能做。 19 | 20 | II 的话规则: 21 | 单数位 大于 双数位。 22 | 23 | 思路: 24 | 25 | 一开始的话想到的是排序后,取中间,然后后半部分按从大到小铺在单数位上。 26 | 前半部分按从大到小从末尾的双数位开始向前铺。 27 | 28 | 这个思路一开始是可以的,不过忽略了相等的部分,因为有可能铺的时候相遇。所以注意下,相等的等上面的过程铺完之后,用于补剩下的部分。 29 | 30 | 进阶要求是: 31 | O(n) 时间,O(1) 空间。 32 | 33 | 排序的话 O(n log n),不符合要求。 34 | 35 | 这个思路的关键点是找到中位数,但怎么在 O(n) 时间 O(1) 空间找到中位数呢? 36 | 37 | 下面是我的思考,没有最终实现。 38 | 39 | 1. 先找到里面最小的元素并获取出总长度。 40 | 2. 过一遍,找出 总长度 // 2 个比它大的元素,顺便记录出这里面的最大值。 41 | 3. 再过一遍,找出 比 2. 中最大值大的 元素。 42 | 4. 再找出比它大的元素个数 - 总长度 // 2 43 | 5. 若刚好有 总长度 // 2 个那么它就是中位数,否则它就是第 k(比它大的元素个数 - 总长度 // 2) 大个元素。 44 | 6. 缩小了范围。重复步骤... 45 | 46 | 时间复杂度非常依赖运气... 47 | 48 | 下面直接用了排序,没有达成进阶条件,待改进。 49 | 50 | beat 51 | 68% 52 | 53 | 测试地址: 54 | https://leetcode.com/problems/wiggle-sort-ii/description/ 55 | 56 | 57 | """ 58 | class Solution(object): 59 | def wiggleSort(self, nums): 60 | """ 61 | :type nums: List[int] 62 | :rtype: void Do not return anything, modify nums in-place instead. 63 | """ 64 | 65 | nums.sort() 66 | middle = nums[len(nums) // 2] 67 | larger = [i for i in nums[len(nums)//2:] if i != middle] 68 | smaller = [i for i in nums[:len(nums)//2] if i != middle] 69 | equal = [i for i in nums if i == middle] 70 | 71 | larger.reverse() 72 | smaller.reverse() 73 | length = len(nums) 74 | odd = 1 75 | even = length - 1 if (length-1) % 2 == 0 else length - 2 76 | 77 | for i in larger: 78 | # try: 79 | nums[odd] = i 80 | 81 | odd += 2 82 | 83 | for i in smaller: 84 | nums[even] = i 85 | 86 | even -= 2 87 | 88 | while even >= 0: 89 | nums[even] = equal.pop() 90 | even -= 2 91 | 92 | while odd < length: 93 | nums[odd] = equal.pop() 94 | odd += 2 95 | -------------------------------------------------------------------------------- /Stack/GetMinStack.py: -------------------------------------------------------------------------------- 1 | """ 2 | 设计一个可以 Get Min的栈结构。 3 | 4 | 栈是一个先进后出的数据结构。 5 | 6 | 要设计这样的一个需要两个栈来完成,一个栈用于正常的存储,另一个用于只存储最小的。 7 | 8 | 这样push/pop get min都是O(1) 时间完成。 9 | 10 | 非常基础。 11 | 12 | 其实在Python中可以用类直接写min属性,不过限定了只能用栈了。 13 | 14 | """ 15 | 16 | # deque 是一个Python实现的双端队列。 17 | # 由底层C代码实现。 18 | # 使用它可以保证在左右两端进行添加和删除操作时间都是O(1)。 19 | from collections import deque 20 | 21 | testStack = range(10) 22 | 23 | 24 | class Stack: 25 | """ 26 | 一个先进后出的栈。 27 | """ 28 | def __init__(self): 29 | """ 30 | 这里用实例对象。 31 | """ 32 | self.stored = deque() 33 | 34 | def __repr__(self): 35 | # 3.6 + 36 | return f'<{self.stored}>' 37 | 38 | def push(self, value): 39 | self.stored.append(value) 40 | 41 | def pop(self): 42 | return self.stored.pop() 43 | 44 | def get_top(self): 45 | """ 46 | 查看栈顶的数据但不压出。 47 | """ 48 | return self.stored[-1] 49 | 50 | def empty(self): 51 | if self.stored: 52 | return False 53 | return True 54 | 55 | 56 | class MinStack(Stack): 57 | """ 58 | 一个可以在O(1)时间内获取出最小值的栈。 59 | """ 60 | def __init__(self): 61 | super().__init__() 62 | 63 | self.minStack = Stack() 64 | 65 | def push(self, value): 66 | super().push(value) 67 | if self.minStack.empty(): 68 | self.minStack.push(value) 69 | else: 70 | if self.minStack.get_top() <= value: 71 | self.minStack.push(self.minStack.get_top()) 72 | else: 73 | self.minStack.push(value) 74 | 75 | def pop(self): 76 | super().pop() 77 | self.minStack.pop() 78 | 79 | def get_min(self): 80 | """ 81 | 返回栈顶但不压出。 82 | """ 83 | return self.minStack.get_top() 84 | 85 | 86 | a = Stack() 87 | for i in testStack: 88 | a.push(i) 89 | 90 | print(a) 91 | a.pop() 92 | print(a) 93 | 94 | a = MinStack() 95 | 96 | a.push(1) 97 | print(a.get_min()) # 1 98 | a.push(2) 99 | print(a.get_min()) # 1 100 | a.push(0) 101 | print(a.get_min()) # 0 102 | a.pop() 103 | print(a.get_min()) # 1 104 | 105 | -------------------------------------------------------------------------------- /Stack/ImplementQueueUsingStack.py: -------------------------------------------------------------------------------- 1 | """ 2 | 使用栈来实现队列。 3 | 队列是一个先进先出的数据结构,栈则是一个先进后出的数据结构。 4 | 5 | 当然在 Python 中可以直接使用 Queue 队列,deque 双端队列。 6 | 7 | 不过还是要学习思考下如何用栈来实现。 8 | 9 | 用栈实现有两个难点: 10 | 栈只能是先进后出。所以要想实现的话务必需要另一个栈。 11 | 将当前栈里所有的数据压入另一个栈然后另一个栈里的先进后出就会变成原本的先进先出了。 12 | 13 | 难点1: 何时将数据压入栈2? 14 | 难点2:压入栈2后如果又有新的数据追加进来呢? 15 | 16 | 第一个问题我想到的是在栈2为空,且栈1数据为两个及以上时。 17 | 第二个问题我想到的是如果栈2有数据,则在栈1追加。 18 | 这时pop(),直到条件为难点1时清空栈1,压入栈2。 19 | 20 | 21 | 1. push 时,如果两个都没有数据则直接压入栈2. 22 | 2. push 时,如果栈2有数据则压入栈1. 23 | 3. pop 时,如果栈2有数据则 pop 栈2. 24 | 4. pop 栈2之后若栈2为空,则pop栈1,直至空。 25 | 26 | 测试用例: 27 | https://leetcode.com/problems/implement-queue-using-stacks/ 28 | 29 | """ 30 | 31 | # 要使用3遍以上时再抽象到一个单独的类中。 32 | 33 | from GetMinStack import Stack 34 | 35 | 36 | class Queue: 37 | 38 | def __init__(self): 39 | self.stack_one = Stack() 40 | self.stack_two = Stack() 41 | 42 | def push(self, value): 43 | if self.stack_two.empty(): 44 | self.stack_two.push(value) 45 | else: 46 | self.stack_one.push(value) 47 | 48 | def pop(self): 49 | 50 | pop_result = self.stack_two.pop() 51 | if self.stack_two.empty(): 52 | while 1: 53 | if self.stack_one.empty(): 54 | break 55 | 56 | self.stack_two.push(self.stack_one.pop()) 57 | 58 | return pop_result 59 | 60 | def peek(self): 61 | 62 | return self.stack_two.get_top() 63 | 64 | 65 | queue = Queue() 66 | 67 | queue.push(1) 68 | queue.push(2) 69 | queue.push(3) 70 | 71 | print(queue.pop()) 72 | queue.push(4) 73 | print(queue.pop()) 74 | print(queue.pop()) 75 | print(queue.pop()) 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /Stack/ReverseAStackByRecursive.py: -------------------------------------------------------------------------------- 1 | """ 2 | 只能用递归不能用其他数据结构来逆序一个栈。 3 | 4 | 可以用另一个新栈的话比较容易。 5 | 6 | """ 7 | 8 | 9 | from GetMinStack import Stack 10 | 11 | 12 | def reverseStack(stacks): 13 | new_stack = Stack() 14 | 15 | def helper(stacks): 16 | if stacks.empty(): 17 | return 18 | 19 | new_stack.push(stacks.pop()) 20 | 21 | helper(stacks) 22 | 23 | helper(stacks) 24 | 25 | return new_stack 26 | 27 | # 测试用例。 28 | a = range(10) 29 | 30 | b = Stack() 31 | 32 | for i in a: 33 | b.push(i) 34 | 35 | # 不用assert了。 36 | print(b) 37 | 38 | print(reverseStack(b)) 39 | 40 | 41 | -------------------------------------------------------------------------------- /String/DetectCapital.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a word, you need to judge whether the usage of capitals in it is right or not. 3 | 4 | We define the usage of capitals in a word to be right when one of the following cases holds: 5 | 6 | 1. All letters in this word are capitals, like "USA". 7 | 2. All letters in this word are not capitals, like "leetcode". 8 | 3. Only the first letter in this word is capital if it has more than one letter, like "Google". 9 | Otherwise, we define that this word doesn't use capitals in a right way. 10 | Example 1: 11 | Input: "USA" 12 | Output: True 13 | Example 2: 14 | Input: "FlaG" 15 | Output: False 16 | 17 | 18 | 题目中将三种情况定义为 capitals: 19 | 1. 全是大写。("USA") 20 | 2. 全是小写。("leetcode") 21 | 3. 多于1个字符只在第一位用了大写。("Google") 22 | 23 | 思路O(n)的遍历和内置。 24 | 25 | 遍历的判断: 26 | ASCII码中: 27 | 65-90 是 A-Z. 28 | 97-122 是 a-z. 29 | 30 | 若第一个字符是大写,则判断: 31 | 剩下的是否全是大写,剩下的是否全是小写。 32 | 33 | 若第一个字符是小写,则判断: 34 | 剩下的是否全是小写。 35 | 36 | 只有一个字符时,无论如何都是capital. 37 | 38 | 测试用例: 39 | https://leetcode.com/problems/detect-capital/description/ 40 | 41 | 内置最快,自写慢个4ms,考虑到内置是c写的。4ms完全可以接受。 42 | 43 | 44 | """ 45 | 46 | class Solution(object): 47 | def detectCapitalUse(self, word): 48 | """ 49 | :type word: str 50 | :rtype: bool 51 | """ 52 | if len(word) < 2: 53 | return True 54 | 55 | letter_one = ord(word[0]) 56 | # letter_two = word[1] 57 | if 65 <= letter_one <= 90: 58 | return self.letter_all_capital_or_lower(word[1:]) 59 | 60 | return self.letter_all_lower(word[1:]) 61 | # for i in word: 62 | 63 | def letter_all_capital_or_lower(self, word): 64 | # 65 | lower = False 66 | capital = False 67 | 68 | # A-Z 69 | left = 65 70 | right = 90 71 | 72 | if 97 <= ord(word[0]) <= 122: 73 | left = 97 74 | right = 122 75 | 76 | for i in word: 77 | if not left <= ord(i) <= right: 78 | return False 79 | return True 80 | 81 | def letter_all_lower(self, word): 82 | for i in word: 83 | if not 97 <= ord(i) <= 122: 84 | return False 85 | return True 86 | 87 | -------------------------------------------------------------------------------- /String/FindAndReplacePattern.py: -------------------------------------------------------------------------------- 1 | """ 2 | You have a list of words and a pattern, and you want to know which words in words matches the pattern. 3 | 4 | A word matches the pattern if there exists a permutation of letters p so that after replacing every letter x in the pattern with p(x), we get the desired word. 5 | 6 | (Recall that a permutation of letters is a bijection from letters to letters: every letter maps to another letter, and no two letters map to the same letter.) 7 | 8 | Return a list of the words in words that match the given pattern. 9 | 10 | You may return the answer in any order. 11 | 12 | 13 | 14 | Example 1: 15 | 16 | Input: words = ["abc","deq","mee","aqq","dkd","ccc"], pattern = "abb" 17 | Output: ["mee","aqq"] 18 | Explanation: "mee" matches the pattern because there is a permutation {a -> m, b -> e, ...}. 19 | "ccc" does not match the pattern because {a -> c, b -> c, ...} is not a permutation, 20 | since a and b map to the same letter. 21 | 22 | 23 | Note: 24 | 25 | 1 <= words.length <= 50 26 | 1 <= pattern.length = words[i].length <= 20 27 | 28 | 判断是否与给定的字符串模式是一样的。 29 | 30 | 思路是把所有的字符串转换为同一种编码的格式之后与pattern对比即可。 31 | 32 | 用的 str 直接就过了,beat 95%。 换成 set 取交集应该更快一些。 33 | 34 | 测试地址: 35 | https://leetcode.com/contest/weekly-contest-98/problems/find-and-replace-pattern/ 36 | 37 | beat: 38 | 95% 24ms. 39 | 40 | 41 | """ 42 | 43 | class Solution(object): 44 | def findAndReplacePattern(self, words, pattern): 45 | """ 46 | :type words: List[str] 47 | :type pattern: str 48 | :rtype: List[str] 49 | """ 50 | 51 | def translate_pattern(word): 52 | result = ['0'] 53 | current = '0' 54 | patterns = {word[0]: '0'} 55 | for i in word[1:]: 56 | if patterns.get(i) is not None: 57 | result.append(patterns.get(i)) 58 | else: 59 | current = str(int(current)+1) 60 | patterns[i] = current 61 | result.append(current) 62 | 63 | return ''.join(result) 64 | 65 | x = translate_pattern(pattern) 66 | 67 | result = [] 68 | for i in words: 69 | if x == translate_pattern(i): 70 | result.append(i) 71 | 72 | return result 73 | -------------------------------------------------------------------------------- /String/FirstUniqueCharacterInAString.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a string, find the first non-repeating character in it and return it's index. If it doesn't exist, return -1. 3 | 4 | Examples: 5 | 6 | s = "leetcode" 7 | return 0. 8 | 9 | s = "loveleetcode", 10 | return 2. 11 | Note: You may assume the string contain only lowercase letters. 12 | 13 | 给定一个字符串,找到第一个不重复的字符,输出索引,如不存在输出 -1。 14 | 15 | 思路是直接使用字典,都是O(1)。 16 | 17 | Discuss 中使用的 count 方法居然比这种方式快... 18 | 19 | beat 72% 20 | 21 | 测试地址: 22 | https://leetcode.com/problems/first-unique-character-in-a-string/description/ 23 | 24 | 25 | """ 26 | class Solution(object): 27 | def firstUniqChar(self, s): 28 | """ 29 | :type s: str 30 | :rtype: int 31 | """ 32 | 33 | x = {} 34 | 35 | for i in s: 36 | try: 37 | x[i] += 1 38 | except: 39 | x[i] = 1 40 | 41 | for i in x.keys(): 42 | if x[i] > 1: 43 | x.pop(i) 44 | 45 | for i in range(len(s)): 46 | if s[i] in x: 47 | return i 48 | return -1 49 | -------------------------------------------------------------------------------- /String/HammingDistance.py: -------------------------------------------------------------------------------- 1 | """ 2 | 汉明距离: 3 | Input: x = 1, y = 4 4 | 5 | Output: 2 6 | 7 | Explanation: 8 | 1 (0 0 0 1) 9 | 4 (0 1 0 0) 10 | ↑ ↑ 11 | 12 | The above arrows point to positions where the corresponding bits are different. 13 | 14 | 相异的部分就是汉明距离。 15 | 应用: 16 | 搜索引擎中的搜图: 17 | https://blog.csdn.net/liudongdong19/article/details/80541216 18 | 基本思路是: 19 | 将图片转换灰度后会有64级,每级对应一个整数,两两对比整数。也就是取汉明距离。 20 | 21 | 测试用例: 22 | https://leetcode.com/problems/hamming-distance/description/ 23 | 24 | 思路: 25 | 利用异或运算相同取0,相异取1,最后计算出 26 | """ 27 | 28 | class Solution(object): 29 | def hammingDistance(self, x, y): 30 | """ 31 | :type x: int 32 | :type y: int 33 | :rtype: int 34 | """ 35 | return str(bin(x ^ y)).count('1') 36 | 37 | -------------------------------------------------------------------------------- /String/ImplementStrStr().py: -------------------------------------------------------------------------------- 1 | """ 2 | Implement strStr(). 3 | 4 | Return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack. 5 | 6 | Example 1: 7 | 8 | Input: haystack = "hello", needle = "ll" 9 | Output: 2 10 | Example 2: 11 | 12 | Input: haystack = "aaaaa", needle = "bba" 13 | Output: -1 14 | Clarification: 15 | 16 | What should we return when needle is an empty string? This is a great question to ask during an interview. 17 | 18 | For the purpose of this problem, we will return 0 when needle is an empty string. This is consistent to C's strstr() and Java's indexOf(). 19 | 20 | strStr() 等同于 Python 中的 find() 21 | 22 | 想要通过直接: 23 | ``` 24 | str.find() 25 | ``` 26 | 直接 beat 100%... 27 | 28 | 测试用例: 29 | https://leetcode.com/problems/implement-strstr/description/ 30 | 31 | 自己的实现思路: 32 | 33 | 记录两者len,needle的长度大于haystack,则一定不存在 -1. 34 | 接下来遍历 haystack 若此时剩余长度小于 needle 则一定不存在 -1. 35 | 若[0]与[0]相同,则进一步进行对比,一样则返回下标,不一样则继续。 36 | 37 | built-in 20ms 38 | myself 24ms 39 | 考虑到built-in 是 c++,这样效率也基本一致了。 40 | 41 | """ 42 | class Solution(object): 43 | def strStr(self, haystack, needle): 44 | """ 45 | :type haystack: str 46 | :type needle: str 47 | :rtype: int 48 | """ 49 | # bulit-in 20ms 50 | # return haystack.find(needle) 51 | 52 | # myself 53 | if not needle: 54 | return 0 55 | 56 | # 24ms. 57 | lengthHaystack = len(haystack) 58 | lengthNeedle = len(needle) 59 | 60 | if lengthNeedle > lengthHaystack: 61 | return -1 62 | 63 | if lengthNeedle == lengthHaystack: 64 | return 0 if haystack == needle else -1 65 | 66 | for i, d in enumerate(haystack): 67 | if lengthHaystack - i < lengthNeedle: 68 | return -1 69 | 70 | if d == needle[0]: 71 | if haystack[i:i+lengthNeedle] == needle: 72 | return i 73 | 74 | -------------------------------------------------------------------------------- /String/JewelsAndStones.py: -------------------------------------------------------------------------------- 1 | """ 2 | Example 1: 3 | 4 | Input: J = "aA", S = "aAAbbbb" 5 | Output: 3 6 | Example 2: 7 | 8 | Input: J = "z", S = "ZZ" 9 | Output: 0 10 | Note: 11 | 12 | S and J will consist of letters and have length at most 50. 13 | The characters in J are distinct. 14 | 15 | 查找J中的每个字符在 S 出现的次数的总和。 16 | 17 | 改进: 18 | J有可能有重复的数。 19 | 20 | 测试数据: 21 | https://leetcode.com/problems/jewels-and-stones/description/ 22 | 23 | """ 24 | 25 | class Solution(object): 26 | def numJewelsInStones(self, J, S): 27 | """ 28 | :type J: str 29 | :type S: str 30 | :rtype: int 31 | """ 32 | S_dict = {i:S.count(i) for i in set(S)} 33 | 34 | return sum((S_dict.get(i, 0) for i in J)) 35 | -------------------------------------------------------------------------------- /String/LengthOfLastWord.py: -------------------------------------------------------------------------------- 1 | """ 2 | Input: "Hello World" 3 | Output: 5 4 | 5 | 每个单词都会被 ' ' 分割。 6 | 所以要做的是从尾向前找第一个空格。当然Python 下用 strip(' ')分割后取[-1]是最好写出来的。 7 | 当然还要确保下尾部开始不能是' ',要找到第一个单词才行。 8 | 9 | 测试用例: 10 | https://leetcode.com/problems/length-of-last-word/description/ 11 | 12 | """ 13 | class Solution(object): 14 | def lengthOfLastWord(self, s): 15 | """ 16 | :type s: str 17 | :rtype: int 18 | """ 19 | if not s: 20 | return 0 21 | 22 | result = 0 23 | flag = False 24 | 25 | for i in s[::-1]: 26 | if i == ' ' and not flag: 27 | continue 28 | elif i == ' ' and flag: 29 | return result 30 | else: 31 | result += 1 32 | flag = True 33 | continue 34 | 35 | return result 36 | return result 37 | -------------------------------------------------------------------------------- /String/LetterCombinationsOfAPhoneNumber.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a string containing digits from 2-9 inclusive, return all possible letter combinations that the number could represent. 3 | 4 | A mapping of digit to letters (just like on the telephone buttons) is given below. Note that 1 does not map to any letters. 5 | 6 | 7 | 8 | Example: 9 | 10 | Input: "23" 11 | Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]. 12 | Note: 13 | 14 | Although the above answer is in lexicographical order, your answer could be in any order you want. 15 | 16 | 17 | 图看链接: 18 | https://leetcode.com/problems/letter-combinations-of-a-phone-number/description/ 19 | 20 | 21 | 老式手机键盘一样,返回所有的组合。 22 | 23 | 使用的递归思路: 24 | 迭代每一个组合,返回所有的组合... 25 | 应该容易理解。时间复杂度上应该只有 O(xn)的解法。 26 | 27 | 测试链接: 28 | https://leetcode.com/problems/letter-combinations-of-a-phone-number/description/ 29 | 30 | beat 100% 20ms。 31 | 应该会有浮动吧,一次通过,不测第二次了。 32 | 33 | 34 | """ 35 | class Solution(object): 36 | def letterCombinations(self, digits): 37 | """ 38 | :type digits: str 39 | :rtype: List[str] 40 | """ 41 | maps = { 42 | '2': 'abc', 43 | '3': 'def', 44 | '4': 'ghi', 45 | '5': 'jkl', 46 | '6': 'mno', 47 | '7': 'pqrs', 48 | '8': 'tuv', 49 | '9': 'wxyz' 50 | } 51 | 52 | result = [] 53 | 54 | def reduce_abc(strs, currentStr=""): 55 | if not strs: 56 | return currentStr 57 | else: 58 | for i in maps[strs[0]]: 59 | x = reduce_abc(strs[1:], currentStr=currentStr+i) 60 | if x: 61 | result.append(x) 62 | reduce_abc(digits) 63 | return result 64 | -------------------------------------------------------------------------------- /String/LongPressedName.py: -------------------------------------------------------------------------------- 1 | """ 2 | Your friend is typing his name into a keyboard. Sometimes, when typing a character c, the key might get long pressed, and the character will be typed 1 or more times. 3 | 4 | You examine the typed characters of the keyboard. Return True if it is possible that it was your friends name, with some characters (possibly none) being long pressed. 5 | 6 | 7 | 8 | Example 1: 9 | 10 | Input: name = "alex", typed = "aaleex" 11 | Output: true 12 | Explanation: 'a' and 'e' in 'alex' were long pressed. 13 | Example 2: 14 | 15 | Input: name = "saeed", typed = "ssaaedd" 16 | Output: false 17 | Explanation: 'e' must have been pressed twice, but it wasn't in the typed output. 18 | Example 3: 19 | 20 | Input: name = "leelee", typed = "lleeelee" 21 | Output: true 22 | Example 4: 23 | 24 | Input: name = "laiden", typed = "laiden" 25 | Output: true 26 | Explanation: It's not necessary to long press any character. 27 | 28 | 29 | Note: 30 | 31 | name.length <= 1000 32 | typed.length <= 1000 33 | The characters of name and typed are lowercase letters. 34 | 35 | 判断 typed 里 是否存在 name,保证顺序的。 36 | 37 | 思路: 38 | typed 和 name 各一个指针,命中了就一起走,没命中就typed走。最后判断指针是否指向了name尾。 39 | 40 | 测试地址: 41 | https://leetcode.com/contest/weekly-contest-107/problems/long-pressed-name/ 42 | 43 | """ 44 | class Solution(object): 45 | def isLongPressedName(self, name, typed): 46 | """ 47 | :type name: str 48 | :type typed: str 49 | :rtype: bool 50 | """ 51 | x = 0 52 | y = 0 53 | 54 | x_length = len(name) 55 | y_length = len(typed) 56 | 57 | while x < x_length and y < y_length: 58 | 59 | if typed[y] == name[x]: 60 | y += 1 61 | x += 1 62 | else: 63 | y += 1 64 | 65 | if x == x_length: 66 | return True 67 | return False 68 | -------------------------------------------------------------------------------- /String/LongesSubstrings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a string, find the length of the longest substring without repeating characters. 3 | 4 | Examples: 5 | 6 | Given "abcabcbb", the answer is "abc", which the length is 3. 7 | 8 | Given "bbbbb", the answer is "b", with the length of 1. 9 | 10 | Given "pwwkew", the answer is "wke", with the length of 3. Note that the answer must be a substring, "pwke" is a subsequence and not a substring. 11 | 12 | 找到最长的子字符串。 13 | 14 | 基本思路是逐个遍历若不在new里则添加进里面,如果在new里则表示已经发生了重复,那么会对比目前的new与之前保存的子字符串长度哪个较大, 15 | 保存较大的。新的new则为发生重复的字符串直到最后+新数据。`pkwk`遍历到第二个k时new此时会变成`wk`。 16 | 17 | 因为是子字符串并不是子序列,所以这样做是可行的。 18 | 19 | 时间复杂度 O(n) 20 | 21 | 测试用例: 22 | https://leetcode.com/problems/longest-substring-without-repeating-characters/description/ 23 | 24 | 25 | """ 26 | 27 | class Solution(object): 28 | def lengthOfLongestSubstring(self, s): 29 | """ 30 | :type s: str 31 | :rtype: int 32 | """ 33 | if not s: 34 | return 0 35 | 36 | longestSubstringLength = 1 37 | 38 | new = s[0] 39 | 40 | for data in s[1:]: 41 | if data not in new: 42 | new += data 43 | continue 44 | 45 | # repeated. 46 | if len(new) > longestSubstringLength: 47 | longestSubstringLength = len(new) 48 | 49 | new = new[new.index(data)+1:] + data 50 | 51 | if len(new) > longestSubstringLength: 52 | return len(new) 53 | 54 | return longestSubstringLength -------------------------------------------------------------------------------- /String/LongestCommonPrefix.py: -------------------------------------------------------------------------------- 1 | """ 2 | Write a function to find the longest common prefix string amongst an array of strings. 3 | 4 | If there is no common prefix, return an empty string "". 5 | 6 | Example 1: 7 | 8 | Input: ["flower","flow","flight"] 9 | Output: "fl" 10 | Example 2: 11 | 12 | Input: ["dog","racecar","car"] 13 | Output: "" 14 | Explanation: There is no common prefix among the input strings. 15 | Note: 16 | 17 | All given inputs are in lowercase letters a-z. 18 | 19 | 20 | 21 | 所有单词的共同的前缀。 22 | 没什么技巧,从每个单词的第一个开始对比就好了。 23 | Python 中有一个 zip 可以做这些事情。 24 | 25 | beat 90% 26 | 27 | 测试地址: 28 | https://leetcode.com/problems/longest-common-prefix/description/ 29 | 30 | 今日的零启动任务。 31 | 32 | """ 33 | class Solution(object): 34 | def longestCommonPrefix(self, strs): 35 | """ 36 | :type strs: List[str] 37 | :rtype: str 38 | """ 39 | result = "" 40 | 41 | for i in zip(*strs): 42 | a = i[0] 43 | for j in i[1:]: 44 | if j != a: 45 | return result 46 | else: 47 | result += a 48 | 49 | return result 50 | 51 | -------------------------------------------------------------------------------- /String/MinimumAddToMakeParenthesesValid.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a string S of '(' and ')' parentheses, we add the minimum number of parentheses ( '(' or ')', and in any positions ) so that the resulting parentheses string is valid. 3 | 4 | Formally, a parentheses string is valid if and only if: 5 | 6 | It is the empty string, or 7 | It can be written as AB (A concatenated with B), where A and B are valid strings, or 8 | It can be written as (A), where A is a valid string. 9 | Given a parentheses string, return the minimum number of parentheses we must add to make the resulting string valid. 10 | 11 | 12 | 13 | Example 1: 14 | 15 | Input: "())" 16 | Output: 1 17 | Example 2: 18 | 19 | Input: "(((" 20 | Output: 3 21 | Example 3: 22 | 23 | Input: "()" 24 | Output: 0 25 | Example 4: 26 | 27 | Input: "()))((" 28 | Output: 4 29 | 30 | 31 | Note: 32 | 33 | S.length <= 1000 34 | S only consists of '(' and ')' characters. 35 | 36 | 给一个字符串只包含 "(" 和 ")"。 37 | 38 | 返回至少补多少个可以达成全部有效。 39 | 40 | 思路: 41 | 去除原来有效的,剩余多少个即为需要多少个。 42 | 43 | 44 | """ 45 | class Solution(object): 46 | def minAddToMakeValid(self, S): 47 | """ 48 | :type S: str 49 | :rtype: int 50 | """ 51 | if not S: 52 | return 0 53 | t = [S[0]] 54 | for i in S[1:]: 55 | if i == ')': 56 | if not t: 57 | t.append(i) 58 | continue 59 | 60 | if t[-1] == '(': 61 | t.pop() 62 | else: 63 | t.append(i) 64 | else: 65 | t.append(i) 66 | return len(t) 67 | -------------------------------------------------------------------------------- /String/NumberOfSegmentsInString.py: -------------------------------------------------------------------------------- 1 | """ 2 | Count the number of segments in a string, where a segment is defined to be a contiguous sequence of non-space characters. 3 | 4 | Please note that the string does not contain any non-printable characters. 5 | 6 | Example: 7 | 8 | Input: "Hello, my name is John" 9 | Output: 5 10 | 11 | 深刻的体会到了什么是,当我要用正则解决一个问题时,那么就有了两个问题。 12 | cry= =. 13 | 14 | 其实本来用不着正则的。 15 | 16 | 就是根据空白分割,然后统计数量,没什么难度。O(n). 17 | 18 | Python中可以直接 len(s.split()). 19 | 20 | 测试用例: 21 | https://leetcode.com/problems/number-of-segments-in-a-string/description/ 22 | 23 | """ 24 | import re 25 | 26 | class Solution(object): 27 | def countSegments(self, s): 28 | """ 29 | :type s: str 30 | :rtype: int 31 | """ 32 | s = s.strip() 33 | if not s.strip(): 34 | return 0 35 | 36 | result = re.split(r'\s+', s) 37 | 38 | return len(result) 39 | -------------------------------------------------------------------------------- /String/PermutationInString.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given two strings s1 and s2, write a function to return true if s2 contains the permutation of s1. In other words, one of the first string's permutations is the substring of the second string. 3 | Example 1: 4 | Input:s1 = "ab" s2 = "eidbaooo" 5 | Output:True 6 | Explanation: s2 contains one permutation of s1 ("ba"). 7 | Example 2: 8 | Input:s1= "ab" s2 = "eidboaoo" 9 | Output: False 10 | Note: 11 | The input strings only contain lower case letters. 12 | The length of both given strings is in range [1, 10,000]. 13 | 14 | 类似于 Find All Anagrams in a String 难度应该颠倒过来。 15 | 16 | 这个的测试用例更丰富,发现了没想到的一个盲点。 17 | 18 | 思路请看 https://github.com/HuberTRoy/leetCode/blob/master/DP/FindAllAnagramsInAString.py 19 | 20 | 21 | beat 79% 22 | 23 | 测试地址: 24 | https://leetcode.com/problems/permutation-in-string/description/ 25 | 26 | 27 | """ 28 | class Solution(object): 29 | def checkInclusion(self, s1, s2): 30 | """ 31 | :type s1: str 32 | :type s2: str 33 | :rtype: bool 34 | """ 35 | if len(s1) > len(s2): 36 | return False 37 | 38 | counts = {} 39 | 40 | for i in s1: 41 | try: 42 | counts[i] += 1 43 | except: 44 | counts[i] = 1 45 | 46 | pre = counts.copy() 47 | 48 | for c in range(len(s2)): 49 | i = s2[c] 50 | if i in pre: 51 | pre[i] -= 1 52 | if not pre[i]: 53 | pre.pop(i) 54 | 55 | if not pre: 56 | return True 57 | else: 58 | if i in counts: 59 | if i != s2[c-len(s1)+sum(pre.values())]: 60 | for t in s2[c-len(s1)+sum(pre.values()):c]: 61 | if t == i: 62 | break 63 | try: 64 | pre[t] += 1 65 | except: 66 | pre[t] = 1 67 | continue 68 | pre = counts.copy() 69 | if i in pre: 70 | pre[i] -= 1 71 | if not pre[i]: 72 | pre.pop(i) 73 | 74 | return False 75 | -------------------------------------------------------------------------------- /String/ReverseInteger.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | Given a 32-bit signed integer, reverse digits of an integer. 4 | 5 | Example 1: 6 | 7 | Input: 123 8 | Output: 321 9 | Example 2: 10 | 11 | Input: -123 12 | Output: -321 13 | Example 3: 14 | 15 | Input: 120 16 | Output: 21 17 | Note: 18 | Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [−231, 231 − 1]. For the purpose of this problem, assume that your function returns 0 when the reversed integer overflows. 19 | 20 | 21 | 翻转一个整数。 22 | 23 | 我直接用了转成字符串,然后取反然后转成整数的方法。 24 | 效率过得去。 25 | beat 45%. 26 | 27 | 测试地址: 28 | https://leetcode.com/problems/reverse-integer/description/ 29 | 30 | """ 31 | 32 | class Solution(object): 33 | def reverse(self, x): 34 | """ 35 | :type x: int 36 | :rtype: int 37 | """ 38 | 39 | # str_x = str(x) 40 | if x < 0: 41 | x = -int(str(abs(x))[::-1]) 42 | else: 43 | x = int(str(abs(x))[::-1]) 44 | 45 | if x > 2**31 or x < -2**31: 46 | return 0 47 | return x 48 | -------------------------------------------------------------------------------- /String/ReverseString.py: -------------------------------------------------------------------------------- 1 | """ 2 | Write a function that takes a string as input and returns the string reversed. 3 | 4 | Example 1: 5 | 6 | Input: "hello" 7 | Output: "olleh" 8 | Example 2: 9 | 10 | Input: "A man, a plan, a canal: Panama" 11 | Output: "amanaP :lanac a ,nalp a ,nam A" 12 | 13 | 倒序字符串,在 Python 中应该是非常简单的,Python 的字符串支持分片操作。 14 | 15 | 基本有这么几种方法: 16 | 1. 创建新字符串,从后向前迭代,然后与新字符串合并。 17 | 2. 直接用分片 [::-1] 18 | 3. 转换成列表,然后翻转列表。 19 | 20 | 经测试 2 和 3的效率差不多,没看源码,底层2应该用的1的思路实现的吧。 21 | 22 | 23 | 测试用例: 24 | https://leetcode.com/problems/reverse-string/description/ 25 | 26 | """ 27 | class Solution(object): 28 | def reverseString(self, s): 29 | """ 30 | :type s: str 31 | :rtype: str 32 | """ 33 | 34 | # return s[::-1] 35 | return ''.join(reversed(list(s))) 36 | -------------------------------------------------------------------------------- /String/ShiftingLetters.py: -------------------------------------------------------------------------------- 1 | """ 2 | We have a string S of lowercase letters, and an integer array shifts. 3 | 4 | Call the shift of a letter, the next letter in the alphabet, (wrapping around so that 'z' becomes 'a'). 5 | 6 | For example, shift('a') = 'b', shift('t') = 'u', and shift('z') = 'a'. 7 | 8 | Now for each shifts[i] = x, we want to shift the first i+1 letters of S, x times. 9 | 10 | Return the final string after all such shifts to S are applied. 11 | 12 | Example 1: 13 | 14 | Input: S = "abc", shifts = [3,5,9] 15 | Output: "rpl" 16 | Explanation: 17 | We start with "abc". 18 | After shifting the first 1 letters of S by 3, we have "dbc". 19 | After shifting the first 2 letters of S by 5, we have "igc". 20 | After shifting the first 3 letters of S by 9, we have "rpl", the answer. 21 | Note: 22 | 23 | 1 <= S.length = shifts.length <= 20000 24 | 0 <= shifts[i] <= 10 ^ 9 25 | 26 | 27 | 给一个字符串,不断经过转换,得出最终字符串。 28 | 29 | 每一轮的转换都是对这之前的所有字符串而言的。 30 | 31 | 思路: 32 | 1. 33 | 从后向前,得到索引 % 26. 34 | 35 | 2. 36 | 转换字符到 ascii,相加然后处理超过的量。 37 | 38 | 测试地址: 39 | https://leetcode.com/contest/weekly-contest-88/problems/shifting-letters/ 40 | 41 | """ 42 | class Solution(object): 43 | def shiftingLetters(self, S, shifts): 44 | """ 45 | :type S: str 46 | :type shifts: List[int] 47 | :rtype: str 48 | """ 49 | 50 | letters = "abcdefghijklmnopqrstuvwxyz" 51 | 52 | new_s = [] 53 | old_index = 0 54 | for i, j in zip(S[::-1], shifts[::-1]): 55 | index = letters.index(i) 56 | 57 | new_index = (index+j+old_index)%26 58 | 59 | new_s.append(letters[new_index]) 60 | old_index += j 61 | return ''.join(new_s[::-1]) 62 | -------------------------------------------------------------------------------- /String/SimplifyPath.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given an absolute path for a file (Unix-style), simplify it. 3 | 4 | For example, 5 | path = "/home/", => "/home" 6 | path = "/a/./b/../../c/", => "/c" 7 | path = "/a/../../b/../c//.//", => "/c" 8 | path = "/a//b////c/d//././/..", => "/a/b/c" 9 | 10 | In a UNIX-style file system, a period ('.') refers to the current directory, so it can be ignored in a simplified path. Additionally, a double period ("..") moves up a directory, so it cancels out whatever the last directory was. For more information, look here: https://en.wikipedia.org/wiki/Path_(computing)#Unix_style 11 | 12 | Corner Cases: 13 | 14 | Did you consider the case where path = "/../"? 15 | In this case, you should return "/". 16 | Another corner case is the path might contain multiple slashes '/' together, such as "/home//foo/". 17 | In this case, you should ignore redundant slashes and return "/home/foo". 18 | 19 | 给一个 UNIX 风格的文件系统字符串,修剪成标准格式。 20 | 21 | 思路: 22 | 1. 先用正则多斜线变一斜线。 23 | 2. 一个用于存放结果的新列表: 24 | 遇到 . 不管,遇到 .. 就弹出尾部的一个,其他的均加入。 25 | 3. 最后用 '/' 合并起来。 26 | 27 | beat 73% 28 | 测试了多次最高是 28ms,和 24ms大致一样,24ms的没用正则,直接 split('/') 然后 判断非空的组成新的。 29 | 30 | 测试地址: 31 | https://leetcode.com/problems/simplify-path/description/ 32 | 33 | """ 34 | import re 35 | 36 | class Solution(object): 37 | def simplifyPath(self, path): 38 | """ 39 | :type path: str 40 | :rtype: str 41 | """ 42 | path = re.sub(r'/+', '/', path) 43 | if path[-1] == '/': 44 | path = path[:-1] 45 | 46 | path = path.split('/') 47 | 48 | new_path = [] 49 | for i in path: 50 | if i == '..': 51 | try: 52 | new_path.pop() 53 | continue 54 | except: 55 | continue 56 | if i =='.': 57 | continue 58 | 59 | new_path.append(i) 60 | 61 | x = '/'.join(new_path) 62 | if x and x[0] == '/': 63 | return x 64 | return '/' + x 65 | -------------------------------------------------------------------------------- /String/SortCharactersByFrequency.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a string, sort it in decreasing order based on the frequency of characters. 3 | 4 | Example 1: 5 | 6 | Input: 7 | "tree" 8 | 9 | Output: 10 | "eert" 11 | 12 | Explanation: 13 | 'e' appears twice while 'r' and 't' both appear once. 14 | So 'e' must appear before both 'r' and 't'. Therefore "eetr" is also a valid answer. 15 | Example 2: 16 | 17 | Input: 18 | "cccaaa" 19 | 20 | Output: 21 | "cccaaa" 22 | 23 | Explanation: 24 | Both 'c' and 'a' appear three times, so "aaaccc" is also a valid answer. 25 | Note that "cacaca" is incorrect, as the same characters must be together. 26 | Example 3: 27 | 28 | Input: 29 | "Aabb" 30 | 31 | Output: 32 | "bbAa" 33 | 34 | Explanation: 35 | "bbaA" is also a valid answer, but "Aabb" is incorrect. 36 | Note that 'A' and 'a' are treated as two different characters. 37 | 38 | 给定一个字符串,以字符出现的频率进行排序。 39 | 40 | 思路: 41 | 1. 用一个字典记录每个字符出现的频率。 42 | 2. 根据出现的频率排序。 43 | 3. 因为直接堆在一起即可,直接构建一个列表。 44 | 4. 在组合起来。 45 | 46 | beat 95% 36ms. 47 | 48 | 测试地址: 49 | https://leetcode.com/problems/sort-characters-by-frequency/description/ 50 | 51 | """ 52 | class Solution(object): 53 | def frequencySort(self, s): 54 | """ 55 | :type s: str 56 | :rtype: str 57 | """ 58 | 59 | x = {} 60 | 61 | for i in s: 62 | try: 63 | x[i] += 1 64 | except: 65 | x[i] = 1 66 | 67 | b = sorted(x, key=lambda t: x[t], reverse=True) 68 | 69 | return ''.join([i*x[i] for i in b]) 70 | -------------------------------------------------------------------------------- /String/ToLowerCase.py: -------------------------------------------------------------------------------- 1 | """ 2 | 将所有字符转换成小写字符。 3 | Python 自带此函数。 4 | 5 | 若要自己写的话,我想到的是一个是建立起哈希表。 6 | {'A': 'a'....} 7 | 这样查表,时间复杂度是 O(n)。 8 | 9 | 还有可以利用ASCII。 10 | ord('a') 11 | 97 12 | chr('A') 13 | 65 14 | 中间差了32个。 15 | 16 | """ 17 | 18 | class Solution(object): 19 | def toLowerCase(self, str): 20 | """ 21 | :type str: str 22 | :rtype: str 23 | """ 24 | return str.lower() 25 | -------------------------------------------------------------------------------- /String/UniqueEmailAddresses.py: -------------------------------------------------------------------------------- 1 | """ 2 | Every email consists of a local name and a domain name, separated by the @ sign. 3 | 4 | For example, in alice@leetcode.com, alice is the local name, and leetcode.com is the domain name. 5 | 6 | Besides lowercase letters, these emails may contain '.'s or '+'s. 7 | 8 | If you add periods ('.') between some characters in the local name part of an email address, mail sent there will be forwarded to the same address without dots in the local name. For example, "alice.z@leetcode.com" and "alicez@leetcode.com" forward to the same email address. (Note that this rule does not apply for domain names.) 9 | 10 | If you add a plus ('+') in the local name, everything after the first plus sign will be ignored. This allows certain emails to be filtered, for example m.y+name@email.com will be forwarded to my@email.com. (Again, this rule does not apply for domain names.) 11 | 12 | It is possible to use both of these rules at the same time. 13 | 14 | Given a list of emails, we send one email to each address in the list. How many different addresses actually receive mails? 15 | 16 | 17 | 18 | Example 1: 19 | 20 | Input: ["test.email+alex@leetcode.com","test.e.mail+bob.cathy@leetcode.com","testemail+david@lee.tcode.com"] 21 | Output: 2 22 | Explanation: "testemail@leetcode.com" and "testemail@lee.tcode.com" actually receive mails 23 | 24 | 25 | Note: 26 | 27 | 1 <= emails[i].length <= 100 28 | 1 <= emails.length <= 100 29 | Each emails[i] contains exactly one '@' character. 30 | 31 | 32 | 替换 . 和 + 即可。 33 | 34 | 测试地址: 35 | https://leetcode.com/contest/weekly-contest-108/problems/unique-email-addresses/ 36 | 37 | """ 38 | import re 39 | 40 | class Solution(object): 41 | def numUniqueEmails(self, emails): 42 | """ 43 | :type emails: List[str] 44 | :rtype: int 45 | """ 46 | 47 | result = 0 48 | # local = {} 49 | _emails = set() 50 | ignore = re.compile(r'\+(.*)') 51 | for i in emails: 52 | x = i.split('@') 53 | if len(x) > 2: 54 | continue 55 | 56 | if len(x) == 1: 57 | continue 58 | 59 | local = x[0] 60 | domain = x[1] 61 | local = local.replace('.', '') 62 | 63 | 64 | local = re.sub(ignore, '', local) 65 | 66 | _emails.add(local + '@' + domain) 67 | 68 | return len(_emails) 69 | -------------------------------------------------------------------------------- /String/ValidAnagram.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given two strings s and t , write a function to determine if t is an anagram of s. 3 | 4 | Example 1: 5 | 6 | Input: s = "anagram", t = "nagaram" 7 | Output: true 8 | Example 2: 9 | 10 | Input: s = "rat", t = "car" 11 | Output: false 12 | Note: 13 | You may assume the string contains only lowercase alphabets. 14 | 15 | Follow up: 16 | What if the inputs contain unicode characters? How would you adapt your solution to such case? 17 | 18 | 判断 s 与 t 是否为变位词。 19 | 20 | 思路是排序 s 和 t,若相等则确定是变位词。 21 | 22 | 直接用 sorted 了。 23 | 效率 O(nlogn) 24 | 25 | beat 61%. 26 | 27 | 前面都是用的 dict 的思路,dict 查询是 O(1) 总体也就是 O(n) 了。 28 | 29 | dict 的思路基本是记录每个单词出现的次数,到0就剔除,最后若不剩余的话则表示是变位词,不写了,没有难点。 30 | 31 | 测试地址: 32 | https://leetcode.com/problems/valid-anagram/description/ 33 | 34 | 35 | """ 36 | class Solution(object): 37 | def isAnagram(self, s, t): 38 | """ 39 | :type s: str 40 | :type t: str 41 | :rtype: bool 42 | """ 43 | if sorted(s) == sorted(t): 44 | return True 45 | return False 46 | -------------------------------------------------------------------------------- /String/ValidNumber.py: -------------------------------------------------------------------------------- 1 | """ 2 | Validate if a given string can be interpreted as a decimal number. 3 | 4 | Some examples: 5 | "0" => true 6 | " 0.1 " => true 7 | "abc" => false 8 | "1 a" => false 9 | "2e10" => true 10 | " -90e3 " => true 11 | " 1e" => false 12 | "e3" => false 13 | " 6e-1" => true 14 | " 99e2.5 " => false 15 | "53.5e93" => true 16 | " --6 " => false 17 | "-+3" => false 18 | "95a54e53" => false 19 | 20 | Note: It is intended for the problem statement to be ambiguous. You should gather all requirements up front before implementing one. However, here is a list of characters that can be in a valid decimal number: 21 | 22 | Numbers 0-9 23 | Exponent - "e" 24 | Positive/negative sign - "+"/"-" 25 | Decimal point - "." 26 | Of course, the context of these characters also matters in the input. 27 | 28 | Update (2015-02-10): 29 | The signature of the C++ function had been updated. If you still see your function signature accepts a const char * argument, please click the reload button to reset your code definition. 30 | 31 | 判断可否化为数字。 32 | 虽然使用float是作弊行为,但还是忍不住用了... 33 | 当做零启动任务吧。 34 | 测试地址: 35 | https://leetcode.com/problems/valid-number/description/ 36 | 37 | """ 38 | 39 | class Solution(object): 40 | def isNumber(self, s): 41 | """ 42 | :type s: str 43 | :rtype: bool 44 | """ 45 | try: 46 | float(s) 47 | return True 48 | except: 49 | return False 50 | -------------------------------------------------------------------------------- /String/ValidPalindrome.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases. 3 | 4 | Note: For the purpose of this problem, we define empty string as valid palindrome. 5 | 6 | Example 1: 7 | 8 | Input: "A man, a plan, a canal: Panama" 9 | Output: true 10 | Example 2: 11 | 12 | Input: "race a car" 13 | Output: false 14 | 15 | 忽略特殊字符,空白,大小写。判断是否为回文字符串,空的话也为有效的。 16 | 17 | 关键字: re. 18 | 19 | 测试地址: 20 | https://leetcode.com/problems/valid-palindrome/description/ 21 | 22 | """ 23 | import re 24 | 25 | class Solution(object): 26 | def isPalindrome(self, s): 27 | """ 28 | :type s: str 29 | :rtype: bool 30 | """ 31 | 32 | if not s: 33 | return True 34 | 35 | s = s.lower() 36 | x = ''.join(re.findall(r'[a-z0-9]{1}', s)) 37 | 38 | return x == x[::-1] 39 | -------------------------------------------------------------------------------- /String/ValidParentheses.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid. 3 | 4 | An input string is valid if: 5 | 6 | Open brackets must be closed by the same type of brackets. 7 | Open brackets must be closed in the correct order. 8 | Note that an empty string is also considered valid. 9 | 10 | Example 1: 11 | 12 | Input: "()" 13 | Output: true 14 | Example 2: 15 | 16 | Input: "()[]{}" 17 | Output: true 18 | Example 3: 19 | 20 | Input: "(]" 21 | Output: false 22 | Example 4: 23 | 24 | Input: "([)]" 25 | Output: false 26 | Example 5: 27 | 28 | Input: "{[]}" 29 | Output: true 30 | 31 | 用栈即可。 32 | 33 | 测试地址: 34 | https://leetcode.com/problems/valid-parentheses/description/ 35 | 36 | beat 85%. 37 | 38 | """ 39 | 40 | class Solution(object): 41 | def isValid(self, s): 42 | """ 43 | :type s: str 44 | :rtype: bool 45 | """ 46 | left = "({[" 47 | left_key = {')': '(', ']': '[', '}': '{'} 48 | 49 | stack = [] 50 | 51 | for i in s: 52 | if i in left: 53 | stack.append(i) 54 | else: 55 | try: 56 | if stack[-1] == left_key[i]: 57 | stack.pop() 58 | else: 59 | return False 60 | except: 61 | return False 62 | 63 | if stack: 64 | return False 65 | return True 66 | -------------------------------------------------------------------------------- /String/WordPattern.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a pattern and a string str, find if str follows the same pattern. 3 | 4 | Here follow means a full match, such that there is a bijection between a letter in pattern and a non-empty word in str. 5 | 6 | Example 1: 7 | 8 | Input: pattern = "abba", str = "dog cat cat dog" 9 | Output: true 10 | Example 2: 11 | 12 | Input:pattern = "abba", str = "dog cat cat fish" 13 | Output: false 14 | Example 3: 15 | 16 | Input: pattern = "aaaa", str = "dog cat cat dog" 17 | Output: false 18 | Example 4: 19 | 20 | Input: pattern = "abba", str = "dog dog dog dog" 21 | Output: false 22 | Notes: 23 | You may assume pattern contains only lowercase letters, and str contains lowercase letters separated by a single space. 24 | 25 | 与 IsomorphicString 一样,此题来自于做完IsomorphicString的相关推荐。 26 | 27 | 思路: 28 | 直接 one line 的思路: 29 | 转换成列表,然后一致。判断下字符位数的不同。 30 | 31 | 同样的思路换成这个题就能跑20ms.. 32 | beat 99%. 33 | 34 | """ 35 | class Solution(object): 36 | def wordPattern(self, pattern, string): 37 | """ 38 | :type pattern: str 39 | :type str: str 40 | :rtype: bool 41 | """ 42 | pattern = list(pattern) 43 | string = string.split(' ') 44 | if len(pattern) != len(string): 45 | return False 46 | temp = len(set(zip(pattern, string))) 47 | return temp == len(set(pattern)) and temp == len(set(string)) 48 | -------------------------------------------------------------------------------- /Tree/BinaryTreeRightSideView.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a binary tree, imagine yourself standing on the right side of it, return the values of the nodes you can see ordered from top to bottom. 3 | 4 | Example: 5 | 6 | Input: [1,2,3,null,5,null,4] 7 | Output: [1, 3, 4] 8 | Explanation: 9 | 10 | 1 <--- 11 | / \ 12 | 2 3 <--- 13 | \ \ 14 | 5 4 <--- 15 | 16 | 给一颗二叉树,返回从右边看能看到的第一个。 17 | 18 | 思路BFS,返回最后的一个即可。 19 | 20 | beat 94%。 21 | 22 | 测试地址: 23 | https://leetcode.com/problems/binary-tree-right-side-view/description/ 24 | 25 | """ 26 | # Definition for a binary tree node. 27 | # class TreeNode(object): 28 | # def __init__(self, x): 29 | # self.val = x 30 | # self.left = None 31 | # self.right = None 32 | 33 | class Solution(object): 34 | def rightSideView(self, root): 35 | """ 36 | :type root: TreeNode 37 | :rtype: List[int] 38 | """ 39 | if not root: 40 | return [] 41 | 42 | result = [root.val] 43 | 44 | current = [root] 45 | next_nodes = [] 46 | 47 | while current or next_nodes: 48 | for i in current: 49 | if i.left: 50 | next_nodes.append(i.left) 51 | if i.right: 52 | next_nodes.append(i.right) 53 | if next_nodes: 54 | 55 | result.append(next_nodes[-1].val) 56 | current = next_nodes 57 | next_nodes = [] 58 | 59 | return result 60 | -------------------------------------------------------------------------------- /Tree/ConstructBinaryTreeFromInorderAndPostorderTraversal.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given inorder and postorder traversal of a tree, construct the binary tree. 3 | 4 | Note: 5 | You may assume that duplicates do not exist in the tree. 6 | 7 | For example, given 8 | 9 | inorder = [9,3,15,20,7] 10 | postorder = [9,15,7,20,3] 11 | Return the following binary tree: 12 | 13 | 3 14 | / \ 15 | 9 20 16 | / \ 17 | 15 7 18 | 19 | 20 | 这个的思路与之前的大同小异。 21 | 22 | inorder: 23 | 24 | 左 根 右 25 | 26 | postorder: 27 | 28 | 左 右 根 29 | 30 | postorder 中找根, 31 | inorder 中找左右。 32 | 33 | 下面是一个递归实现。 34 | 35 | left_inorder 36 | left_postorder 37 | 和 38 | right_inorder 39 | right_postorder 40 | 的处理。 41 | 42 | 一开始全部中规中矩的定义清晰,然后root.left, root.right。 43 | 44 | 完成所有测试大概需要 200ms 左右。 45 | 46 | 后面发现并不需要: 47 | 48 | postoder 是 左 右 根。 49 | 根完了就是右,所以直接可以postorder.pop(),然后先进行 right 的查找,相当于 right_postorder 带了一些另一颗树的东西,不过无关紧要。 50 | 51 | 都是些优化的步骤。 52 | 53 | 测试地址: 54 | https://leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/ 55 | 56 | """ 57 | # Definition for a binary tree node. 58 | # class TreeNode(object): 59 | # def __init__(self, x): 60 | # self.val = x 61 | # self.left = None 62 | # self.right = None 63 | 64 | class Solution(object): 65 | def buildTree(self, inorder, postorder): 66 | """ 67 | :type inorder: List[int] 68 | :type postorder: List[int] 69 | :rtype: TreeNode 70 | """ 71 | 72 | def makeTree(inorder, 73 | postorder): 74 | if not inorder or not postorder: 75 | return None 76 | 77 | root = TreeNode(postorder.pop()) 78 | index = inorder.index(root.val) 79 | 80 | # left_inorder = inorder[:inorder.index(root.val)] 81 | # left_postorder = postorder[:len(left_inorder)] 82 | 83 | # right_inorder = inorder[len(left_inorder)+1:] 84 | # right_postorder = postorder[len(left_postorder):-1] 85 | 86 | 87 | root.right = makeTree(inorder[index+1:], postorder) 88 | root.left = makeTree(inorder[:index], postorder) 89 | 90 | return root 91 | 92 | return makeTree(inorder, postorder) 93 | -------------------------------------------------------------------------------- /Tree/ConstructBinaryTreeFromPreorderAndInorderTraversal.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given preorder and inorder traversal of a tree, construct the binary tree. 3 | 4 | Note: 5 | You may assume that duplicates do not exist in the tree. 6 | 7 | For example, given 8 | 9 | preorder = [3,9,20,15,7] 10 | inorder = [9,3,15,20,7] 11 | Return the following binary tree: 12 | 13 | 3 14 | / \ 15 | 9 20 16 | / \ 17 | 15 7 18 | 19 | 20 | 给定中序和前序遍历返回完整的二叉树。 21 | 22 | 就思路上来说比较容易理解: 23 | 1. 前序是 根 左 右。 24 | 2. 中序是 左 根 右。 25 | 26 | 也就是在 前序中找到根,然后在中序中找到根的左右两颗子树。不断的重复左右两颗子树这样的过程。 27 | 28 | 下面是一个递归实现,效率并不是非常高: 29 | beat 40% ~ 50%. 30 | 31 | 测试地址: 32 | https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/description/ 33 | 34 | 35 | """ 36 | # Definition for a binary tree node. 37 | # class TreeNode(object): 38 | # def __init__(self, x): 39 | # self.val = x 40 | # self.left = None 41 | # self.right = None 42 | 43 | class Solution(object): 44 | def buildTree(self, preorder, inorder): 45 | """ 46 | :type preorder: List[int] 47 | :type inorder: List[int] 48 | :rtype: TreeNode 49 | """ 50 | 51 | def make(preorder, inorder): 52 | if not preorder: 53 | return None 54 | 55 | root = TreeNode(preorder[0]) 56 | 57 | left_in = inorder[:inorder.index(root.val)] 58 | left_pre = preorder[1:len(left_in)+1] 59 | right_in = inorder[len(left_in)+1:] 60 | right_pre = preorder[len(left_in)+1:] 61 | 62 | root.left = make(left_pre, left_in) 63 | root.right = make(right_pre, right_in) 64 | 65 | return root 66 | 67 | return make(preorder, inorder) 68 | 69 | -------------------------------------------------------------------------------- /Tree/ConvertSortedArrayToBinarySearchTree.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given an array where elements are sorted in ascending order, convert it to a height balanced BST. 3 | 4 | For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1. 5 | 6 | Example: 7 | 8 | Given the sorted array: [-10,-3,0,5,9], 9 | 10 | One possible answer is: [0,-3,9,-10,null,5], which represents the following height balanced BST: 11 | 12 | 0 13 | / \ 14 | -3 9 15 | / / 16 | -10 5 17 | 18 | 19 | 给定一个已排序过的数组,将它转换为一颗高度平衡的二叉搜索树。 20 | 21 | 也就是两颗子树的高度差不超过1。 22 | 23 | 因为是排序的数组,相对来说也异常简单,可以将它看做是一颗二叉搜索树中序遍历后的结果。 24 | 按照此结果转换回去就是了。 25 | 26 | 27 | 每次都二分: 28 | 29 | [-10,-3,0,5,9] 30 | mid 31 | 5//2 = 2 mid = 2 32 | 0 33 | [-10, -3] [5, 9] 2 // 2 = 1 mid = 1 34 | ↓ ↓ 35 | -3 9 36 | [-10] [] [5] [] 37 | 38 | 为空则不进行下面的操作。 39 | 40 | beat 98% 41 | 42 | 测试地址: 43 | https://leetcode.com/problems/convert-sorted-array-to-binary-search-tree/description/ 44 | 45 | """ 46 | # Definition for a binary tree node. 47 | # class TreeNode(object): 48 | # def __init__(self, x): 49 | # self.val = x 50 | # self.left = None 51 | # self.right = None 52 | 53 | class Solution(object): 54 | def sortedArrayToBST(self, nums): 55 | """ 56 | :type nums: List[int] 57 | :rtype: TreeNode 58 | """ 59 | if not nums: 60 | return None 61 | 62 | def makeBinarySearchTree(nums): 63 | mid = len(nums) // 2 64 | 65 | root = TreeNode(nums[mid]) 66 | left = nums[:mid] 67 | right = nums[mid+1:] 68 | 69 | if left: 70 | root.left = makeBinarySearchTree(left) 71 | if right: 72 | root.right = makeBinarySearchTree(right) 73 | 74 | return root 75 | 76 | root = makeBinarySearchTree(nums) 77 | return root 78 | 79 | -------------------------------------------------------------------------------- /Tree/KthSmallestElementInABST.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a binary search tree, write a function kthSmallest to find the kth smallest element in it. 3 | 4 | Note: 5 | You may assume k is always valid, 1 ≤ k ≤ BST's total elements. 6 | 7 | Example 1: 8 | 9 | Input: root = [3,1,4,null,2], k = 1 10 | 3 11 | / \ 12 | 1 4 13 | \ 14 | 2 15 | Output: 1 16 | Example 2: 17 | 18 | Input: root = [5,3,6,2,4,null,null,1], k = 3 19 | 5 20 | / \ 21 | 3 6 22 | / \ 23 | 2 4 24 | / 25 | 1 26 | Output: 3 27 | Follow up: 28 | What if the BST is modified (insert/delete operations) often and you need to find the kth smallest frequently? How would you optimize the kthSmallest routine? 29 | 30 | 取出二叉搜索树中第 k 小的数据。 31 | 就这一条来看用 inorder 即可。 32 | 33 | 进阶条件是如果这颗树经常进行 插入/删除操作如何去优化它呢? 34 | 以下是思考: 35 | 36 | 一颗相对平衡的 BST 的优势在于:可以在 O(log n) 时间内查找/插入/删除某些数据。 37 | 38 | 就查找这一个条件来说构建一个 排序过的数组是可以达到 O(log n) 的需求的。 但是插入和删除对于数组来说都是 O(n)级别的。 39 | 40 | Discuss里有讨论说可以记录 第 k ,第 k-1 个。若插入的比 k 大那么不变,否则k就变为 k-1,然后在重新计算 k - 1。这样也是部分优化。 41 | 待解决。 42 | 43 | 非进阶的: 44 | beat 78% 48ms。 45 | 46 | 测试地址: 47 | https://leetcode.com/problems/kth-smallest-element-in-a-bst/description/ 48 | 49 | 50 | 51 | """ 52 | # Definition for a binary tree node. 53 | # class TreeNode(object): 54 | # def __init__(self, x): 55 | # self.val = x 56 | # self.left = None 57 | # self.right = None 58 | 59 | class Solution: 60 | 61 | def find_data(self, root: TreeNode): 62 | 63 | if root is None: 64 | return 65 | Solution.find_data(self,root.left) 66 | self.data.append(root.val) 67 | Solution.find_data(self,root.right) 68 | return 69 | 70 | def kthSmallest(self, root: TreeNode, k: int) -> int: 71 | self.data = [] 72 | Solution.find_data(self, root) 73 | return self.data[k-1] 74 | -------------------------------------------------------------------------------- /Tree/LowestCommonAncestorOfABinarySearchTree.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST. 3 | 4 | According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).” 5 | 6 | Given binary search tree: root = [6,2,8,0,4,7,9,null,null,3,5] 7 | 8 | _______6______ 9 | / \ 10 | ___2__ ___8__ 11 | / \ / \ 12 | 0 _4 7 9 13 | / \ 14 | 3 5 15 | Example 1: 16 | 17 | Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 18 | Output: 6 19 | Explanation: The LCA of nodes 2 and 8 is 6. 20 | Example 2: 21 | 22 | Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4 23 | Output: 2 24 | Explanation: The LCA of nodes 2 and 4 is 2, since a node can be a descendant of itself 25 | according to the LCA definition. 26 | Note: 27 | 28 | All of the nodes' values will be unique. 29 | p and q are different and both values will exist in the BST. 30 | 31 | 32 | 给定一颗 BST,找到两个子节点的最小公共祖先。 33 | 用普通的树的方法也是可以的,不过可以做个剪枝优化。 34 | 35 | 因为 BST 我们知道每个节点的左右子节点的范围。 36 | 37 | 1. 如果处于 root 左右,那么直接返回即可。 38 | 2. 如果都小于,那么去找左子树。 39 | 3. 如果都大,那么去找右子树。 40 | 41 | 在寻找过程中, 42 | 4. 只要有一个命中了,那么直接返回当前节点即可。因为剩下的那个节点只有可能在它的子树中,如果不在它的子树中也不会执行到这一步。 43 | 44 | beat 99% 45 | 46 | 测试地址: 47 | https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/description/ 48 | 49 | """ 50 | # Definition for a binary tree node. 51 | # class TreeNode(object): 52 | # def __init__(self, x): 53 | # self.val = x 54 | # self.left = None 55 | # self.right = None 56 | 57 | class Solution(object): 58 | def lowestCommonAncestor(self, root, p, q): 59 | """ 60 | :type root: TreeNode 61 | :type p: TreeNode 62 | :type q: TreeNode 63 | :rtype: TreeNode 64 | """ 65 | 66 | if p.val == root.val or q.val == root.val: 67 | return root 68 | 69 | if p.val < root.val and q.val > root.val: 70 | return root 71 | elif p.val > root.val and q.val < root.val: 72 | return root 73 | 74 | if p.val > root.val and q.val > root.val: 75 | 76 | return self.lowestCommonAncestor(root.right, p, q) 77 | 78 | else: 79 | return self.lowestCommonAncestor(root.left, p, q) 80 | -------------------------------------------------------------------------------- /Tree/PathSumII.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum. 3 | 4 | Note: A leaf is a node with no children. 5 | 6 | Example: 7 | 8 | Given the below binary tree and sum = 22, 9 | 10 | 5 11 | / \ 12 | 4 8 13 | / / \ 14 | 11 13 4 15 | / \ / \ 16 | 7 2 5 1 17 | Return: 18 | 19 | [ 20 | [5,4,11,2], 21 | [5,8,4,5] 22 | ] 23 | 24 | PathSum 的进阶版,输出所有符合条件的路径。所以这里直接用遍历,有负数加上不是二叉搜索树应该没太多需要优化的地方。 25 | 26 | 测试用例: 27 | https://leetcode.com/problems/path-sum-ii/description/ 28 | 29 | """ 30 | # Definition for a binary tree node. 31 | # class TreeNode(object): 32 | # def __init__(self, x): 33 | # self.val = x 34 | # self.left = None 35 | # self.right = None 36 | 37 | class Solution(object): 38 | def pathSum(self, root, sum): 39 | """ 40 | :type root: TreeNode 41 | :type sum: int 42 | :rtype: List[List[int]] 43 | """ 44 | if not root: 45 | return [] 46 | 47 | result = [] 48 | 49 | def helper(prev, root, sum, path): 50 | if prev + root.val == sum: 51 | if not root.left and not root.right: 52 | result.append(list(map(int, path.split(' ')[1:]))+[root.val]) 53 | return True 54 | 55 | if root.left: 56 | helper(prev + root.val, root.left, sum, path=path+" "+str(root.val)) 57 | # return True 58 | 59 | if root.right: 60 | helper(prev + root.val, root.right, sum, path=path+" "+str(root.val)) 61 | 62 | return False 63 | 64 | helper(0, root, sum, "") 65 | 66 | return result 67 | -------------------------------------------------------------------------------- /Tree/PopulatingNextRightPointersInEachNode.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a binary tree 3 | 4 | struct TreeLinkNode { 5 | TreeLinkNode *left; 6 | TreeLinkNode *right; 7 | TreeLinkNode *next; 8 | } 9 | Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL. 10 | 11 | Initially, all next pointers are set to NULL. 12 | 13 | Note: 14 | 15 | You may only use constant extra space. 16 | Recursive approach is fine, implicit stack space does not count as extra space for this problem. 17 | You may assume that it is a perfect binary tree (ie, all leaves are at the same level, and every parent has two children). 18 | Example: 19 | 20 | Given the following perfect binary tree, 21 | 22 | 1 23 | / \ 24 | 2 3 25 | / \ / \ 26 | 4 5 6 7 27 | After calling your function, the tree should look like: 28 | 29 | 1 -> NULL 30 | / \ 31 | 2 -> 3 -> NULL 32 | / \ / \ 33 | 4->5->6->7 -> NULL 34 | 35 | 36 | 给一颗二叉树,二叉树是满二叉树,每个节点默认 next 为 None,将每个节点的 next 指向它右边的一个。 37 | 38 | 需要使用 O(1)空间.. 39 | 40 | O(1) 空间没什么思路,目前用的两个列表存放Node. 41 | 42 | 也就是BFS. 43 | 44 | beat 88% 45 | 46 | 测试地址: 47 | https://leetcode.com/problems/populating-next-right-pointers-in-each-node/description/ 48 | 49 | """ 50 | # Definition for binary tree with next pointer. 51 | # class TreeLinkNode: 52 | # def __init__(self, x): 53 | # self.val = x 54 | # self.left = None 55 | # self.right = None 56 | # self.next = None 57 | 58 | class Solution: 59 | # @param root, a tree link node 60 | # @return nothing 61 | def connect(self, root): 62 | if not root: 63 | return 64 | 65 | current = [root] 66 | next_nodes = [] 67 | 68 | while current or next_nodes: 69 | for i in current: 70 | if i.left: 71 | if next_nodes: 72 | next_nodes[-1].next = i.left 73 | 74 | next_nodes.append(i.left) 75 | if i.right: 76 | if next_nodes: 77 | next_nodes[-1].next = i.right 78 | 79 | next_nodes.append(i.right) 80 | 81 | current = next_nodes 82 | next_nodes = [] 83 | -------------------------------------------------------------------------------- /Tree/PopulatingNextRightPointersInEachNodeII.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a binary tree 3 | 4 | struct TreeLinkNode { 5 | TreeLinkNode *left; 6 | TreeLinkNode *right; 7 | TreeLinkNode *next; 8 | } 9 | Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL. 10 | 11 | Initially, all next pointers are set to NULL. 12 | 13 | Note: 14 | 15 | You may only use constant extra space. 16 | Recursive approach is fine, implicit stack space does not count as extra space for this problem. 17 | Example: 18 | 19 | Given the following binary tree, 20 | 21 | 1 22 | / \ 23 | 2 3 24 | / \ \ 25 | 4 5 7 26 | After calling your function, the tree should look like: 27 | 28 | 1 -> NULL 29 | / \ 30 | 2 -> 3 -> NULL 31 | / \ \ 32 | 4-> 5 -> 7 -> NULL 33 | 34 | 使用 BFS 和列表的额外空间的话 I 和 II没有任何区别... 35 | 36 | 待添加 O(1) 空间算法。 37 | 38 | beat 72%. 39 | 40 | 测试地址: 41 | https://leetcode.com/problems/populating-next-right-pointers-in-each-node-ii/description/ 42 | 43 | """ 44 | # Definition for binary tree with next pointer. 45 | # class TreeLinkNode: 46 | # def __init__(self, x): 47 | # self.val = x 48 | # self.left = None 49 | # self.right = None 50 | # self.next = None 51 | 52 | class Solution: 53 | # @param root, a tree link node 54 | # @return nothing 55 | def connect(self, root): 56 | if not root: 57 | return 58 | 59 | current = [root] 60 | next_nodes = [] 61 | 62 | while current or next_nodes: 63 | for i in current: 64 | if i.left: 65 | if next_nodes: 66 | next_nodes[-1].next = i.left 67 | 68 | next_nodes.append(i.left) 69 | if i.right: 70 | if next_nodes: 71 | next_nodes[-1].next = i.right 72 | 73 | next_nodes.append(i.right) 74 | 75 | current = next_nodes 76 | next_nodes = [] 77 | -------------------------------------------------------------------------------- /Tree/SumRootToLeafNumbers.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number. 3 | 4 | An example is the root-to-leaf path 1->2->3 which represents the number 123. 5 | 6 | Find the total sum of all root-to-leaf numbers. 7 | 8 | Note: A leaf is a node with no children. 9 | 10 | Example: 11 | 12 | Input: [1,2,3] 13 | 1 14 | / \ 15 | 2 3 16 | Output: 25 17 | Explanation: 18 | The root-to-leaf path 1->2 represents the number 12. 19 | The root-to-leaf path 1->3 represents the number 13. 20 | Therefore, sum = 12 + 13 = 25. 21 | Example 2: 22 | 23 | Input: [4,9,0,5,1] 24 | 4 25 | / \ 26 | 9 0 27 | / \ 28 | 5 1 29 | Output: 1026 30 | Explanation: 31 | The root-to-leaf path 4->9->5 represents the number 495. 32 | The root-to-leaf path 4->9->1 represents the number 491. 33 | The root-to-leaf path 4->0 represents the number 40. 34 | Therefore, sum = 495 + 491 + 40 = 1026. 35 | 36 | 给一只二叉树,输出所有从根到叶路径的总和。 37 | O(n) 遍历。 字符串 -> 数字 -> 求和。 38 | 39 | 测试用例: 40 | https://leetcode.com/problems/sum-root-to-leaf-numbers/description/ 41 | 42 | 24 ms beat 75% 43 | 44 | """ 45 | # Definition for a binary tree node. 46 | # class TreeNode(object): 47 | # def __init__(self, x): 48 | # self.val = x 49 | # self.left = None 50 | # self.right = None 51 | 52 | class Solution(object): 53 | def sumNumbers(self, root): 54 | """ 55 | :type root: TreeNode 56 | :rtype: int 57 | """ 58 | 59 | result = [] 60 | if not root: 61 | return 0 62 | 63 | def helper(root, string): 64 | if not root.left and not root.right: 65 | result.append(int(string+str(root.val))) 66 | return 67 | 68 | if root.left: 69 | helper(root.left, string+str(root.val)) 70 | 71 | if root.right: 72 | helper(root.right, string+str(root.val)) 73 | helper(root, '') 74 | return sum(result) 75 | -------------------------------------------------------------------------------- /Tree/SymmetricTree.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). 3 | 4 | For example, this binary tree [1,2,2,3,4,4,3] is symmetric: 5 | 6 | 1 7 | / \ 8 | 2 2 9 | / \ / \ 10 | 3 4 4 3 11 | But the following [1,2,2,null,3,null,3] is not: 12 | 1 13 | / \ 14 | 2 2 15 | \ \ 16 | 3 3 17 | Note: 18 | Bonus points if you could solve it both recursively and iteratively. 19 | 20 | 21 | 判断左子树是否与右子树互为镜像。 22 | 23 | 思路: 24 | 遍历左子树,把结果放入队列中。 25 | 按照相反的左右遍历右子树,同时让压出队列顶的一项作对比。 26 | 不匹配或队列中没有足够的数据都可判为False. 27 | 28 | 效率 O(n) 29 | beat 100%. 30 | 31 | 测试地址: 32 | https://leetcode.com/problems/symmetric-tree/description/ 33 | 34 | """ 35 | # Definition for a binary tree node. 36 | # class TreeNode(object): 37 | # def __init__(self, x): 38 | # self.val = x 39 | # self.left = None 40 | # self.right = None 41 | 42 | class Solution(object): 43 | def isSymmetric(self, root): 44 | """ 45 | :type root: TreeNode 46 | :rtype: bool 47 | """ 48 | if not root: 49 | return True 50 | 51 | left = root.left 52 | right = root.right 53 | 54 | left_node = [left] 55 | right_node = [right] 56 | 57 | left_node_value = [] 58 | 59 | while left_node: 60 | # if left_node: 61 | _left = left_node.pop() 62 | if _left: 63 | left_node_value.append(_left.val) 64 | else: 65 | left_node_value.append(None) 66 | 67 | if _left: 68 | left_node.append(_left.right) 69 | left_node.append(_left.left) 70 | 71 | left_node_value.reverse() 72 | 73 | while right_node: 74 | _right = right_node.pop() 75 | 76 | if left_node_value: 77 | left_value = left_node_value.pop() 78 | else: 79 | return False 80 | 81 | if _right: 82 | if left_value != _right.val: 83 | return False 84 | else: 85 | if left_value != None: 86 | return False 87 | 88 | if _right: 89 | right_node.append(_right.left) 90 | right_node.append(_right.right) 91 | return True 92 | -------------------------------------------------------------------------------- /Tree/ValidateBinarySearchTree.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a binary tree, determine if it is a valid binary search tree (BST). 3 | 4 | Assume a BST is defined as follows: 5 | 6 | The left subtree of a node contains only nodes with keys less than the node's key. 7 | The right subtree of a node contains only nodes with keys greater than the node's key. 8 | Both the left and right subtrees must also be binary search trees. 9 | Example 1: 10 | 11 | Input: 12 | 2 13 | / \ 14 | 1 3 15 | Output: true 16 | Example 2: 17 | 18 | 5 19 | / \ 20 | 1 4 21 | / \ 22 | 3 6 23 | Output: false 24 | Explanation: The input is: [5,1,4,null,null,3,6]. The root node's value 25 | is 5 but its right child's value is 4. 26 | 27 | 28 | 验证是否为有效的 二叉搜索树。 29 | 30 | 二叉搜索树的定义是: 31 | 右边的小于父节点,左边的大于父节点,对于每一个节点都是同样的规则。 32 | 33 | 思路: 34 | 直接中序遍历,中序遍历的二叉搜索树会以排序好的形式返回,返回的同时判断是否比上一个要大,若小于或相等,那么就表示这不是一颗二叉搜索树。 35 | 36 | 递归..O(n) 时间复杂度。 37 | 38 | 测试链接: 39 | https://leetcode.com/problems/validate-binary-search-tree/description/ 40 | 41 | beat 100% 36ms. 42 | 43 | """ 44 | # Definition for a binary tree node. 45 | # class TreeNode(object): 46 | # def __init__(self, x): 47 | # self.val = x 48 | # self.left = None 49 | # self.right = None 50 | 51 | class Solution(object): 52 | def isValidBST(self, root): 53 | """ 54 | :type root: TreeNode 55 | :rtype: bool 56 | """ 57 | if not root: 58 | return True 59 | 60 | self.prev = -float('inf') 61 | 62 | def inOrderTraversal(root): 63 | 64 | if root.left: 65 | if inOrderTraversal(root.left) == -1: 66 | return -1 67 | 68 | if root.val <= self.prev: 69 | return -1 70 | 71 | self.prev = root.val 72 | 73 | if root.right: 74 | if inOrderTraversal(root.right) == -1: 75 | return -1 76 | if inOrderTraversal(root) == -1: 77 | return False 78 | return True 79 | --------------------------------------------------------------------------------