├── String ├── ACAuto │ └── README.md ├── string-match │ ├── BF │ │ └── README.md │ ├── BM │ │ └── README.md │ ├── KMP │ │ └── README.md │ └── RK │ │ └── README.md ├── README.md ├── LengthOfLongestSubstring │ ├── README.md │ └── index.js ├── ReverseString │ └── README.md ├── ReverseWords │ └── README.md ├── StringToInteger │ └── README.md └── longest-palindromic-substring │ └── index.js ├── Sort ├── 03.MergeSort │ ├── README.md │ └── MergeSort.js ├── 05.BucketSort │ └── README.md ├── 07.RadixSort │ └── README.md ├── 02.InsertionSort │ ├── README.md │ └── InsertionSort.js ├── 06.CountingSort │ └── README.md ├── 01.BubbleSort │ ├── README.md │ └── BubbleSort.js ├── README.md ├── 08.SortColors │ ├── sortColors.cpp │ └── README.md ├── 09.SelectionSort │ └── SelectionSort.js └── 04.QuickSort │ └── QuickSort.js ├── Queue ├── 01.ArrayQueue │ └── README.md ├── 02.LinkedListQueue │ └── README.md ├── README.md ├── 04.CircularDeque │ ├── README.md │ ├── CircularDeque.hpp │ ├── CircularDeque.py │ ├── desisn-circular-deque-2.go │ └── desisn-circular-deque.go ├── 05.SlidingWindowMaximum │ ├── SlidingWindowMaximum.cpp │ ├── README.md │ └── SlidingWindowMaximum.js └── 03.QueueUsingStacks │ ├── README.md │ ├── QueueUsingStacks.php │ └── implementQueueUsingStacks.hpp ├── Stack ├── 01.ArrayStack │ ├── README.md │ └── Stack.js ├── 02.LinkedListStack │ └── README.md ├── README.md ├── 03.ValidParentheses │ ├── validParentheses.js │ ├── validParentheses.cpp │ ├── valid_parentheses.go │ └── README.md ├── 04.LongestValidParentheses │ ├── longestvalidparentheses.js │ ├── README.md │ └── longestvalidparentheses.cpp └── 05.EvaluateReversePolishNotation │ ├── README.md │ ├── evaluateReversePolishNotation.cpp │ └── evaluate_reverse_polish_notation.go ├── dp ├── BuyAndSellStock │ ├── buyAndSellStock.js │ └── README.md ├── EditDistance │ ├── README.md │ └── editDistance.js ├── README.md ├── LongestIncreasingSubsequence │ ├── README.md │ └── lis.js ├── ClimbingStairs │ ├── climb-stairs.go │ └── README.md ├── MinimumPathSum │ ├── README.md │ └── minimumPathSum.js ├── CoinChange │ └── README.md ├── Triangle │ └── README.md └── regular-expression-matching │ ├── index.js │ └── README.md ├── LinkedList ├── ReverseLinkedList │ ├── ReverseLinkedList.js │ ├── ReverseLinkedList.py │ ├── README.md │ ├── ReverseLinkedList.php │ └── ReverseLinkedList.cpp ├── README.md ├── LinkedListCycle │ ├── LinkedListCycle.cpp │ ├── LinkedListCycle.py │ ├── linked_list_cycle.go │ ├── LinkedListCycle.java │ └── README.md ├── LinkedListCycle2 │ ├── LinkedListCycle2.cpp │ ├── LinkedListCycle2.py │ └── README.md ├── MergeSortedLists │ ├── MergeSortedLists.py │ ├── README.md │ ├── MergeSortedLists.cpp │ └── MergeSortedLists.php ├── MergeKSortedLists │ ├── README.md │ ├── ListNode.java │ ├── MergeKSortedLists.java │ ├── MergeKSortedLists.php │ └── MergeKSortedLists.cpp └── ReverseNodesKGroup │ ├── ReverseNodesKGroup.php │ ├── README.md │ ├── ReverseNodesKGroup.cpp │ └── ReverseNodesKGroup.js ├── DivideAndConquer ├── 1.ClosestPairOfPoints │ ├── ClosestPairOfPoints.c │ └── README.md └── README.md ├── banner.png ├── .gitignore ├── Graph ├── README.md ├── 01.NumberOfIslands │ └── README.md └── 02.ValidSudoku │ └── README.md ├── Array ├── SingleNumber │ ├── SingleNumber.cpp │ ├── SingleNumber.js │ └── README.md ├── FizzBuzz │ ├── FizzBuzz.py │ ├── FizzBuzz.cpp │ └── README.md ├── MajorityElement │ ├── MajorityElement.cpp │ ├── majority_elements.go │ ├── MajorityElement.java │ ├── README.md │ └── MajorityElement.js ├── FirstMissingPositive │ ├── FirstMissingPositive.py │ ├── FirstMissingPositive.cpp │ ├── index.js │ └── README.md ├── FindAllDuplicates │ ├── FindAllDuplicates.cpp │ ├── FindAllDuplicates.js │ ├── README.md │ └── FindAllDuplicates.py ├── TwoSum │ ├── TwoSum.py │ ├── TwoSum.cpp │ ├── TwoSum.js │ ├── TwoSum.java │ └── README.md ├── NextPremutation │ ├── README.md │ ├── NextPremutation.cpp │ └── NextPremutation.js ├── README.md ├── MergeSortedArray │ ├── MergeSortedArray.cpp │ ├── MergeSortedArray.py │ └── README.md ├── ThreeSum │ ├── README.md │ ├── ThreeSum.js │ ├── ThreeSum.cpp │ ├── ThreeSum.py │ ├── ThreeSum.java │ └── three_sum.go └── KthLargestElement │ ├── index.js │ ├── KthLargestElement.cpp │ ├── KthLargestElement.py │ └── README.md ├── BackTracking ├── README.md ├── 02.Permutations │ └── README.md ├── 01.N-Queens │ ├── README.md │ └── N-Queens.py └── 03.RegularExpressingMatching │ ├── regular-expression-matching.go │ └── README.md ├── Search ├── README.md ├── 01.LowestCommonAncestor │ └── README.md ├── 02.Sqrt │ └── README.md ├── 03.WordSearch │ └── README.md ├── 07.01Matrix │ └── README.md ├── 04.WordSearch2 │ └── README.md ├── 05.SearchInRotatedArray │ └── README.md └── 06.SearchA2DMatrix │ └── README.md ├── BinaryTree ├── 01.SameTree │ ├── SameTree.py │ └── README.md ├── 02.SymmetricTree │ ├── symmetricTree.js │ └── README.md ├── 10.FindLargestValue │ └── README.md ├── 04.MaximumDepthOfBinaryTree │ └── README.md ├── 11.PathSum │ └── README.md ├── 08.FlattenBinaryTreeToLinkedList │ └── README.md ├── 09.BinaryTreeLevelTraversal │ └── README.md ├── 03.InvertBinaryTree │ └── README.md ├── 12.ConvertToBinarySearchTree │ └── README.md ├── 07.ConvertSortedListToBinarySearchTree │ └── README.md ├── README.md ├── 05.BalancedBinaryTree │ └── README.md └── 06.ValidateBinarySearchTree │ └── README.md └── README.md /String/ACAuto/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Sort/03.MergeSort/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Sort/05.BucketSort/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Sort/07.RadixSort/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Queue/01.ArrayQueue/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Sort/02.InsertionSort/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Sort/06.CountingSort/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Stack/01.ArrayStack/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /String/string-match/BF/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /String/string-match/BM/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /String/string-match/KMP/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /String/string-match/RK/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Queue/02.LinkedListQueue/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Stack/02.LinkedListStack/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dp/BuyAndSellStock/buyAndSellStock.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /LinkedList/ReverseLinkedList/ReverseLinkedList.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /DivideAndConquer/1.ClosestPairOfPoints/ClosestPairOfPoints.c: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iostalks/Algorithms/HEAD/banner.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | tags 6 | tags.* 7 | idea.* 8 | .idea 9 | -------------------------------------------------------------------------------- /DivideAndConquer/README.md: -------------------------------------------------------------------------------- 1 | # Divide andn Conquer(分治算法) 2 | 3 | [1. ClosestPairOfPoints(平面内两点的最短距离)](./1.ClosestPairOfPoints) 4 | -------------------------------------------------------------------------------- /Graph/README.md: -------------------------------------------------------------------------------- 1 | # 图 2 | 3 | [01. Number of Islands(岛屿的个数)](./01.NumberOfIslands) 4 | 5 | [02. Valid Sudoku(有效的数独)](./02.ValidSudoku) 6 | -------------------------------------------------------------------------------- /String/README.md: -------------------------------------------------------------------------------- 1 | # String(字符串) 2 | 3 | - [ReverseString](./ReverseString) 4 | 5 | - [LengthOfLongestSubstring](./LengthOfLongestSubstring) 6 | -------------------------------------------------------------------------------- /Array/SingleNumber/SingleNumber.cpp: -------------------------------------------------------------------------------- 1 | 2 | class Solution { 3 | public: 4 | int singleNumber(vector& nums) { 5 | int res = 0; 6 | for(auto num : nums) { res^=num; } 7 | return res; 8 | } 9 | }; -------------------------------------------------------------------------------- /BackTracking/README.md: -------------------------------------------------------------------------------- 1 | # BackTracking(回溯算法) 2 | 3 | [01.N-Queens(N 皇后)](./01.N-Queens) 4 | 5 | [02. Permutations (全排列)](./02.Permutations) 6 | 7 | [03. Regular Expression Matching(正则表达式匹配)](./03.RegularExpressingMatching) 8 | -------------------------------------------------------------------------------- /Array/FizzBuzz/FizzBuzz.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def fizzBuzz(self, n): 3 | """ 4 | :type n: int 5 | :rtype: List[str] 6 | """ 7 | return ['Fizz' * (not i % 3) + 'Buzz' * (not i % 5) or str(i) for i in xrange(1, n + 1)] 8 | -------------------------------------------------------------------------------- /Sort/01.BubbleSort/README.md: -------------------------------------------------------------------------------- 1 | # Bubble Sort(冒泡排序实现) 2 | ## 特点 3 | 4 | ## 代码实现 5 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 6 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 7 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 8 | 9 | -------------------------------------------------------------------------------- /Array/MajorityElement/MajorityElement.cpp: -------------------------------------------------------------------------------- 1 | 2 | class Solution { 3 | public: 4 | int majorityElement(vector& nums) { 5 | int major; 6 | int count = 0; 7 | for(auto num : nums) { 8 | if(count == 0) { major = num; } 9 | count += (num == major) ? 1 : -1; 10 | } 11 | return major; 12 | } 13 | }; -------------------------------------------------------------------------------- /Array/SingleNumber/SingleNumber.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number} 4 | */ 5 | var singleNumber = function(nums) { 6 | let result = 0; 7 | nums.forEach((num) => { result ^= num; }); 8 | return result; 9 | }; 10 | 11 | // 方法二,使用 reduce 12 | var singleNumber = function(nums) { 13 | return nums.reduce((res, ele) => res^ele , 0); 14 | } -------------------------------------------------------------------------------- /LinkedList/README.md: -------------------------------------------------------------------------------- 1 | # LinkedList 2 | 3 | - [Reverse Linked List](./ReverseLinkedList) 4 | 5 | - [Linked List Cycle](./LinkedListCycle) 6 | 7 | - [Lnked List Cycle II](./LinkedListCycle2) 8 | 9 | - [Merge Two Sorted Lists](./MergeSortedLists) 10 | 11 | - [Merge k Sorted Lists](./MergeKSortedLists) 12 | 13 | - [Reverse Nodes in k-Group](./ReverseNodesKGroup) 14 | -------------------------------------------------------------------------------- /LinkedList/LinkedListCycle/LinkedListCycle.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | bool hasCycle(ListNode *head) { 4 | ListNode *fast = head, *slow = head; 5 | while(fast && fast->next) { 6 | fast = fast->next->next; 7 | slow = slow->next; 8 | if(fast == slow) { return true; } 9 | } 10 | return false; 11 | } 12 | }; -------------------------------------------------------------------------------- /Queue/README.md: -------------------------------------------------------------------------------- 1 | # Queue(队列) 2 | 3 | [01. Implement Queue by Array(用数组实现队列)](./01.ArrayQueue) 4 | 5 | [02. Implement Queue by LinkedList(用链表实现队列)](./02.LinkedListQueue) 6 | 7 | [03. Implement Queue using Stacks(用栈实现队列)](./03.QueueUsingStacks) 8 | 9 | [04. Design Circular Deque(设计一个双端队列)](./04.CircularDeque) 10 | 11 | [05. Sliding Window Maximum(滑动窗口最大值)](./05.SlidingWindowMaximum) 12 | -------------------------------------------------------------------------------- /dp/EditDistance/README.md: -------------------------------------------------------------------------------- 1 | # 72. Edit Distance 2 | 3 | - [英文版](https://leetcode.com/problems/edit-distance/) 4 | 5 | - [中文版](https://leetcode-cn.com/problems/edit-distance/) 6 | 7 | ## 代码实现 8 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 9 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 10 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 11 | 12 | -------------------------------------------------------------------------------- /Stack/README.md: -------------------------------------------------------------------------------- 1 | # Stack(栈) 2 | 3 | [01. Implement Stack by Array(数组实现栈)](./01.ArrayStack) 4 | 5 | [02. Implement Stack by LinkedList(链表实现栈)](./02.LinkedListStack) 6 | 7 | [03. Valid Parentheses(有效的括号)](./03.ValidParentheses) 8 | 9 | [04. Longest Valid Parentheses(最长有效括号)](./04.LongestValidParentheses) 10 | 11 | [05. Evaluate Reverse Polish Notatio(逆波兰表达式求值)](./05.EvaluateReversePolishNotation) 12 | -------------------------------------------------------------------------------- /Array/FirstMissingPositive/FirstMissingPositive.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def firstMissingPositive(self, nums): 3 | """ 4 | :type nums: List[int] 5 | :rtype: int 6 | """ 7 | if not nums: return 1 8 | 9 | length = len(nums) + 1 10 | for x in range(1, length): 11 | if x not in nums: 12 | return x 13 | return length 14 | -------------------------------------------------------------------------------- /Array/FindAllDuplicates/FindAllDuplicates.cpp: -------------------------------------------------------------------------------- 1 | 2 | class Solution { 3 | public: 4 | vector findDuplicates(vector& nums) { 5 | vector res; 6 | for(int i=0; i len(nums)/2 { 14 | return num 15 | } 16 | } 17 | 18 | panic("no majority element found") 19 | } 20 | -------------------------------------------------------------------------------- /Sort/README.md: -------------------------------------------------------------------------------- 1 | # Sort(排序) 2 | 3 | [01. Bubble Sort(冒泡排序实现)](./01.BubbleSort) 4 | 5 | [02. Insertion Sort(插入排序实现)](./02.InsertionSort) 6 | 7 | [03. Merge Sort(并归排序实现)](./03.MergeSort) 8 | 9 | [04. Quick Sort(快速排序实现)](./04.QuickSort) 10 | 11 | [05. Bucket Sort(桶排序实现)](./05.BucketSort) 12 | 13 | [06. Counting Sort(计数排序实现)](./06.CountingSort) 14 | 15 | [07. Radix Sort(基数排序实现)](./07.RadixSort) 16 | 17 | [08. Sort Colors(颜色分类)](./08.SortColors) 18 | -------------------------------------------------------------------------------- /LinkedList/LinkedListCycle/LinkedListCycle.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def hasCycle(self, head): 3 | """ 4 | :type head: ListNode 5 | :rtype: bool 6 | """ 7 | 8 | fast = head 9 | slow = head 10 | while fast and fast.next and fast.next.next: 11 | slow = slow.next 12 | fast = fast.next.next 13 | if fast == slow: 14 | return True 15 | return False 16 | -------------------------------------------------------------------------------- /Array/FindAllDuplicates/FindAllDuplicates.js: -------------------------------------------------------------------------------- 1 | const findDuplicates = (nums) => { 2 | const res = []; 3 | for (let i = 0; i < nums.length; ++i) { 4 | const index = Math.abs(nums[i]) - 1; 5 | if (nums[index] < 0) { 6 | res.push(Math.abs(index) + 1); 7 | } else { 8 | nums[index] = -nums[index] 9 | } 10 | } 11 | return res; 12 | } 13 | 14 | const r = findDuplicates([1,2,3,2,7,5,6,1]); 15 | console.log(r); 16 | 17 | -------------------------------------------------------------------------------- /Search/README.md: -------------------------------------------------------------------------------- 1 | # Search(查找、搜索) 2 | 3 | [01. Lowest Common Ancestor of a Binary Search Tree(二叉搜索树的最近公共祖先)](./01.LowestCommonAncestor) 4 | 5 | [02. Sqrt(x) (x 的平方根)](./02.Sqrt) 6 | 7 | [03. Word Search(单词搜索)](./03.WordSearch) 8 | 9 | [04. Word Search II(单词搜索 II)](./04.WordSearch2) 10 | 11 | [05. Search in Rotated Sorted Array(搜索旋转排序数组)](./05.SearchInRotatedArray) 12 | 13 | [06. Search a 2D Matrix(搜索二维矩阵)](./06.SearchA2DMatrix) 14 | 15 | [07. Matrix(01 矩阵)](./07.01Matrix) 16 | -------------------------------------------------------------------------------- /Array/TwoSum/TwoSum.py: -------------------------------------------------------------------------------- 1 | # O(n) 2 | class Solution(object): 3 | def twoSum(self, nums, target): 4 | """ 5 | :type nums: List[int] 6 | :type target: int 7 | :rtype: List[int] 8 | """ 9 | 10 | numberIndexDict = {} 11 | for i, x in enumerate(nums): 12 | y = target - x 13 | if y in numberIndexDict: 14 | return [numberIndexDict[y], i] 15 | # 存下标 16 | numberIndexDict[x] = i 17 | -------------------------------------------------------------------------------- /Stack/01.ArrayStack/Stack.js: -------------------------------------------------------------------------------- 1 | class Stack { 2 | constructor() { 3 | this.items = []; 4 | } 5 | 6 | push(element) { 7 | this.items.push(element); 8 | } 9 | 10 | pop() { 11 | return this.items.pop(); 12 | } 13 | 14 | peek() { 15 | return this.items[this.size() - 1]; 16 | } 17 | 18 | isEmpty() { 19 | return this.size() === 0; 20 | } 21 | 22 | size() { 23 | return this.items.length; 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /dp/README.md: -------------------------------------------------------------------------------- 1 | # 动态规划(Dynamic Programming) 2 | 3 | [Minimum Path Sum(最小路径和)](./MinimumPathSum) 4 | 5 | [Coin Change (零钱兑换)](./CoinChange) 6 | 7 | [Best Time to Buy and Sell Stock(买卖股票的最佳时机)](./BuyAndSellStock) 8 | 9 | [Climbing Stairs(爬楼梯)](./ClimbingStairs) 10 | 11 | [Triangle(三角形最小路径和)](./Triangle) 12 | 13 | [EditDistance(最短编辑距离](./EditDistance) 14 | 15 | [Longest Increating Subseque(最长子序列)](./LongestIncreasingSubsequence) 16 | 17 | [Regular Expression Matching(正则表达式匹配)](./regular-expression-matching) -------------------------------------------------------------------------------- /Array/NextPremutation/README.md: -------------------------------------------------------------------------------- 1 | 2 | https://leetcode.com/problems/next-permutation/ 3 | 4 | 思路: 5 | 1. 从右往左查找,找到第一个破坏递增序列的数,所在的下标 k,如果没找到返回原序列的逆序列; 6 | 2. 在 k 下标的右侧查找比 nums[k] 大的,下标最大的数 nums[l]; 7 | 3. 交换 nums[l] 和 nums[k]; 8 | 4. 将 k 下标之后的元素,从小到大排序。 9 | 10 | ## 代码实现 11 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 12 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 13 | | 🤔 | [😀](./NextPremutation.cpp) | 🤔 | 🤔 | 🤔 | 🤔 | [😀](./NextPremutation.js) | 🤔 | 🤔 | -------------------------------------------------------------------------------- /dp/LongestIncreasingSubsequence/README.md: -------------------------------------------------------------------------------- 1 | # Longest Increasing Subsequence 2 | 3 | LeetCode 300 4 | 5 | - [英文版](https://leetcode.com/problems/longest-increasing-subsequence/) 6 | 7 | ## 题目 8 | 9 | ## 思路 10 |
11 | 点击展开 12 | // TODO 13 |
14 | 15 | ## 代码实现 16 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 17 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 18 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Array/README.md: -------------------------------------------------------------------------------- 1 | # Array 2 | 3 | - [Two Sum](./TwoSum) 4 | 5 | - [Three Sum](./ThreeSum) 6 | 7 | - [Majority Element](./MajorityElement) 8 | 9 | - [FizzBuzz](./FizzBuzz) 10 | 11 | - [Merge Sorted Array](./MergeSortedArray) 12 | 13 | - [First Missing Positive](./FirstMissingPositive) 14 | 15 | - [Kth Largest Element in an Array](./KthLargestElement) 16 | 17 | - [Single Number](./SingleNumber) 18 | 19 | - [Find All Duplicates in an Array](./FindAllDuplicates) 20 | 21 | - [Next Premutation](./NextPremutation) 22 | -------------------------------------------------------------------------------- /LinkedList/LinkedListCycle/linked_list_cycle.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type ListNode struct { 4 | Val int 5 | Next *ListNode 6 | } 7 | 8 | func hasCycle(head *ListNode) bool { 9 | if head == nil || head.Next == nil { 10 | return false 11 | } 12 | 13 | slow := head 14 | fast := head 15 | 16 | //fast move 2 step, slow move 1 step 17 | for fast != nil && fast.Next != nil { 18 | fast = fast.Next.Next 19 | slow = slow.Next 20 | 21 | if fast == slow { 22 | return true 23 | } 24 | } 25 | 26 | return false 27 | } 28 | -------------------------------------------------------------------------------- /Array/TwoSum/TwoSum.cpp: -------------------------------------------------------------------------------- 1 | 2 | class Solution { 3 | public: 4 | vector twoSum(vector& nums, int target) { 5 | vector res; 6 | map hashMap; 7 | for(int i=0; i& nums1, int m, vector& nums2, int n) { 5 | while(m && n) { 6 | if(nums1[m-1] > nums2[n-1]) { 7 | nums1[m+n-1] = nums1[m-1]; 8 | m--; 9 | } 10 | else { 11 | nums1[m+n-1] = nums2[n-1]; 12 | n--; 13 | } 14 | } 15 | while(n) { 16 | nums1[n-1] = nums2[n-1]; 17 | n--; 18 | } 19 | } 20 | }; -------------------------------------------------------------------------------- /Stack/03.ValidParentheses/validParentheses.js: -------------------------------------------------------------------------------- 1 | const dict = { 2 | ')': '(', 3 | ']': '[', 4 | '}': '{', 5 | } 6 | 7 | var isValid = function(s) { 8 | if (!s) return true; 9 | let stack = []; 10 | for (let i = 0; i < s.length; ++i) { 11 | const c = s[i]; 12 | if (c == '(' || c == '{' || c == '[') { 13 | stack.push(c); 14 | } else { 15 | if (dict[c] !== stack.pop()) { 16 | return false; 17 | } 18 | } 19 | } 20 | return stack.length == 0; 21 | }; 22 | 23 | -------------------------------------------------------------------------------- /dp/BuyAndSellStock/README.md: -------------------------------------------------------------------------------- 1 | # Best Time to Buy and Sell Stock(买卖股票的最佳时机) 2 | 3 | **LeetCode 121** 4 | 5 | - [英文版](https://leetcode.com/problems/best-time-to-buy-and-sell-stock/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/) 8 | 9 | ## 题目 10 | 11 | ## 思路 12 |
13 | 点击展开 14 | // TODO 15 |
16 | 17 | ## 代码实现 18 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 19 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 20 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 21 | 22 | -------------------------------------------------------------------------------- /Sort/02.InsertionSort/InsertionSort.js: -------------------------------------------------------------------------------- 1 | // 原地,稳定,O(n^2) 2 | const insertionSort = (list) => { 3 | const n = list.length; 4 | if (n <= 1) return; 5 | 6 | for (let i = 1; i < n; ++i) { 7 | const val = list[i]; 8 | let j = i - 1; 9 | for (; j >= 0; j--) { 10 | if (list[j] > val) { 11 | list[j+1] = list[j]; 12 | } else { 13 | break; 14 | } 15 | } 16 | list[j+1] = val; 17 | } 18 | } 19 | 20 | const list = [3, 4, 39, 2, 12, 49, 32]; 21 | insertionSort(list); 22 | console.log(list); 23 | -------------------------------------------------------------------------------- /Array/FizzBuzz/FizzBuzz.cpp: -------------------------------------------------------------------------------- 1 | 2 | class Solution { 3 | public: 4 | vector fizzBuzz(int n) { 5 | vector res(n, ""); 6 | for(int i = 1; i<=n; ++i) { 7 | bool multiplesOfThree = (i % 3 == 0); 8 | bool multiplesOfFive = (i % 5 == 0); 9 | 10 | if(multiplesOfThree && multiplesOfFive) { res[i-1] = "FizzBuzz"; } 11 | else if(multiplesOfThree) { res[i-1] = "Fizz"; } 12 | else if(multiplesOfFive) {res[i-1] = "Buzz"; } 13 | else { res[i-1] = to_string(i); } 14 | } 15 | return res; 16 | } 17 | }; -------------------------------------------------------------------------------- /LinkedList/LinkedListCycle2/LinkedListCycle2.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | ListNode *detectCycle(ListNode *head) { 4 | ListNode *fast = head, *slow = head; 5 | while (fast && fast->next) { 6 | fast = fast->next->next; 7 | slow = slow->next; 8 | if (fast == slow) { 9 | fast = head; 10 | while (fast != slow) { 11 | fast = fast->next; 12 | slow = slow->next; 13 | } 14 | return fast; 15 | } 16 | } 17 | return nullptr; 18 | } 19 | }; -------------------------------------------------------------------------------- /Queue/04.CircularDeque/README.md: -------------------------------------------------------------------------------- 1 | # Design Circular Deque(设计一个双端队列) 2 | 3 | **LeetCode 641** 4 | 5 | - [英文版](https://leetcode.com/problems/design-circular-deque/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/design-circular-deque/) 8 | 9 | ## 题目 10 | 11 | ## 思路 12 |
13 | 点击展开 14 | // TODO 15 |
16 | 17 | ## 代码实现 18 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 19 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 20 | | 🤔 | [😀](./CircularDeque.hpp) | 🤔 | 🤔 | 🤔 | [😀](./CircularDeque.py) | 🤔 | 🤔 | 🤔 | 21 | 22 | 完成 😀,待完成 🤔 23 | -------------------------------------------------------------------------------- /Array/FirstMissingPositive/FirstMissingPositive.cpp: -------------------------------------------------------------------------------- 1 | 2 | class Solution { 3 | public: 4 | int firstMissingPositive(vector& nums) { 5 | int len = nums.size(); 6 | for (int i = 0; i < len; ++i) { 7 | int tmp = nums[i]; 8 | while (tmp > 0 && tmp <= len && nums[tmp-1] != tmp) { 9 | nums[i] = nums[tmp-1]; 10 | nums[tmp-1] = tmp; 11 | tmp = nums[i]; 12 | } 13 | } 14 | for (int i = 0; i < len; ++i) { 15 | if (nums[i]-1 != i) { return i + 1; } 16 | } 17 | 18 | return len + 1; 19 | } 20 | }; -------------------------------------------------------------------------------- /Array/MajorityElement/MajorityElement.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | /** 4 | * @note 求众数 5 | * @apiNote leetcode上说明,一定是具有众数存在的,则可以计算出一个初始值 count, 6 | * 从数组的下标1开始,如果与下一个数组下标的数字不相等,则count-- 当count 为0 就切换为下一个比较的数字 7 | * @since 19-3-18 11:24 by jdk 1.8 8 | */ 9 | 10 | public static int majorityElement(int[]nums){ 11 | int count=1; 12 | int maj=nums[0]; 13 | for(int i=1;i 13 | 点击展开 14 | // TODO 15 | 16 | 17 | ## 代码实现 18 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 19 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 20 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 21 | 22 | -------------------------------------------------------------------------------- /Sort/01.BubbleSort/BubbleSort.js: -------------------------------------------------------------------------------- 1 | // 原地,稳定,O(n^2) 2 | const bubbleSort = (list) => { 3 | const n = list.length; 4 | if (n <= 1) return; 5 | 6 | for (let i = 0; i < n; ++i) { 7 | let flag = false; // 如果没有进行交换 说明已排序完毕 8 | for (let j = 0; j < n - i - 1; ++j) { 9 | if (list[j] > list[j + 1]) { 10 | const tmp = list[j]; 11 | list[j] = list[j+1]; 12 | list[j+1] = tmp; 13 | flag = true; 14 | } 15 | } 16 | if (!flag) break; 17 | } 18 | }; 19 | 20 | const list = [10, 13, 41, 25, 40, 5, 6]; 21 | bubbleSort(list); 22 | console.log(list); 23 | -------------------------------------------------------------------------------- /Queue/05.SlidingWindowMaximum/SlidingWindowMaximum.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector maxSlidingWindow(vector& nums, int k) { 4 | vector res; 5 | deque que; 6 | for (int i =0; i < nums.size(); ++i) { 7 | if (!que.empty() && que.front() == i - k) // 队列头超出滑动窗口 8 | que.pop_front(); 9 | while (!que.empty() && nums[i] >= nums[que.back()]) // 删除队列尾元素,直到大于当前元素的元素 10 | que.pop_back(); 11 | que.push_back(i); // 当前元素入队 12 | if (i >= k - 1) 13 | res.push_back(nums[que.front()]); 14 | } 15 | return res; 16 | } 17 | }; -------------------------------------------------------------------------------- /Sort/08.SortColors/sortColors.cpp: -------------------------------------------------------------------------------- 1 | /* 荷兰国旗问题 2 | * 使用三个指针,分别指向当前元素、最右侧的0和最左侧的2 3 | */ 4 | 5 | class Solution { 6 | public: 7 | void sortColors(vector& nums) { 8 | int left = 0, right = nums.size() - 1; 9 | int curr = 0; 10 | while(curr <= right){ 11 | if(nums[curr] == 0 && curr > left){ 12 | swap(nums[curr], nums[left]); 13 | left++; 14 | } 15 | else if(nums[curr] == 2){ 16 | swap(nums[curr], nums[right]); 17 | right--; 18 | } 19 | else{ 20 | curr++; 21 | } 22 | } 23 | } 24 | }; -------------------------------------------------------------------------------- /Array/TwoSum/TwoSum.java: -------------------------------------------------------------------------------- 1 | 2 | // (时间O(n),空间O(n),通俗易懂) 3 | 4 | import java.util.HashMap; 5 | 6 | public class Solution { 7 | 8 | public int[] twoSum(int[] nums, int target) { 9 | 10 | HashMap hashMap = new HashMap<>(); 11 | 12 | for (int i = 0; i < nums.length; i++){ 13 | 14 | int key = target - nums[i]; 15 | 16 | if (hashMap.containsKey(key)){ 17 | 18 | return new int[]{hashMap.get(key), i}; 19 | 20 | } 21 | 22 | hashMap.put(nums[i],i); 23 | 24 | } 25 | 26 | throw new IllegalArgumentException("No two sum solution"); 27 | 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /String/LengthOfLongestSubstring/README.md: -------------------------------------------------------------------------------- 1 | # Longest Substring Without Repeating Characters 2 | 3 | [LeetCode 3](https://leetcode.com/problems/longest-substring-without-repeating-characters/) 4 | 5 | ## 题目 6 | 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。 7 | 8 | 示例 1: 9 | 10 | 输入: "abcabcbb" 11 | 输出: 3 12 | 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。 13 | 示例 2: 14 | 15 | 输入: "bbbbb" 16 | 输出: 1 17 | 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。 18 | 示例 3: 19 | 20 | 输入: "pwwkew" 21 | 输出: 3 22 | 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 23 |   请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。 24 | 25 | ## 代码实现 26 | | C++ | Java | Python | JS | 27 | | :--: | :--: | :--: | :---: | 28 | |[🤔]() | [🤔]() | [🤔]() | [😀](index.js) | 29 | -------------------------------------------------------------------------------- /Array/FirstMissingPositive/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number} 4 | */ 5 | var firstMissingPositive = function(nums) { 6 | const n = nums.length; 7 | let i = 0; 8 | while (i < n) { 9 | if (nums[i] > 0 && nums[i] <= n && nums[nums[i] - 1] != nums[i]) { 10 | // swap nums[nums[i] - 1] and nums[i] 11 | [nums[nums[i] - 1], nums[i]] = [nums[i], nums[nums[i] - 1]] 12 | } else { 13 | ++i; 14 | } 15 | } 16 | 17 | for (let i = 0; i < n; ++i) { 18 | if (nums[i] != i + 1) { 19 | return i + 1 20 | } 21 | } 22 | 23 | return nums.length + 1; 24 | }; -------------------------------------------------------------------------------- /BinaryTree/01.SameTree/SameTree.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode(object): 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution(object): 9 | def isSameTree(self, p, q): 10 | """ 11 | :type p: TreeNode 12 | :type q: TreeNode 13 | :rtype: bool 14 | """ 15 | if not p and not q: 16 | return True 17 | if not p and q or p and not q: 18 | return False 19 | if p.val != q.val: 20 | return False 21 | 22 | return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right) 23 | -------------------------------------------------------------------------------- /Array/MergeSortedArray/MergeSortedArray.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def merge(self, nums1, m, nums2, n): 3 | """ 4 | :type nums1: List[int] 5 | :type m: int 6 | :type nums2: List[int] 7 | :type n: int 8 | :rtype: void Do not return anything, modify nums1 in-place instead. 9 | """ 10 | if not nums1 or not nums2: return 11 | 12 | while m > 0 and n > 0: 13 | if nums1[m - 1] >= nums2[n - 1]: 14 | nums1[m + n -1] = nums1[m - 1] 15 | m -= 1 16 | else: 17 | nums1[m + n - 1] = nums2[n - 1] 18 | n -= 1 19 | 20 | if n > 0: nums1[:n] = nums2[:n] 21 | -------------------------------------------------------------------------------- /Array/NextPremutation/NextPremutation.cpp: -------------------------------------------------------------------------------- 1 | 2 | class Solution { 3 | public: 4 | void nextPermutation(vector& nums) { 5 | if(nums.size() < 2) { return; } 6 | int len = nums.size(); 7 | int i = len - 1; 8 | for(; i>0; --i) { 9 | if(nums[i] > nums[i-1]) { break; } 10 | } 11 | if(i==0) { 12 | reverse(nums.begin(), nums.end()); 13 | return; 14 | } 15 | int j = len - 1; 16 | for(; j>=i; --j){ 17 | if(nums[j] > nums[i-1]) { break; } 18 | } 19 | swap(nums[i-1], nums[j]); 20 | reverse(nums.begin()+i, nums.end()); 21 | // sort(nums.begin()+i, nums.end()); 22 | } 23 | }; -------------------------------------------------------------------------------- /Stack/03.ValidParentheses/validParentheses.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | bool isValid(string s) { 4 | stack myStack; 5 | for(auto ch : s) { 6 | if(ch == '(' || ch == '[' || ch == '{') { 7 | myStack.push(ch); 8 | } 9 | else { 10 | if(myStack.empty()) { return false; } 11 | auto top_ch = myStack.top(); 12 | if((top_ch == '(' && ch == ')') || (top_ch == '[' && ch == ']') || (top_ch == '{' && ch == '}')) { 13 | myStack.pop(); 14 | } 15 | else { return false; } 16 | } 17 | } 18 | return myStack.empty(); 19 | } 20 | }; -------------------------------------------------------------------------------- /LinkedList/LinkedListCycle2/LinkedListCycle2.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def detectCycle(self, head): 3 | """ 4 | :type head: ListNode 5 | :rtype: ListNode 6 | """ 7 | if not head or not head.next: return None 8 | 9 | try: 10 | slow = head 11 | fast = head.next 12 | while slow is not fast: 13 | slow = slow.next 14 | fast = fast.next.next 15 | except: 16 | return None 17 | 18 | slow = slow.next 19 | helpNode = head 20 | while slow is not helpNode: 21 | slow = slow.next 22 | helpNode = helpNode.next 23 | 24 | return slow 25 | 26 | -------------------------------------------------------------------------------- /String/ReverseString/README.md: -------------------------------------------------------------------------------- 1 | # Reverse String (反转字符串) 2 | 3 | **LeetCode 334** 4 | 5 | - [英文版](https://leetcode.com/problems/reverse-string/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/reverse-string/) 8 | 9 | ## 题目 10 | 编写一个函数,其作用是将输入的字符串反转过来。 11 | 12 | 示例 1: 13 | 14 | 输入: "hello" 15 | 输出: "olleh" 16 | 示例 2: 17 | 18 | 输入: "A man, a plan, a canal: Panama" 19 | 输出: "amanaP :lanac a ,nalp a ,nam A" 20 | 21 | ## 思路 22 |
23 | 点击展开 24 | // TODO 25 |
26 | 27 | ## 代码实现 28 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 29 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 30 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 31 | 32 | -------------------------------------------------------------------------------- /BackTracking/02.Permutations/README.md: -------------------------------------------------------------------------------- 1 | # Permutations (全排列) 2 | 3 | **LeetCode 46** 4 | 5 | - [英文版](https://leetcode.com/problems/permutations/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/permutations/) 8 | 9 | ## 题目 10 | 给定一个没有重复数字的序列,返回其所有可能的全排列。 11 | 12 | 示例: 13 | ``` 14 | 输入: [1,2,3] 15 | 输出: 16 | [ 17 | [1,2,3], 18 | [1,3,2], 19 | [2,1,3], 20 | [2,3,1], 21 | [3,1,2], 22 | [3,2,1] 23 | ] 24 | ``` 25 | ## 思路 26 |
27 | 点击展开 28 | // TODO 29 |
30 | 31 | ## 代码实现 32 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 33 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 34 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 35 | 36 | -------------------------------------------------------------------------------- /Stack/04.LongestValidParentheses/longestvalidparentheses.js: -------------------------------------------------------------------------------- 1 | var longestvalidparentheses = function(s) { 2 | let longest = 0; 3 | // 栈用来存储接下来遇到的匹配括号的长度 4 | let stk = [0]; 5 | for (let i = 0; i < s.length; ++i) { 6 | if (s[i] === '(') { 7 | stk.push(0); 8 | } else { 9 | if (stk.length > 1) { 10 | let v = stk.pop(); 11 | // 取出第一个元素 12 | let lastCount = stk[stk.length - 1]; 13 | stk[stk.length - 1] = lastCount + v + 2; 14 | longest = Math.max(longest, stk[stk.length - 1]); 15 | } else { 16 | stk = [0]; 17 | } 18 | } 19 | } 20 | return longest; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /LinkedList/MergeSortedLists/README.md: -------------------------------------------------------------------------------- 1 | # Merge Two Sorted Lists(合并两个有序链表) 2 | 3 | **LeetCode 21** 4 | 5 | - [英文版](https://leetcode.com/problems/merge-two-sorted-lists/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/merge-two-sorted-lists/) 8 | 9 | ## 题目 10 | 将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 11 | 12 | 示例: 13 | ``` 14 | 输入:1->2->4, 1->3->4 15 | 输出:1->1->2->3->4->4 16 | ``` 17 | 18 | ## 思路 19 |
20 | 点击展开 21 | // TODO 22 |
23 | 24 | ## 代码实现 25 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 26 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 27 | | 🤔 | [😀](./MergeSortedLists.cpp) | 🤔 | 🤔 | 🤔 | [😀](./MergeSortedLists.py) | 🤔 | 🤔 | 🤔 | 28 | -------------------------------------------------------------------------------- /LinkedList/ReverseLinkedList/ReverseLinkedList.py: -------------------------------------------------------------------------------- 1 | # 迭代法 2 | class Solution(object): 3 | def reverseList(self, head): 4 | """ 5 | :type head: ListNode 6 | :rtype: ListNode 7 | """ 8 | prev = None 9 | while head: 10 | curr = head 11 | head = head.next 12 | curr.next = prev 13 | prev = curr 14 | return prev 15 | 16 | # 递归 17 | class Solution: 18 | # @param {ListNode} head 19 | # @return {ListNode} 20 | def reverseList(self, head): 21 | return self._reverse(head) 22 | 23 | def _reverse(self, node, prev = None): 24 | if not node: 25 | return prev 26 | n = node.next 27 | node.next = prev 28 | return self._reverse(n, node) 29 | -------------------------------------------------------------------------------- /dp/MinimumPathSum/README.md: -------------------------------------------------------------------------------- 1 | # Minimum Path Sum(最小路径和) 2 | 3 | LeetCode 64 4 | 5 | - [英文版](https://leetcode.com/problems/minimum-path-sum/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/minimum-path-sum/) 8 | 9 | ## 题目 10 | 11 | 给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。 12 | 13 | 说明:每次只能向下或者向右移动一步。 14 | 15 | 示例: 16 | ``` 17 | 输入: 18 | [ 19 | [1,3,1], 20 | [1,5,1], 21 | [4,2,1] 22 | ] 23 | 输出: 7 24 | 解释: 因为路径 1→3→1→1→1 的总和最小。 25 | ``` 26 | 27 | ## 思路 28 |
29 | 点击展开 30 | // TODO 31 |
32 | 33 | ## 代码实现 34 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 35 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 36 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 37 | 38 | -------------------------------------------------------------------------------- /Search/02.Sqrt/README.md: -------------------------------------------------------------------------------- 1 | # Sqrt(x) (x 的平方根) 2 | 3 | **LeetCode 69** 4 | 5 | - [英文版](https://leetcode.com/problems/sqrtx/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/sqrtx/) 8 | 9 | ## 题目 10 | 实现 int sqrt(int x) 函数。 11 | 12 | 计算并返回 x 的平方根,其中 x 是非负整数。 13 | 14 | 由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。 15 | 16 | 示例 1: 17 | ``` 18 | 输入: 4 19 | 输出: 2 20 | ``` 21 | 22 | 示例 2: 23 | ``` 24 | 输入: 8 25 | 输出: 2 26 | 说明: 8 的平方根是 2.82842..., 27 | 由于返回类型是整数,小数部分将被舍去。 28 | ``` 29 | ## 思路 30 |
31 | 点击展开 32 | // TODO 33 |
34 | 35 | ## 代码实现 36 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 37 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 38 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 39 | 40 | -------------------------------------------------------------------------------- /Array/TwoSum/README.md: -------------------------------------------------------------------------------- 1 | # Two Sum(两数之和) 2 | 3 | **LeetCode 1** 4 | 5 | - [英文版](https://leetcode.com/problems/two-sum/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/two-sum/) 8 | 9 | ## 题目 10 | 11 | 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那*两个*整数,并返回他们的数组下标。 12 | 13 | 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 14 | 15 | 示例: 16 | 17 | ```js 18 | 给定 nums = [2, 7, 11, 15], target = 9 19 | 20 | 因为 nums[0] + nums[1] = 2 + 7 = 9 21 | 所以返回 [0, 1] 22 | ``` 23 | 24 | ## 思路 25 | 26 |
27 | 点击展开 28 | 使用散列表,缓存访问过的元素和下标,遍历数组,查找缓存中是否存在元素和当前元素的和等于目标值。 29 | 时间复杂度 O(n)。 30 |
31 | 32 | ## 代码实现 33 | 34 | | C++ | Java | Python | JS | 35 | | :--: | :--: | :--: | :---: | 36 | |[😀](TwoSum.cpp) | [😀](TwoSum.java) | [😀](TwoSum.py) | [😀](TwoSum.js) | 37 | -------------------------------------------------------------------------------- /BinaryTree/02.SymmetricTree/symmetricTree.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val) { 4 | * this.val = val; 5 | * this.left = this.right = null; 6 | * } 7 | */ 8 | /** 9 | * @param {TreeNode} root 10 | * @return {boolean} 11 | */ 12 | // 对称树 13 | function isSymmetricHelper(left, right) { 14 | if (!left || !right) { 15 | return left == right; 16 | } 17 | 18 | if (left.val !== right.val) { 19 | return false 20 | } 21 | 22 | return isSymmetricHelper(left.left, right.right) && isSymmetricHelper(left.right, right.left); 23 | } 24 | 25 | var isSymmetric = function(root) { 26 | if (!root) return true; 27 | return isSymmetricHelper(root.left, root.right); 28 | }; 29 | 30 | 31 | // 对于树形结构,如果直接递归行不通,考虑拆分为左右子树来递归。 32 | -------------------------------------------------------------------------------- /BinaryTree/10.FindLargestValue/README.md: -------------------------------------------------------------------------------- 1 | # Find Largest Value in Each Tree Row(在每个树行中找最大值) 2 | 3 | **LeetCode 515** 4 | 5 | - [英文版](https://leetcode.com/problems/find-largest-value-in-each-tree-row/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/find-largest-value-in-each-tree-row/) 8 | 9 | ## 题目 10 | 11 | 您需要在二叉树的每一行中找到最大的值。 12 | 13 | 示例: 14 | ``` 15 | 输入: 16 | 17 | 1 18 | / \ 19 | 3 2 20 | / \ \ 21 | 5 3 9 22 | 23 | 输出: [1, 3, 9] 24 | ``` 25 | 26 | ## 思路 27 |
28 | 点击展开 29 | // TODO 30 |
31 | 32 | ## 代码实现 33 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 34 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 35 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 36 | 37 | -------------------------------------------------------------------------------- /Array/SingleNumber/README.md: -------------------------------------------------------------------------------- 1 | # Single Number(数组中只出现一次的数) 2 | 3 | **LeetCode 136** 4 | 5 | - [英文版](https://leetcode.com/problems/single-number/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/single-number/) 8 | 9 | ## 题目 10 | 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 11 | 12 | 说明: 13 | 14 | 你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗? 15 | 16 | 示例 1: 17 | ``` 18 | 输入: [2,2,1] 19 | 输出: 1 20 | ``` 21 | 22 | 示例 2: 23 | ``` 24 | 输入: [4,1,2,1,2] 25 | 输出: 4 26 | ``` 27 | 28 | ## 思路 29 |
30 | 点击展开 31 | 使用异或 32 |
33 | 34 | ## 代码实现 35 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 36 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 37 | | 🤔 | [😀](./SingleNumber.cpp) | 🤔 | 🤔 | 🤔 | 🤔 | [😀](./SingleNumber.js) | 🤔 | 🤔 | 38 | 39 | -------------------------------------------------------------------------------- /dp/MinimumPathSum/minimumPathSum.js: -------------------------------------------------------------------------------- 1 | var minPath = (grid) => { 2 | let states = [] 3 | const m = grid.length; 4 | const n = grid[0].length; 5 | 6 | // 初始化第一行的数据 7 | let row = [] 8 | let sum = 0 9 | for (let j = 0; j < n; ++j) { 10 | sum += grid[0][j]; 11 | row[j] = sum; 12 | } 13 | states.push(row); 14 | 15 | // 初始化第一列的数据 16 | sum = grid[0][0]; 17 | for (let i = 1; i < m; ++i) { 18 | let row = []; 19 | sum += grid[i][0]; 20 | row[0] = sum; 21 | states.push(row); 22 | } 23 | 24 | for (let i = 1; i < m; ++i) { 25 | for (let j = 1; j < n; ++j) { 26 | states[i][j] = grid[i][j] + Math.min(states[i-1][j], states[i][j-1]); 27 | } 28 | } 29 | 30 | return states[m-1][n-1]; 31 | } 32 | 33 | -------------------------------------------------------------------------------- /Array/ThreeSum/README.md: -------------------------------------------------------------------------------- 1 | # Three Sum (三数之和) 2 | 3 | **LeetCode 15** 4 | 5 | * [英文版](https://leetcode.com/problems/3sum/) 6 | 7 | * [中文版](https://leetcode-cn.com/problems/3sum/) 8 | 9 | ## 题目 10 | 11 | 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。 12 | 13 | 注意:答案中不可以包含重复的三元组。 14 | 15 | 例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4], 16 | 17 | 满足要求的三元组集合为: 18 | [ 19 | [-1, 0, 1], 20 | [-1, -1, 2] 21 | ] 22 | 23 | ## 思路 24 | 25 | 1. 先对原数组排序 26 | 2. 从小到大遍历排序的数组 27 | 3. 在当前遍历下标的后面剩余数组中使用两边夹逼的方式查找两个数 28 | 4. 如果这两个数与当前下标的数之和等于 0,则存入结果数组 29 | 5. 否则继续夹逼查找 30 | 31 | ## 代码实现 32 | 33 | | C++ | Java | Python | JavaScript | Go | 34 | | :--: | :--: | :--: | :--: | :---: | :---: | :---: | 35 | | [😀](ThreeSum.cpp) | [😀](ThreeSum.java) | [😀](ThreeSum.py) | [😀](./ThreeSum.js) | [😀](three_sum.go) | 36 | -------------------------------------------------------------------------------- /dp/CoinChange/README.md: -------------------------------------------------------------------------------- 1 | # Coin Change (零钱兑换) 2 | 3 | **LeetCode 322** 4 | 5 | - [英文版](https://leetcode.com/problems/coin-change/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/coin-change/) 8 | 9 | ## 题目 10 | 给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。 11 | 12 | 示例 1: 13 | ``` 14 | 输入: coins = [1, 2, 5], amount = 11 15 | 输出: 3 16 | 解释: 11 = 5 + 5 + 1 17 | ``` 18 | 19 | 示例 2: 20 | ``` 21 | 输入: coins = [2], amount = 3 22 | 输出: -1 23 | ``` 24 | 25 | 说明: 26 | 你可以认为每种硬币的数量是无限的。 27 | 28 | ## 思路 29 |
30 | 点击展开 31 | // TODO 32 |
33 | 34 | ## 代码实现 35 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 36 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 37 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 38 | 39 | -------------------------------------------------------------------------------- /String/ReverseWords/README.md: -------------------------------------------------------------------------------- 1 | # Reverse Words in a String(翻转字符串里的单词) 2 | 3 | **LeetCode 151** 4 | 5 | - [英文版](https://leetcode.com/problems/reverse-words-in-a-string/) 6 | 7 | - [中文](https://leetcode-cn.com/problems/reverse-words-in-a-string/) 8 | 9 | ## 题目 10 | 给定一个字符串,逐个翻转字符串中的每个单词。 11 | 12 | 示例: 13 | ``` 14 | 输入: "the sky is blue", 15 | 输出: "blue is sky the". 16 | ``` 17 | 说明: 18 | 19 | 无空格字符构成一个单词。 20 | 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。 21 | 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。 22 | 进阶: 请选用C语言的用户尝试使用 O(1) 空间复杂度的原地解法。 23 | 24 | ## 思路 25 |
26 | 点击展开 27 | // TODO 28 |
29 | 30 | ## 代码实现 31 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 32 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 33 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 34 | 35 | -------------------------------------------------------------------------------- /Array/MergeSortedArray/README.md: -------------------------------------------------------------------------------- 1 | # Merge Sorted Array(合并两个有序数组) 2 | 3 | **LeetCode 88** 4 | 5 | * [英文版](https://leetcode.com/problems/merge-sorted-array/) 6 | 7 | * [中文版](https://leetcode-cn.com/problems/merge-sorted-array/) 8 | 9 | ## 题目 10 | 11 | 给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。 12 | 13 | 说明: 14 | 15 | * 初始化 nums1 和 nums2 的元素数量分别为 m 和 n。 16 | * 你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。 17 | 18 | 示例: 19 | 20 | ``` 21 | 输入: 22 | nums1 = [1,2,3,0,0,0], m = 3 23 | nums2 = [2,5,6], n = 3 24 | 25 | 输出: [1,2,2,3,5,6] 26 | ``` 27 | 28 | ## 思路 29 | 30 | 从右往左,存元素。 31 | 32 | ## 代码实现 33 | 34 | | C | C++ | Java | Python | JavaScript | Go | PHP | 35 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 36 | | 🤔 | [😀](MergeSortedArray.cpp) | 🤔 | [😀](MergeSortedArray.py) | 🤔 | 🤔 | 🤔 | 37 | 38 | -------------------------------------------------------------------------------- /BinaryTree/04.MaximumDepthOfBinaryTree/README.md: -------------------------------------------------------------------------------- 1 | # Maximum Depth of Binary Tree(二叉树的最大深度) 2 | 3 | **LeetCode 104** 4 | 5 | - [英文版](https://leetcode.com/problems/maximum-depth-of-binary-tree/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/) 8 | 9 | ## 题目 10 | 给定一个二叉树,找出其最大深度。 11 | 12 | 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。 13 | 14 | 说明: 叶子节点是指没有子节点的节点。 15 | 16 | 示例: 17 | 给定二叉树 [3,9,20,null,null,15,7], 18 | ``` 19 | 3 20 | / \ 21 | 9 20 22 | / \ 23 | 15 7 24 | ``` 25 | 返回它的最大深度 3 。 26 | 27 | ## 思路 28 |
29 | 点击展开 30 | // TODO 31 |
32 | 33 | ## 代码实现 34 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 35 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 36 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 37 | 38 | -------------------------------------------------------------------------------- /Array/FizzBuzz/README.md: -------------------------------------------------------------------------------- 1 | # Fizz Buzz(3 和 5 的倍数) 2 | **LeetCode 412** 3 | 4 | - [英文版](https://leetcode.com/problems/fizz-buzz/) 5 | 6 | - [中文版](https://leetcode-cn.com/problems/fizz-buzz/) 7 | 8 | ## 题目 9 | 写一个程序,输出从 1 到 n 数字的字符串表示。 10 | 11 | 1. 如果 n 是3的倍数,输出“Fizz”; 12 | 13 | 2. 如果 n 是5的倍数,输出“Buzz”; 14 | 15 | 3.如果 n 同时是3和5的倍数,输出 “FizzBuzz”。 16 | 17 | 示例: 18 | ``` 19 | n = 15, 20 | 21 | 返回: 22 | [ 23 | "1", 24 | "2", 25 | "Fizz", 26 | "4", 27 | "Buzz", 28 | "Fizz", 29 | "7", 30 | "8", 31 | "Fizz", 32 | "Buzz", 33 | "11", 34 | "Fizz", 35 | "13", 36 | "14", 37 | "FizzBuzz" 38 | ] 39 | ``` 40 | 41 | ## 代码实现 42 | | C | C++ | Java | Python | JavaScript | Go | PHP | 43 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 44 | | 🤔 | [😀](./FizzBuzz.cpp) | 🤔 | [😀](./FizzBuzz.py) | 🤔 | 🤔 | 🤔 | 45 | -------------------------------------------------------------------------------- /dp/Triangle/README.md: -------------------------------------------------------------------------------- 1 | # Triangle(三角形最小路径和) 2 | 3 | **LeetCode 120** 4 | 5 | - [英文版](https://leetcode.com/problems/triangle/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/triangle/) 8 | 9 | ## 题目 10 | Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below. 11 | 12 | For example, given the following triangle 13 | 14 | [ 15 | [2], 16 | [3,4], 17 | [6,5,7], 18 | [4,1,8,3] 19 | ] 20 | The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11). 21 | 22 | ## 思路 23 |
24 | 点击展开 25 | // TODO 26 |
27 | 28 | ## 代码实现 29 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 30 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 31 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 32 | 33 | -------------------------------------------------------------------------------- /Stack/04.LongestValidParentheses/README.md: -------------------------------------------------------------------------------- 1 | # Longest Valid Parentheses(最长有效括号) 2 | 3 | **LeetCode 32** 4 | 5 | - [英文版](https://leetcode.com/problems/longest-valid-parentheses/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/longest-valid-parentheses/) 8 | 9 | ## 题目 10 | 给定一个只包含 '(' 和 ')' 的字符串,找出最长的包含有效括号的子串的长度。 11 | 12 | 示例 1: 13 | ``` 14 | 输入: "(()" 15 | 输出: 2 16 | 解释: 最长有效括号子串为 "()" 17 | ``` 18 | 示例 2: 19 | ``` 20 | 输入: ")()())" 21 | 输出: 4 22 | 解释: 最长有效括号子串为 "()()" 23 | ``` 24 | ## 思路 25 |
26 | 点击展开 27 | (((()))) 也是有效的 28 | 使用栈 29 |
30 | 31 | ## 代码实现 32 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 33 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 34 | | 🤔 | [😀](./longestvalidparentheses.cpp) | 🤔 | 🤔 | 🤔 | 🤔 | [😀](./longestvalidparentheses.js) | 🤔 | 🤔 | 35 | -------------------------------------------------------------------------------- /BinaryTree/02.SymmetricTree/README.md: -------------------------------------------------------------------------------- 1 | # Symmetric Tree (对称二叉树) 2 | 3 | **LeetCode 101** 4 | 5 | - [英文版](https://leetcode.com/problems/symmetric-tree/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/symmetric-tree/) 8 | 9 | ## 题目 10 | 给定一个二叉树,检查它是否是镜像对称的。 11 | 12 | 例如,二叉树 [1,2,2,3,4,4,3] 是对称的。 13 | ``` 14 | 1 15 | / \ 16 | 2 2 17 | / \ / \ 18 | 3 4 4 3 19 | ``` 20 | 但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的: 21 | ``` 22 | 1 23 | / \ 24 | 2 2 25 | \ \ 26 | 3 3 27 | ``` 28 | 说明: 29 | 30 | 如果你可以运用递归和迭代两种方法解决这个问题,会很加分。 31 | 32 | ## 思路 33 |
34 | 点击展开 35 | // TODO 36 |
37 | 38 | ## 代码实现 39 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 40 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 41 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 42 | 43 | -------------------------------------------------------------------------------- /Search/03.WordSearch/README.md: -------------------------------------------------------------------------------- 1 | # Word Search(单词搜索) 2 | 3 | **LeetCode 79** 4 | 5 | - [英文版](https://leetcode.com/problems/word-search/) 6 | - [中文版](https://leetcode-cn.com/problems/word-search/) 7 | 8 | ## 题目 9 | 给定一个二维网格和一个单词,找出该单词是否存在于网格中。 10 | 11 | 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。 12 | 13 | 示例: 14 | ``` 15 | board = 16 | [ 17 | ['A','B','C','E'], 18 | ['S','F','C','S'], 19 | ['A','D','E','E'] 20 | ] 21 | 22 | 给定 word = "ABCCED", 返回 true. 23 | 给定 word = "SEE", 返回 true. 24 | 给定 word = "ABCB", 返回 false. 25 | ``` 26 | ## 思路 27 |
28 | 点击展开 29 | // TODO 30 |
31 | 32 | ## 代码实现 33 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 34 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 35 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 36 | 37 | -------------------------------------------------------------------------------- /Graph/01.NumberOfIslands/README.md: -------------------------------------------------------------------------------- 1 | # Number of Islands(岛屿的个数) 2 | 3 | **LeetCode 200** 4 | 5 | - [英文版](https://leetcode.com/problems/number-of-islands/description/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/number-of-islands/description/) 8 | 9 | ## 题目 10 | 给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量。一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设网格的四个边均被水包围。 11 | 12 | 示例 1: 13 | ``` 14 | 输入: 15 | 11110 16 | 11010 17 | 11000 18 | 00000 19 | 20 | 输出: 1 21 | ``` 22 | 23 | 示例 2: 24 | 25 | ``` 26 | 输入: 27 | 11000 28 | 11000 29 | 00100 30 | 00011 31 | 32 | 输出: 3 33 | ``` 34 | ## 思路 35 |
36 | 点击展开 37 | // TODO 38 |
39 | 40 | ## 代码实现 41 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 42 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 43 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 44 | 45 | -------------------------------------------------------------------------------- /LinkedList/ReverseLinkedList/README.md: -------------------------------------------------------------------------------- 1 | # Reverse Linked List(反转链表) 2 | 3 | ** LeetCode 206** 4 | 5 | - [英文版](https://leetcode.com/problems/reverse-linked-list/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/reverse-linked-list/) 8 | 9 | ## 题目 10 | 反转一个单链表。 11 | 12 | 示例: 13 | ``` 14 | 输入: 1->2->3->4->5->NULL 15 | 输出: 5->4->3->2->1->NULL 16 | ``` 17 | 进阶: 18 | 你可以迭代或递归地反转链表。你能否用两种方法解决这道题? 19 | 20 | ## 思路 21 |
22 | 点击展开 23 | 24 | 1. 迭代:引入两个指针,prev记录上一个节点,back记录下一个节点,时间复杂度O(n),空间复杂度O(1); 25 | 26 | 2. 递归:head.next.next = head;时间复杂度O(n),空间复杂度O(n)。 27 | 28 |
29 | 30 | ## 代码实现 31 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 32 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 33 | | 🤔 | [😀](./ReverseLinkedList.cpp) | 🤔 | 🤔 | 🤔 | [😀](./ReverseLinkedList.py) | 🤔 | 🤔 | 🤔 | 34 | 35 | -------------------------------------------------------------------------------- /dp/ClimbingStairs/README.md: -------------------------------------------------------------------------------- 1 | # Climbing Stairs(爬楼梯) 2 | 3 | LeetCode 70 4 | 5 | - [英文版](https://leetcode.com/problems/climbing-stairs/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/climbing-stairs/) 8 | 9 | ## 题目 10 | 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 11 | 12 | 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? 13 | 14 | 注意:给定 n 是一个正整数。 15 | 16 | 示例 1: 17 | ``` 18 | 输入: 2 19 | 输出: 2 20 | 解释: 有两种方法可以爬到楼顶。 21 | 1. 1 阶 + 1 阶 22 | 2. 2 阶 23 | ``` 24 | 示例 2: 25 | ``` 26 | 输入: 3 27 | 输出: 3 28 | 解释: 有三种方法可以爬到楼顶。 29 | 1. 1 阶 + 1 阶 + 1 阶 30 | 2. 1 阶 + 2 阶 31 | 3. 2 阶 + 1 阶 32 | ``` 33 | 34 | ## 思路 35 |
36 | 点击展开 37 | // TODO 38 |
39 | 40 | ## 代码实现 41 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 42 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 43 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 44 | 45 | -------------------------------------------------------------------------------- /Array/MajorityElement/README.md: -------------------------------------------------------------------------------- 1 | # Majority Element(求众数) 2 | **LeetCode 169** 3 | 4 | - [英文版](https://leetcode.com/problems/majority-element/) 5 | 6 | - [中文版](https://leetcode-cn.com/problems/majority-element/) 7 | 8 | ## 题目 9 | 给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。 10 | 11 | 你可以假设数组是非空的,并且给定的数组总是存在众数。 12 | 13 | 示例 1: 14 | ``` 15 | 输入: [3,2,3] 16 | 输出: 3 17 | ``` 18 | 19 | 示例 2: 20 | ``` 21 | 输入: [2,2,1,1,1,2,2] 22 | 输出: 2 23 | ``` 24 | 25 | ## 思路 26 | 1. O(n) time and O(n) space 27 | 28 | 2. O(n) time and O(1) space 29 | 使用 major 变量记录众数,count 记录遇到 major +1,非 major -1,最终 count 会大于0,major 即代表众数。 30 | 31 | ## 代码实现 32 | | C | C++ | Java | Python | JavaScript | PHP | Go | 33 | | :--: | :--: | :--: | :--: | :---: | :---: | :---: | 34 | | 🤔 | [😀](./MajorityElement.cpp) | [😀](./MajorityElement.java) | 🤔 | [😀](./MajorityElement.js) | 🤔 | [😀](./majority_elements.go) | 35 | -------------------------------------------------------------------------------- /Sort/09.SelectionSort/SelectionSort.js: -------------------------------------------------------------------------------- 1 | // 选择排序 2 | // 原地、不稳定、O(n^2) 3 | const selectionSort = (list) => { 4 | if (list.length <= 1) return; 5 | 6 | const len = list.length; 7 | for (let i = 0; i < len - 1; ++i) { 8 | let min = i; 9 | for (let j = i + 1; j < len; ++j) { 10 | if (list[min] > list[j]) { 11 | min = j; 12 | } 13 | } 14 | const tmp = list[i]; 15 | list[i] = list[min]; 16 | list[min] = tmp; 17 | } 18 | }; 19 | 20 | const list = [29, 3, 3, 12, 32, 4, 30, 88, 49, 99, 29]; 21 | selectionSort(list); 22 | console.log(list); 23 | 24 | 25 | // 二刷了下排序,有了一些新的体会。 26 | // 27 | // 冒泡、插入、选择排序都有一个共同点,将待排序数列分为已排序和未排序两部分。在未排序的部分中查找一个最值,放到已排序数列的恰当位置。 28 | // 29 | // 具体到代码层面,外层循环的变量用于分割已排序和未排序数,内层循环的变量用于在未排序数中查找。从思路上看,这三种算法其实是一样的,所以时间复杂度也相同。 30 | // 31 | // 这三种排序的实际复杂度依赖于待排序数列的有序度。 32 | 33 | -------------------------------------------------------------------------------- /BinaryTree/11.PathSum/README.md: -------------------------------------------------------------------------------- 1 | # Path Sum(路径总和) 2 | 3 | **LeetCode 112** 4 | 5 | - [英文版](https://leetcode.com/problems/path-sum/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/path-sum/) 8 | 9 | ## 题目 10 | 给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。 11 | 12 | 说明: 叶子节点是指没有子节点的节点。 13 | 14 | 示例: 15 | 16 | 给定如下二叉树,以及目标和 sum = 22, 17 | 18 | ``` 19 | 5 20 | / \ 21 | 4 8 22 | / / \ 23 | 11 13 4 24 | / \ \ 25 | 7 2 1 26 | ``` 27 | 返回 true, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2。 28 | 29 | ## 思路 30 |
31 | 点击展开 32 | // TODO 33 |
34 | 35 | ## 代码实现 36 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 37 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 38 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 39 | 40 | -------------------------------------------------------------------------------- /LinkedList/MergeKSortedLists/README.md: -------------------------------------------------------------------------------- 1 | # Merge k Sorted Lists(合并 k 个排序链表) 2 | 3 | **LeetCode 23** 4 | 5 | - [英文版](https://leetcode.com/problems/merge-k-sorted-lists/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/merge-k-sorted-lists/) 8 | 9 | ## 题目 10 | 合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。 11 | 12 | 示例: 13 | ``` 14 | 输入: 15 | [ 16 | 1->4->5, 17 | 1->3->4, 18 | 2->6 19 | ] 20 | 输出: 1->1->2->3->4->4->5->6 21 | ``` 22 | ## 思路 23 |
24 | 点击展开 25 | 26 | 思路一:纯递归实现,每次从`lists`中找出`val`最小的节点,将其指针前进一步; 27 | 28 | 思路二:分治思想,将问题划分为更小规模的子问题([合并2个有序链表](../04.MergeSortedLists))。 29 | 30 |
31 | 32 | ## 代码实现 33 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 34 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 35 | | 🤔 | [😀](./MergeKSortedLists.cpp) | [😀](./MergeKSortedLists.java) | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 36 | 37 | -------------------------------------------------------------------------------- /BinaryTree/08.FlattenBinaryTreeToLinkedList/README.md: -------------------------------------------------------------------------------- 1 | # Flatten Binary Tree to Linked List(二叉树展开为链表) 2 | 3 | **LeetCode 114** 4 | 5 | - [英文版](https://leetcode.com/problems/flatten-binary-tree-to-linked-list/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/flatten-binary-tree-to-linked-list/) 8 | 9 | ## 题目 10 | 给定一个二叉树,原地将它展开为链表。 11 | 12 | 例如,给定二叉树 13 | ``` 14 | 1 15 | / \ 16 | 2 5 17 | / \ \ 18 | 3 4 6 19 | ``` 20 | 将其展开为: 21 | ``` 22 | 1 23 | \ 24 | 2 25 | \ 26 | 3 27 | \ 28 | 4 29 | \ 30 | 5 31 | \ 32 | 6 33 | ``` 34 | 35 | ## 思路 36 |
37 | 点击展开 38 | // TODO 39 |
40 | 41 | ## 代码实现 42 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 43 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 44 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 45 | 46 | -------------------------------------------------------------------------------- /BinaryTree/09.BinaryTreeLevelTraversal/README.md: -------------------------------------------------------------------------------- 1 | # Binary Tree Zigzag Level Order Traversal(二叉树的锯齿形层次遍历) 2 | 3 | **LeetCode 103** 4 | 5 | - [英文版](https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/binary-tree-zigzag-level-order-traversal/) 8 | 9 | ## 题目 10 | 给定一个二叉树,返回其节点值的锯齿形层次遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。 11 | 12 | 例如: 13 | 给定二叉树 [3,9,20,null,null,15,7], 14 | ``` 15 | 3 16 | / \ 17 | 9 20 18 | / \ 19 | 15 7 20 | ``` 21 | 返回锯齿形层次遍历如下: 22 | ``` 23 | [ 24 | [3], 25 | [20,9], 26 | [15,7] 27 | ] 28 | ``` 29 | ## 思路 30 |
31 | 点击展开 32 | // TODO 33 |
34 | 35 | ## 代码实现 36 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 37 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 38 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 39 | 40 | -------------------------------------------------------------------------------- /LinkedList/LinkedListCycle/LinkedListCycle.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @note 查看链表是否有环, 相关辅助类在ListNode中给出 4 | * @apiNote 运用快慢节点,快节点一次两步,慢节点一次一步,如果有环,快慢节点一定相遇。 5 | * @since 19-3-18 15:33 by jdk 1.8 6 | */ 7 | public class LinkedListCycle { 8 | 9 | public static boolean hasCycle(ListNode head) { 10 | ListNode slow = head; 11 | ListNode fast = head; 12 | while (fast != null && fast.next != null) { 13 | slow = slow.next; 14 | fast = fast.next.next; 15 | if (slow == fast) return true; 16 | } 17 | return false; 18 | } 19 | 20 | public static void main(String[] args) { 21 | int[] a = {1, 2, 3, 4, 5, 6}; 22 | ListNode listNode = ListNode.buildListNode(a); 23 | ListNode cycleNode = ListNode.buildCycleNode(listNode, 3); 24 | boolean b = hasCycle(cycleNode); 25 | System.out.println(b); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Stack/04.LongestValidParentheses/longestvalidparentheses.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int longestValidParentheses(string s) { 4 | int longest = 0; 5 | // 使用 vector 模拟栈,存储接下来遇到的匹配括号的长度 6 | vector stk; 7 | stk.push_back(0); 8 | for (auto ch : s) { 9 | if (ch == '(') { 10 | stk.push_back(0); 11 | } 12 | else { 13 | if (stk.size() > 1) { 14 | int v = stk.back(); stk.pop_back(); 15 | int lastCount = stk[stk.size() - 1]; 16 | stk[stk.size() - 1] = lastCount + v + 2; 17 | longest = max(longest, stk[stk.size() - 1]); 18 | } 19 | else { 20 | stk.clear(); stk.push_back(0); 21 | } 22 | } 23 | } 24 | return longest; 25 | } 26 | }; -------------------------------------------------------------------------------- /BinaryTree/03.InvertBinaryTree/README.md: -------------------------------------------------------------------------------- 1 | # Invert Binary Tree(翻转二叉树) 2 | 3 | **LeetCode 226** 4 | 5 | - [英文版](https://leetcode.com/problems/invert-binary-tree/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/invert-binary-tree/) 8 | 9 | ## 题目 10 | 翻转一棵二叉树。 11 | 12 | 示例: 13 | 14 | 输入: 15 | ``` 16 | 4 17 | / \ 18 | 2 7 19 | / \ / \ 20 | 1 3 6 9 21 | ``` 22 | 输出: 23 | ``` 24 | 4 25 | / \ 26 | 7 2 27 | / \ / \ 28 | 9 6 3 1 29 | ``` 30 | 备注: 31 | 这个问题是受到 Max Howell 的 原问题 启发的 : 32 | ``` 33 | 谷歌:我们90%的工程师使用您编写的软件(Homebrew),但是您却无法在面试时在白板上写出翻转二叉树这道题,这太糟糕了。 34 | ``` 35 | 36 | ## 思路 37 |
38 | 点击展开 39 | // TODO 40 |
41 | 42 | ## 代码实现 43 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 44 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 45 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 46 | 47 | -------------------------------------------------------------------------------- /Sort/08.SortColors/README.md: -------------------------------------------------------------------------------- 1 | # Sort Colors(颜色分类) 2 | LeetCode 75 3 | [English](https://leetcode.com/problems/sort-colors/) 4 | [中文](https://leetcode-cn.com/problems/sort-colors/) 5 | 6 | ## 题目 7 | 给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。 8 | 9 | 此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。 10 | 11 | 注意: 12 | 不能使用代码库中的排序函数来解决这道题。 13 | 14 | 示例: 15 | ``` 16 | 输入: [2,0,2,1,1,0] 17 | 输出: [0,0,1,1,2,2] 18 | ``` 19 | 进阶: 20 | 21 | - 一个直观的解决方案是使用计数排序的两趟扫描算法。 22 | 首先,迭代计算出0、1 和 2 元素的个数,然后按照0、1、2的排序,重写当前数组。 23 | - 你能想出一个仅使用常数空间的一趟扫描算法吗? 24 | ## 思路 25 |
26 | 点击展开 27 | 使用三个指针,分别指向当前元素、最右侧的0和最左侧的2;当前元素为0则与左侧的2交换,当前元素为2则与右侧的0交换。 28 |
29 | 30 | ## 代码实现 31 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 32 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 33 | | 🤔 | [😀](./sortColors.cpp) | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 34 | 35 | -------------------------------------------------------------------------------- /BinaryTree/12.ConvertToBinarySearchTree/README.md: -------------------------------------------------------------------------------- 1 | # Convert Sorted Array to Binary Search Tree(将有序数组转换为二叉搜索树) 2 | 3 | **LeetCode 108** 4 | 5 | - [英文版](https://leetcode.com/problems/convert-sorted-array-to-binary-search-tree/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/convert-sorted-array-to-binary-search-tree/) 8 | 9 | ## 题目 10 | 将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。 11 | 12 | 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。 13 | 14 | 示例: 15 | 16 | 给定有序数组: [-10,-3,0,5,9], 17 | 18 | 一个可能的答案是:[0,-3,9,-10,null,5],它可以表示下面这个高度平衡二叉搜索树: 19 | ``` 20 | 0 21 | / \ 22 | -3 9 23 | / / 24 | -10 5 25 | ``` 26 | 27 | ## 思路 28 |
29 | 点击展开 30 | // TODO 31 |
32 | 33 | ## 代码实现 34 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 35 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 36 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 37 | 38 | -------------------------------------------------------------------------------- /Array/FindAllDuplicates/README.md: -------------------------------------------------------------------------------- 1 | # Find All Duplicates in an Array(数组中重复的数据) 2 | 3 | **LeetCode 442** 4 | 5 | - [英文版](https://leetcode.com/problems/find-all-duplicates-in-an-array/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/find-all-duplicates-in-an-array/) 8 | 9 | ## 题目 10 | 给定一个整数数组 a,其中1 ≤ a[i] ≤ n (n为数组长度), 其中有些元素出现两次而其他元素出现一次。 11 | 12 | 找到所有出现两次的元素。 13 | 14 | 你可以不用到任何额外空间并在O(n)时间复杂度内解决这个问题吗? 15 | 16 | 示例: 17 | 18 | ``` 19 | 输入: 20 | [4,3,2,7,8,2,3,1] 21 | 22 | 输出: 23 | [2,3] 24 | ``` 25 | ## 思路 26 |
27 | 点击展开 28 | 元素的值在不超过数组的长度,我们遍历数组,将元素值映射的下标改为负数,当遇到负数时,说明该元素下标映射的值已经出现过了。 29 |
30 | 31 | ## 代码实现 32 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 33 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 34 | | 🤔 | [😀](./FindAllDuplicates.cpp) | 🤔 | 🤔 | 🤔 | [😀](./FindAllDuplicates.py) | [😀](./FindAllDuplicates.js) | 🤔 | 🤔 | 35 | 36 | -------------------------------------------------------------------------------- /Array/NextPremutation/NextPremutation.js: -------------------------------------------------------------------------------- 1 | var nextPermutation = function(nums) { 2 | const len = nums.length; 3 | if (len < 2) return nums; 4 | 5 | let prev = nums[len - 1]; 6 | let k = len - 2; 7 | for (k; k >= 0; --k) { 8 | if (prev > nums[k]) { 9 | break; 10 | } 11 | prev = nums[k]; 12 | } 13 | if (k < 0) { 14 | return nums.reverse(); 15 | } 16 | // find rightest index for which value larger than nums[k] 17 | let l = len - 1; 18 | for(l; l > k; --l) { 19 | if (nums[l] > nums[k]) { 20 | break; 21 | } 22 | } 23 | // swap in-place 24 | [nums[k], nums[l]] = [nums[l], nums[k]]; 25 | // reverse start with i, equal to sort 26 | const reverse = (arr, i) => { 27 | const end = arr.length - 1; 28 | const mid = (i + end) / 2; 29 | for (let j = i; j <= mid; ++j) { 30 | [arr[j], arr[end-(j-i)]] = [arr[end-(j-i)], arr[j]]; 31 | } 32 | return arr; 33 | }; 34 | return reverse(nums, k + 1); 35 | }; 36 | 37 | -------------------------------------------------------------------------------- /String/LengthOfLongestSubstring/index.js: -------------------------------------------------------------------------------- 1 | // 解法一:O(n) 2 | const lengthOfLongestSubstring = (str) => { 3 | let maxLength = 0; 4 | const queue = []; // 使用队列存储无重复子串 5 | for (const element of str) { 6 | // 从头部开始检测是否有重复 O(n) 7 | const eleIdx = queue.indexOf(element); 8 | if (eleIdx != -1) { 9 | // 移除重复元素前的元素 10 | queue.splice(0, eleIdx + 1); 11 | } 12 | queue.push(element); 13 | 14 | maxLength = Math.max(queue.length, maxLength); 15 | } 16 | return maxLength; 17 | } 18 | 19 | // 解法二:O(n^2) 20 | const lengthOfLongestSubstring2 = (str) => { 21 | const cache = {}; 22 | let start = max = 0; 23 | for (let i = 0, n = str.length; i < n; ++i) { 24 | const char = str[i]; 25 | const newStart = typeof cache[char] === 'undefined' ? 0 : cache[char] + 1; 26 | start = Math.max(start, newStart); 27 | cache[char] = i; 28 | max = Math.max(i - start + 1, max); 29 | } 30 | return max; 31 | } -------------------------------------------------------------------------------- /Search/07.01Matrix/README.md: -------------------------------------------------------------------------------- 1 | # 01 Matrix(01 矩阵) 2 | 3 | **LeetCode 542** 4 | 5 | - [英文版](https://leetcode.com/problems/01-matrix/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/01-matrix/) 8 | 9 | ## 题目 10 | 给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离。 11 | 12 | 两个相邻元素间的距离为 1 。 13 | 14 | 示例 1: 15 | ``` 16 | 输入: 17 | 18 | 0 0 0 19 | 0 1 0 20 | 0 0 0 21 | 输出: 22 | 23 | 0 0 0 24 | 0 1 0 25 | 0 0 0 26 | ``` 27 | 28 | 示例 2: 29 | ``` 30 | 输入: 31 | 32 | 0 0 0 33 | 0 1 0 34 | 1 1 1 35 | 输出: 36 | 37 | 0 0 0 38 | 0 1 0 39 | 1 2 1 40 | ``` 41 | 42 | 注意: 43 | 44 | 1. 给定矩阵的元素个数不超过 10000。 45 | 2. 给定矩阵中至少有一个元素是 0。 46 | 3. 矩阵中的元素只在四个方向上相邻: 上、下、左、右。 47 | 48 | ## 思路 49 |
50 | 点击展开 51 | // TODO 52 |
53 | 54 | ## 代码实现 55 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 56 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 57 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 58 | 59 | -------------------------------------------------------------------------------- /BinaryTree/07.ConvertSortedListToBinarySearchTree/README.md: -------------------------------------------------------------------------------- 1 | # Convert Sorted List to Binary Search Tree(有序链表转换二叉查找树) 2 | 3 | **LeetCode 109** 4 | 5 | - [英文版](https://leetcode.com/problems/convert-sorted-list-to-binary-search-tree/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/convert-sorted-list-to-binary-search-tree/) 8 | 9 | ## 题目 10 | 11 | 给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树。 12 | 13 | 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。 14 | 15 | 示例: 16 | ``` 17 | 给定的有序链表: [-10, -3, 0, 5, 9], 18 | 19 | 一个可能的答案是:[0, -3, 9, -10, null, 5], 它可以表示下面这个高度平衡二叉搜索树: 20 | 21 | 0 22 | / \ 23 | -3 9 24 | / / 25 | -10 5 26 | ``` 27 | ## 思路 28 |
29 | 点击展开 30 | // TODO 31 |
32 | 33 | ## 代码实现 34 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 35 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 36 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 37 | 38 | -------------------------------------------------------------------------------- /BackTracking/01.N-Queens/README.md: -------------------------------------------------------------------------------- 1 | # N-Queens(N 皇后) 2 | 3 | **LeetCode 51** 4 | 5 | - [英文版](https://leetcode.com/problems/n-queens/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/n-queens/) 8 | 9 | ## 题目 10 | n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。 11 | 12 | 上图为 8 皇后问题的一种解法。 13 | 14 | 给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。 15 | 16 | 每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。 17 | 18 | 示例: 19 | ``` 20 | 输入: 4 21 | 输出: [ 22 | [".Q..", // 解法 1 23 | "...Q", 24 | "Q...", 25 | "..Q."], 26 | 27 | ["..Q.", // 解法 2 28 | "Q...", 29 | "...Q", 30 | ".Q.."] 31 | ] 32 | 解释: 4 皇后问题存在两个不同的解法。 33 | ``` 34 | ## 思路 35 |
36 | 点击展开 37 | // TODO 38 |
39 | 40 | ## 代码实现 41 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 42 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 43 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | [😀](./N-Queens.py) | 🤔 | 🤔 | 🤔 | 44 | 45 | 完成 😀,待完成 🤔 46 | -------------------------------------------------------------------------------- /Search/04.WordSearch2/README.md: -------------------------------------------------------------------------------- 1 | # Word Search II(单词搜索 II) 2 | 3 | **LeetCode 212** 4 | 5 | - [英文版](https://leetcode.com/problems/word-search-ii/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/word-search-ii/) 8 | 9 | ## 题目 10 | 给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在二维网格和字典中出现的单词。 11 | 12 | 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。 13 | 14 | 示例: 15 | 16 | 输入: 17 | ``` 18 | words = ["oath","pea","eat","rain"] and board = 19 | [ 20 | ['o','a','a','n'], 21 | ['e','t','a','e'], 22 | ['i','h','k','r'], 23 | ['i','f','l','v'] 24 | ] 25 | 26 | 输出: ["eat","oath"] 27 | ``` 28 | 说明: 29 | 你可以假设所有输入都由小写字母 a-z 组成。 30 | 31 | ## 思路 32 |
33 | 点击展开 34 | // TODO 35 |
36 | 37 | ## 代码实现 38 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 39 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 40 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 41 | 42 | -------------------------------------------------------------------------------- /Search/05.SearchInRotatedArray/README.md: -------------------------------------------------------------------------------- 1 | # Search in Rotated Sorted Array(搜索旋转排序数组) 2 | 3 | **LeetCode 33** 4 | 5 | - [英文版](https://leetcode.com/problems/search-in-rotated-sorted-array/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/search-in-rotated-sorted-array/) 8 | 9 | ## 题目 10 | 假设按照升序排序的数组在预先未知的某个点上进行了旋转。 11 | 12 | ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。 13 | 14 | 搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。 15 | 16 | 你可以假设数组中不存在重复的元素。 17 | 18 | 你的算法时间复杂度必须是 O(log n) 级别。 19 | 20 | 示例 1: 21 | ``` 22 | 输入: nums = [4,5,6,7,0,1,2], target = 0 23 | 输出: 4 24 | ``` 25 | 26 | 示例 2: 27 | ``` 28 | 输入: nums = [4,5,6,7,0,1,2], target = 3 29 | 输出: -1 30 | ``` 31 | ## 思路 32 |
33 | 点击展开 34 | // TODO 35 |
36 | 37 | ## 代码实现 38 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 39 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 40 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 41 | 42 | -------------------------------------------------------------------------------- /Search/06.SearchA2DMatrix/README.md: -------------------------------------------------------------------------------- 1 | # Search a 2D Matrix(搜索二维矩阵) 2 | 3 | **LeetCode 74** 4 | 5 | - [英文版](https://leetcode.com/problems/search-a-2d-matrix/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/search-a-2d-matrix/) 8 | 9 | ## 题目 10 | 编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性: 11 | 12 | 每行中的整数从左到右按升序排列。 13 | 每行的第一个整数大于前一行的最后一个整数。 14 | 示例 1: 15 | ``` 16 | 输入: 17 | matrix = [ 18 | [1, 3, 5, 7], 19 | [10, 11, 16, 20], 20 | [23, 30, 34, 50] 21 | ] 22 | target = 3 23 | 输出: true 24 | ``` 25 | 示例 2: 26 | ``` 27 | 输入: 28 | matrix = [ 29 | [1, 3, 5, 7], 30 | [10, 11, 16, 20], 31 | [23, 30, 34, 50] 32 | ] 33 | target = 13 34 | 输出: false 35 | ``` 36 | ## 思路 37 |
38 | 点击展开 39 | // TODO 40 |
41 | 42 | ## 代码实现 43 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 44 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 45 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 46 | 47 | -------------------------------------------------------------------------------- /BackTracking/03.RegularExpressingMatching/regular-expression-matching.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func isMatch(s string, p string) bool { 6 | if p == "" { 7 | return s == "" 8 | } 9 | 10 | last := p[len(p)-1] 11 | if last != '*' { 12 | 13 | if len(s) == 0 { 14 | return false 15 | } 16 | 17 | if last != '.' && s[len(s)-1] != p[len(p)-1] { 18 | return false 19 | } 20 | 21 | return isMatch(s[:len(s)-1], p[:len(p)-1]) 22 | } 23 | 24 | result := false 25 | result = result || isMatch(s, p[:len(p)-2]) 26 | patternChar := p[len(p)-2] 27 | if s != "" && (patternChar == '.' || s[len(s)-1] == patternChar) { 28 | result = result || isMatch(s[:len(s)-1], p) 29 | } 30 | 31 | return result 32 | } 33 | 34 | func main() { 35 | fmt.Println(isMatch("aa", "a")) 36 | fmt.Println(isMatch("aa", "a*")) 37 | fmt.Println(isMatch("ab", ".*")) 38 | fmt.Println(isMatch("aab", "c*a*b")) 39 | fmt.Println(isMatch("mississippi", "mis*is*p*.")) 40 | } 41 | -------------------------------------------------------------------------------- /Sort/04.QuickSort/QuickSort.js: -------------------------------------------------------------------------------- 1 | // 快速排序 2 | // 不稳定 3 | // 原地 4 | const quickSort = (arr) => { 5 | const n = arr.length 6 | if (n <= 1) return; 7 | _quickSort(arr, 0, n-1); 8 | } 9 | 10 | const _quickSort = (arr, left, right) => { 11 | if (left >= right) return; 12 | const pivot = _patition(arr, left, right); 13 | _quickSort(arr, left, pivot - 1); 14 | _quickSort(arr, pivot + 1, right); 15 | } 16 | 17 | const _patition = (arr, left, right) => { 18 | const pivot = arr[right]; 19 | let i = left; 20 | for (let j = left; j < right; ++j) { 21 | if (arr[j] < pivot) { 22 | _swap(arr, i, j); 23 | ++i; 24 | } 25 | } 26 | _swap(arr, i, right); 27 | return i; 28 | } 29 | 30 | const _swap = (arr, i, j) => { 31 | const tmp = arr[i]; 32 | arr[i] = arr[j]; 33 | arr[j] = tmp; 34 | } 35 | 36 | 37 | const arr = [23, 3, 2, 12, 34, 23, 4, 32, 19, 39]; 38 | quickSort(arr); 39 | console.log(arr); 40 | -------------------------------------------------------------------------------- /BinaryTree/README.md: -------------------------------------------------------------------------------- 1 | # BinaryTree(二叉树) 2 | 3 | [01. Same Tree(相同的树)](./01.SameTree) 4 | 5 | [02. Symmetric Tree (对称二叉树)](./02.SymmetricTree) 6 | 7 | [03. Invert Binary Tree(翻转二叉树)](./03.InvertBinaryTree) 8 | 9 | [04. Maximum Depth of Binary Tree(二叉树的最大深度)](./04.MaximumDepthOfBinaryTree) 10 | 11 | [05. Balanced Binary Tree(判断平衡二叉树)](./05.BalancedBinaryTree) 12 | 13 | [06. Validate Binary Search Tree(验证二叉查找树)](./06.ValidateBinarySearchTree) 14 | 15 | [07. Convert Sorted List to Binary Search Tree(有序链表转换二叉查找树)](./07.ConvertSortedListToBinarySearchTree) 16 | 17 | [08. Flatten Binary Tree to Linked List(二叉树展开为链表)](./08.FlattenBinaryTreeToLinkedList) 18 | 19 | [09. Binary Tree Zigzag Level Order Traversal(二叉树的锯齿形层次遍历)](./09.BinaryTreeLevelTraversal) 20 | 21 | [10. Find Largest Value in Each Tree Row(在每个树行中找最大值)](./10.FindLargestValue) 22 | 23 | [11. Path Sum(路径总和)](./11.PathSum) 24 | 25 | [12. Convert Sorted Array to Binary Search Tree(将有序数组转换为二叉搜索树)](./12.ConvertToBinarySearchTree) 26 | -------------------------------------------------------------------------------- /Array/MajorityElement/MajorityElement.js: -------------------------------------------------------------------------------- 1 | // O(n) time, O(n) space 2 | var majorityElement = function(nums) { 3 | // O(n) 空间复杂度的解法 4 | const map = {}; // 存储元素出现的次数 5 | nums.forEach(ele => { 6 | if (!map[ele]) { 7 | map[ele] = 1; 8 | } else { 9 | map[ele] = map[ele] + 1; 10 | } 11 | }); 12 | for (let key in map) { 13 | if (map[key] > nums.length / 2) { // 查找出现次数大于一半的元素 14 | return key; 15 | } 16 | } 17 | return null; 18 | }; 19 | 20 | // O(n) time, O(1) space 21 | 22 | const majorityElement2 = function(nums) { 23 | if (!nums || nums.length <= 0) return; 24 | let count = 0, cur = numbs[0]; 25 | for (let i = 1; i < nums.length; ++i) { 26 | if (nums[i] === cur) { 27 | count++; 28 | } else { 29 | count--; 30 | if (count === 0) { 31 | cur = nums[i+1]; 32 | } 33 | } 34 | } 35 | return cur; 36 | } 37 | -------------------------------------------------------------------------------- /BinaryTree/05.BalancedBinaryTree/README.md: -------------------------------------------------------------------------------- 1 | # Balanced Binary Tree(平衡二叉树) 2 | 3 | **LeetCode 110** 4 | 5 | - [英文版](https://leetcode.com/problems/balanced-binary-tree/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/balanced-binary-tree/) 8 | 9 | ## 题目 10 | 给定一个二叉树,判断它是否是高度平衡的二叉树。 11 | 12 | 本题中,一棵高度平衡二叉树定义为: 13 | 14 | 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。 15 | 16 | 示例 1: 17 | 18 | 给定二叉树 [3,9,20,null,null,15,7] 19 | ``` 20 | 3 21 | / \ 22 | 9 20 23 | / \ 24 | 15 7 25 | ``` 26 | 返回 true 。 27 | 28 | 示例 2: 29 | 30 | 给定二叉树 [1,2,2,3,3,null,null,4,4] 31 | ``` 32 | 1 33 | / \ 34 | 2 2 35 | / \ 36 | 3 3 37 | / \ 38 | 4 4 39 | ``` 40 | 返回 false 。 41 | 42 | ## 思路 43 |
44 | 点击展开 45 | // TODO 46 |
47 | 48 | ## 代码实现 49 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 50 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 51 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 52 | 53 | -------------------------------------------------------------------------------- /BinaryTree/06.ValidateBinarySearchTree/README.md: -------------------------------------------------------------------------------- 1 | # Validate Binary Search Tree(验证二叉查找树) 2 | 3 | **LeetCode 98** 4 | 5 | - [英文版](https://leetcode.com/problems/validate-binary-search-tree/) 6 | - [中文版](https://leetcode-cn.com/problems/validate-binary-search-tree/) 7 | 8 | ## 题目 9 | 给定一个二叉树,判断其是否是一个有效的二叉搜索树。 10 | 11 | 假设一个二叉搜索树具有如下特征: 12 | 13 | 节点的左子树只包含小于当前节点的数。 14 | 节点的右子树只包含大于当前节点的数。 15 | 所有左子树和右子树自身必须也是二叉搜索树。 16 | 17 | 示例 1: 18 | ``` 19 | 输入: 20 | 2 21 | / \ 22 | 1 3 23 | 输出: true 24 | ``` 25 | 26 | 示例 2: 27 | ``` 28 | 输入: 29 | 5 30 | / \ 31 | 1 4 32 | / \ 33 | 3 6 34 | 输出: false 35 | 解释: 输入为: [5,1,4,null,null,3,6]。 36 | 根节点的值为 5 ,但是其右子节点值为 4 。 37 | ``` 38 | ## 思路 39 |
40 | 点击展开 41 | // TODO 42 |
43 | 44 | ## 代码实现 45 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 46 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 47 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 48 | 49 | -------------------------------------------------------------------------------- /Array/ThreeSum/ThreeSum.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number[][]} 4 | */ 5 | var threeSum = function(nums) { 6 | const res = []; 7 | nums.sort((a, b) => a - b); 8 | for (let i = 0, n = nums.length - 2; i < n; ++i) { 9 | if (i > 0 && nums[i] === nums[i - 1]) continue; 10 | 11 | let l = i + 1; 12 | let r = nums.length - 1; 13 | 14 | while (l < r) { 15 | s = nums[i] + nums[l] + nums[r]; 16 | if (s < 0) { 17 | l++; 18 | } else if ( s > 0) { 19 | r--; 20 | } else { 21 | res.push([nums[i], nums[l], nums[r]]); 22 | while (l < r && nums[l] === nums[l + 1]) { 23 | l++; 24 | } 25 | while (l < r && nums[r] === nums[r - 1]) { 26 | r--; 27 | } 28 | l++; 29 | r--; 30 | } 31 | } 32 | } 33 | return res; 34 | }; -------------------------------------------------------------------------------- /dp/LongestIncreasingSubsequence/lis.js: -------------------------------------------------------------------------------- 1 | /* 2 | 先不考虑最长子序列,同一长度的递增子序列可能有多个,比如说 {2, 7, 5},长度为 2 的子序列有 {2,5}, {2,7},如果下一个元素是 6,那么 {2,7} 对我们来说没有意义,同一长度的子序列,我们只关心最小的尾数。 3 | 4 | 使用一个数组 tail 来保存每一种长度子序列最小的末尾元素, tail 将会是个递增数组。从数组第一个元素开始,逐个考察,如果元素比 tail 数组的末尾元素大,我们就将该元素添加进入 tail。 5 | 6 | 如果比 tail 小,就查找该元素所在的区间,用它替换 tail 元素中,比它大的最小的元素。因为 tail 是有序的,所以可以使用二分查找。 7 | **/ 8 | 9 | var lengthOfLIS = function(nums) { 10 | const n = nums.length; 11 | let tail = Array(n).fill(0); 12 | let s = 0; // tail 的长度 13 | for (let i = 0; i < n; ++i) { 14 | let l = 0; 15 | let r = s; 16 | // 二分查找 17 | while (l != r) { 18 | const m = ((l + r) / 2) | 0; // m 取整 19 | if (nums[i] > tail[m]) { 20 | l = m+1; 21 | } else { 22 | r = m; 23 | } 24 | } 25 | // 二分查找结束 l 对应目标放置位置 26 | tail[l] = nums[i]; 27 | // 如果目标位置是 tail 的长度,说明是添加到尾部的 28 | if (l === s) ++s; 29 | } 30 | return s; 31 | }; 32 | 33 | -------------------------------------------------------------------------------- /Stack/03.ValidParentheses/valid_parentheses.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type Stack struct { 6 | strs []rune 7 | } 8 | 9 | func (self *Stack) push(char rune) { 10 | self.strs = append(self.strs, char) 11 | } 12 | 13 | func (self *Stack) pop() { 14 | self.strs = self.strs[:len(self.strs)-1] 15 | } 16 | 17 | func (self *Stack) top() rune { 18 | return self.strs[len(self.strs)-1] 19 | } 20 | 21 | func (self *Stack) isEmpty() bool { 22 | return len(self.strs) == 0 23 | } 24 | 25 | func isValid(s string) bool { 26 | 27 | parenteseMap := map[rune]rune{ 28 | '(': ')', 29 | '[': ']', 30 | '{': '}', 31 | } 32 | 33 | stack := &Stack{} 34 | for _, char := range s { 35 | 36 | if stack.isEmpty() || parenteseMap[stack.top()] != char { 37 | stack.push(char) 38 | } else { 39 | stack.pop() 40 | } 41 | } 42 | 43 | return stack.isEmpty() 44 | } 45 | 46 | func main() { 47 | 48 | fmt.Println(isValid("()")) 49 | fmt.Println(isValid("()[]{}")) 50 | fmt.Println(isValid("(]")) 51 | fmt.Println(isValid("{[]}")) 52 | } 53 | -------------------------------------------------------------------------------- /Array/KthLargestElement/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @param {number} k 4 | * @return {number} 5 | */ 6 | // 时间复杂度 O(NlogN) 7 | var findKthLargest = function(nums, k) { 8 | // 二分查找 9 | const quickSelect = (nums, left, right, tIndex) => { 10 | const pvoit = nums[right]; 11 | let l = left, r = right; 12 | while (l < r) { 13 | // 左边跳过比 pvoit 大的数 14 | while (nums[l] > pvoit && l < r) l++; 15 | // 右边跳过不大于 pvoit 的数 16 | while (nums[r] <= pvoit && l < r) r--; 17 | // 此时 num[l] 一定大于或等于 nums[r],交换它们 18 | [nums[l], nums[r]] = [nums[r], nums[l]]; 19 | } 20 | // 一次二分结束,将 pvoit 交换的中间位置 21 | [nums[right], nums[l]] = [nums[l], nums[right]]; 22 | 23 | if (tIndex > l) { 24 | // 目标值在右边 25 | return quickSelect(nums, l + 1, right, tIndex); 26 | } else if (tIndex < l) { 27 | // 目标值在左边 28 | return quickSelect(nums, left, l - 1, tIndex); 29 | } else { 30 | return nums[l]; 31 | } 32 | } 33 | 34 | return quickSelect(nums, 0, nums.length - 1, k - 1); 35 | }; -------------------------------------------------------------------------------- /LinkedList/ReverseNodesKGroup/ReverseNodesKGroup.php: -------------------------------------------------------------------------------- 1 | val = $val; } 9 | * } 10 | */ 11 | class Solution 12 | { 13 | 14 | /** 15 | * @param ListNode $head 16 | * @param Integer $k 17 | * @return ListNode 18 | */ 19 | function reverseKGroup($head, $k) 20 | { 21 | $dummy = new ListNode(-1); 22 | $pre = $cur = $dummy; 23 | $dummy->next = $head; 24 | $num = 0; 25 | while ($cur = $cur->next) ++$num; 26 | while ($num >= $k) { 27 | $cur = $pre->next; 28 | for ($i = 1; $i < $k; ++$i) { 29 | $t = $cur->next; 30 | $cur->next = $t->next; 31 | $t->next = $pre->next; 32 | $pre->next = $t; 33 | } 34 | $pre = $cur; 35 | $num -= $k; 36 | } 37 | return $dummy->next; 38 | } 39 | } -------------------------------------------------------------------------------- /DivideAndConquer/1.ClosestPairOfPoints/README.md: -------------------------------------------------------------------------------- 1 | # ClosestPairOfPoints(平面内两点的最短距离) 2 | [GeeksforGeeks](https://www.geeksforgeeks.org/closest-pair-of-points-using-divide-and-conquer-algorithm/) 3 | 4 | ## 题目 5 | 给定平面上 n 个点,每个点坐标分别为 (x,y),求其中的一对点,使得在 n 个点组成的所有点对中,该点对的距离最小。 6 | 7 | ## 思路 8 |
9 | 点击展开 10 | 11 | 1. 将所有点按照横坐标排序,取中间的点,将平面分成左右两部分,时间复杂度 O(nlogn); 12 | 13 | 2. 左边区域点对的最短距离为 dl,右边区域点对的最短距离为 dr, d = min(dl, dr); 14 | 15 | 3. 最短距离的点也能分布在左右两侧,并且横坐标在区间 [midX - d, midX + d],纵坐标的差值小于等于 d 的区间内; 16 | 17 | 4. 过滤出位于 midX 左右两侧的目标点,并按照纵坐标大小排序,在 y1 - y2 <= d 的范围内符合要求的点不会超过 6 个; 18 | 19 | 5. 在一侧 d x d 的范围内,不能存在两个点的距离小于 d,否则在同一侧,d 的就不是最短距离了; 20 | 21 | 6. 如果一个点与另一个点的距离小于等于 d,在 d x d 的范围内会构成一个 1/4 半径等于 d 圆型,面积:`(d^2 * π)/4 = π*d^2/16`; 22 | 23 | 7. d x d 的区域可能存在 16/π ≈ 5.1 个这样的区域,所以符合条件的点不会超过 6 个; 24 | 25 | 8. 比较 d 和两侧区域最短距离,取最小值对应的点对即为目标解。 26 |
27 | 28 | ## 代码实现 29 | | C | C++ | Java | Python | JavaScript | Go | PHP | 30 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 31 | | [😀](./ClosestPairOfPoints.c) | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 32 | 33 | -------------------------------------------------------------------------------- /Stack/03.ValidParentheses/README.md: -------------------------------------------------------------------------------- 1 | # Valid Parentheses(有效的括号) 2 | 3 | **LeetCode 20** 4 | 5 | - [英文版](https://leetcode.com/problems/valid-parentheses/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/valid-parentheses/) 8 | 9 | ## 题目 10 | 给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。 11 | 12 | 有效字符串需满足: 13 | 14 | 左括号必须用相同类型的右括号闭合。 15 | 左括号必须以正确的顺序闭合。 16 | 注意空字符串可被认为是有效字符串。 17 | 18 | 示例 1: 19 | ``` 20 | 输入: "()" 21 | 输出: true 22 | ``` 23 | 示例 2: 24 | ``` 25 | 输入: "()[]{}" 26 | 输出: true 27 | ``` 28 | 29 | 示例 3: 30 | ``` 31 | 输入: "(]" 32 | 输出: false 33 | ``` 34 | 35 | 示例 4: 36 | ``` 37 | 输入: "([)]" 38 | 输出: false 39 | ``` 40 | 示例 5: 41 | ``` 42 | 输入: "{[]}" 43 | 输出: true 44 | ``` 45 | ## 思路 46 |
47 | 点击展开 48 | // TODO 49 |
50 | 51 | ## 代码实现 52 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 53 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 54 | | 🤔 | [😀](./validParentheses.cpp) | 🤔 | 🤔 | 🤔 | 🤔 | [😀](./validParentheses.js) | [😀](./valid_parentheses.go) | 🤔 | 55 | 56 | 完成 😀,待完成 🤔 57 | -------------------------------------------------------------------------------- /Array/KthLargestElement/KthLargestElement.cpp: -------------------------------------------------------------------------------- 1 | 2 | class Solution { 3 | public: 4 | int findKthLargest(vector& nums, int k) { 5 | return _quickSelect(nums, 0, nums.size()-1, k-1); 6 | } 7 | 8 | int _quickSelect(vector nums, int left, int right, int k) { 9 | int origin_left = left, origin_right = right; 10 | int pivot = nums[origin_right]; 11 | while (left < right) { 12 | while (left < right && nums[left] > pivot) { left++; } 13 | while (left < right && nums[right] <= pivot) { right--; } 14 | int tmp = nums[left]; 15 | nums[left] = nums[right]; 16 | nums[right] = tmp; 17 | } 18 | nums[origin_right] = nums[left]; 19 | nums[left] = pivot; 20 | 21 | 22 | if (k == left) { 23 | return nums[left]; 24 | } 25 | else if (k > left) { 26 | return _quickSelect(nums, left+1, origin_right, k); 27 | } 28 | else { 29 | return _quickSelect(nums, origin_left, left-1, k); 30 | } 31 | } 32 | }; -------------------------------------------------------------------------------- /BinaryTree/01.SameTree/README.md: -------------------------------------------------------------------------------- 1 | # Same Tree(相同的树) 2 | 3 | **LeetCode 100** 4 | 5 | - [英文版](https://leetcode.com/problems/same-tree/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/same-tree/) 8 | 9 | ## 题目 10 | 给定两个二叉树,编写一个函数来检验它们是否相同。 11 | 12 | 如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。 13 | 14 | 示例 1: 15 | ``` 16 | 输入: 1 1 17 | / \ / \ 18 | 2 3 2 3 19 | 20 | [1,2,3], [1,2,3] 21 | 22 | 输出: true 23 | ``` 24 | 25 | 示例 2: 26 | ``` 27 | 输入: 1 1 28 | / \ 29 | 2 2 30 | 31 | [1,2], [1,null,2] 32 | 33 | 输出: false 34 | ``` 35 | 36 | 示例 3: 37 | ``` 38 | 输入: 1 1 39 | / \ / \ 40 | 2 1 1 2 41 | 42 | [1,2,1], [1,1,2] 43 | 44 | 输出: false 45 | ``` 46 | 47 | ## 思路 48 |
49 | 点击展开 50 | // TODO 51 |
52 | 53 | ## 代码实现 54 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 55 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 56 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 57 | 58 | -------------------------------------------------------------------------------- /Queue/03.QueueUsingStacks/README.md: -------------------------------------------------------------------------------- 1 | # Implement Queue using Stacks(用栈实现队列) 2 | LeetCode 232 3 | [English](https://leetcode.com/problems/implement-queue-using-stacks/) 4 | [中文](https://leetcode-cn.com/problems/implement-queue-using-stacks/) 5 | 6 | ## 题目 7 | 使用栈实现队列的下列操作: 8 | 9 | push(x) -- 将一个元素放入队列的尾部。 10 | pop() -- 从队列首部移除元素。 11 | peek() -- 返回队列首部的元素。 12 | empty() -- 返回队列是否为空。 13 | 示例: 14 | ``` 15 | MyQueue queue = new MyQueue(); 16 | 17 | queue.push(1); 18 | queue.push(2); 19 | queue.peek(); // 返回 1 20 | queue.pop(); // 返回 1 21 | queue.empty(); // 返回 false 22 | ``` 23 | 说明: 24 | 25 | - 你只能使用标准的栈操作 -- 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。 26 | - 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。 27 | - 假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)。 28 | 29 | ## 思路 30 |
31 | 点击展开 32 | // TODO 33 |
34 | 35 | ## 代码实现 36 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 37 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 38 | | 🤔 | [😀](./implementQueueUsingStacks.hpp) | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 39 | 40 | -------------------------------------------------------------------------------- /Array/KthLargestElement/KthLargestElement.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def findKthLargest(self, nums, k): 3 | """ 4 | :type nums: List[int] 5 | :type k: int 6 | :rtype: int 7 | """ 8 | return self._quick_select(nums, 0, len(nums) - 1, k - 1) # 注意 k-1 9 | 10 | def _quick_select(self, nums, left, right, k): 11 | pvoit = nums[right] 12 | origin_left, origin_right = left, right 13 | 14 | while left < right: 15 | # 左边略过比 pvoit 大的 16 | while nums[left] > pvoit and left < right: left += 1 17 | # 右边略过比 pvoit 小的 18 | while nums[right] <= pvoit and left < right: right -= 1 19 | # 否则交换左右元素 20 | nums[left], nums[right] = nums[right], nums[left] 21 | 22 | # 把 pvoit 交换到中间 23 | nums[left], nums[origin_right] = nums[origin_right], nums[left] 24 | if k == left: 25 | return nums[left] 26 | elif k > left: 27 | return self._quick_select(nums, left + 1, origin_right, k) 28 | else: 29 | return self._quick_select(nums, origin_left, left - 1, k) 30 | -------------------------------------------------------------------------------- /Array/KthLargestElement/README.md: -------------------------------------------------------------------------------- 1 | # Kth Largest Element in an Array(数组中的第K个最大元素) 2 | 3 | **LeetCode 215** 4 | 5 | - [英文版](https://leetcode.com/problems/kth-largest-element-in-an-array/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/kth-largest-element-in-an-array/) 8 | 9 | ## 题目 10 | 在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。 11 | 12 | 示例 1: 13 | ``` 14 | 输入: [3,2,1,5,6,4] 和 k = 2 15 | 输出: 5 16 | ``` 17 | 示例 2: 18 | ``` 19 | 输入: [3,2,3,1,2,4,5,5,6] 和 k = 4 20 | 输出: 4 21 | ``` 22 | 23 | 说明: 24 | 25 | 你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。 26 | 27 | ## 思路 28 |
29 | 点击展开 30 | 31 | 题中有个要点容易误解,目标值位于数组从大到小排序的第 k 下标,而不是去重后按元素值从大到小的序位; 32 | 33 | 对于无序数组查找的场景,首先要想到的是二分查找,它的时间复杂度仅次于有序数组查找 O(n)。 34 | 35 | 对于二分比较关键的优化点是,pvoit 的确定,会影响实际的效率,工业算法一般会随机一个下标。 36 | 37 | 不过随机算法也有一定的开销,这题就直接用最右边的下标作为 pvoit 了。 38 | 39 | 这像是快排的简化版本。 40 | 41 | 二分查找是一种解法,另一个解法可以采用大顶堆,请自行尝试~ 42 |
43 | 44 | ## 代码实现 45 | 46 | | C++ | Java | Python | JavaScript | Go | PHP | 47 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 48 | | [😀](KthLargestElement.cpp) | 🤔 | [😀](KthLargestElement.py) | [😀](./index.js) | 🤔 | 🤔 | 49 | -------------------------------------------------------------------------------- /Sort/03.MergeSort/MergeSort.js: -------------------------------------------------------------------------------- 1 | // 归并排序 2 | // time: O(nlog(n)) 3 | // space: O(n) 4 | // 非原地排序 5 | // 稳定排序 6 | 7 | const mergeSort = (list) => { 8 | if (list.length <= 1) return list; 9 | const middle = list.length / 2; 10 | const left = list.slice(0, middle); 11 | const right = list.slice(middle); 12 | 13 | return merge(mergeSort(left), mergeSort(right)); 14 | } 15 | 16 | const merge = (leftList, rightList) => { 17 | let tmpList = []; leftIndex = 0; rightIndex = 0; 18 | while (leftIndex < leftList.length && rightIndex < rightList.length) { 19 | if (leftList[leftIndex] <= rightList[rightIndex]) { // 取 = 确定是稳定的排序 20 | tmpList.push(leftList[leftIndex]); 21 | leftIndex++; 22 | } else { 23 | tmpList.push(rightList[rightIndex]); 24 | rightIndex++; 25 | } 26 | } 27 | return tmpList.concat(leftList.slice(leftIndex).concat(rightList.slice(rightIndex))); 28 | } 29 | 30 | 31 | const list = [3, 4, 40, 23, 12, 4, 12, 4, 32, 1234, 23]; 32 | const r = mergeSort(list); 33 | console.log(r); 34 | 35 | // 排序的思路虽然一样,但是受语言的影响,实现形式看起来差别还是挺大的 36 | // 最好不要修改入参 37 | -------------------------------------------------------------------------------- /LinkedList/ReverseLinkedList/ReverseLinkedList.php: -------------------------------------------------------------------------------- 1 | val = $val; } 9 | * } 10 | */ 11 | class Solution 12 | { 13 | 14 | 15 | /** 16 | * @param ListNode $head 17 | * @return ListNode 18 | */ 19 | function reverseList($head) 20 | { 21 | $current = $head; 22 | $newList = null; 23 | while ($current) { 24 | $nextNode = $current->next; 25 | $current->next = $newList; 26 | $newList = $current; 27 | $current = $nextNode; 28 | } 29 | 30 | return $newList; 31 | } 32 | 33 | 34 | //recursion 35 | function reverseListForRecursion($head){ 36 | 37 | if(!$head || !$head->next){ 38 | return $head; 39 | } 40 | $newList=$this->reverseList($head->next); 41 | //we want n(k+1)'s next node to point k(n),so 42 | $head->next->next=$head; 43 | $head->next=null; 44 | return $newList; 45 | } 46 | } -------------------------------------------------------------------------------- /dp/EditDistance/editDistance.js: -------------------------------------------------------------------------------- 1 | function min(a, b, c) { 2 | let min = a; 3 | if (b < min) { 4 | min = b; 5 | } 6 | if (c < min) { 7 | min = c 8 | } 9 | return min; 10 | } 11 | 12 | var minDistance2 = function(word1, word2) { 13 | const m = word1.length + 1, n = word2.length + 1; 14 | const minDist = []; 15 | const row0 = [] 16 | // 填充第一行数据 17 | for (let j = 0; j < n; ++j) { 18 | row0.push(j); 19 | } 20 | minDist.push(row0); 21 | // 创建 1~m 个数组,填充第一个元素 22 | // 也就是二维数组的第一列 23 | for (let i = 1; i < m; ++i) { 24 | let row = []; 25 | row[0] = i; 26 | minDist.push(row); 27 | } 28 | // 最小值填表 29 | for (let i = 1; i < m; ++i) { 30 | for (let j = 1; j < n; ++j) { 31 | if (word1[i-1] == word2[j-1]) { 32 | minDist[i][j] = min(minDist[i-1][j-1], minDist[i][j-1] + 1, minDist[i-1][j] + 1); 33 | } else { 34 | minDist[i][j] = min(minDist[i-1][j-1] + 1, minDist[i][j-1] + 1, minDist[i-1][j] + 1); 35 | } 36 | } 37 | } 38 | 39 | return minDist[m-1][n-1]; 40 | } 41 | 42 | -------------------------------------------------------------------------------- /LinkedList/LinkedListCycle/README.md: -------------------------------------------------------------------------------- 1 | # Linked List Cycle I(环形链表) 2 | 3 | **LeetCode 142** 4 | 5 | - [英文版](https://leetcode.com/problems/linked-list-cycle/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/linked-list-cycle/) 8 | 9 | ## 题目 10 | 给定一个链表,判断链表中是否有环。 11 | 12 | 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。 13 | 14 | 示例 1: 15 | ``` 16 | 输入:head = [3,2,0,-4], pos = 1 17 | 输出:true 18 | 解释:链表中有一个环,其尾部连接到第二个节点。 19 | ``` 20 | 21 | 示例 2: 22 | ``` 23 | 输入:head = [1,2], pos = 0 24 | 输出:true 25 | 解释:链表中有一个环,其尾部连接到第一个节点。 26 | ``` 27 | 28 | 示例 3: 29 | ``` 30 | 输入:head = [1], pos = -1 31 | 输出:false 32 | 解释:链表中没有环。 33 | ``` 34 | 35 | 进阶: 36 | 37 | 你能用 O(1)(即,常量)内存解决此问题吗? 38 | 39 | ## 思路 40 |
41 | 点击展开 42 | 快慢指针,快指针每次前进两步,慢指针每次前进一步。如果链表中不存在环,则快指针先到达链表尾;若存在环,则快慢指针总会相遇。 43 |
44 | 45 | ## 代码实现 46 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 47 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 48 | | 🤔 | [😀](./LinkedListCycle.cpp) | [😀](./LinkedListCycle.java) | 🤔 | 🤔 | [😀](./LinkedListCycle.py) | 🤔 | [😀](./linked_list_cycle.go) | 🤔 | 49 | 50 | -------------------------------------------------------------------------------- /LinkedList/ReverseNodesKGroup/README.md: -------------------------------------------------------------------------------- 1 | # Reverse Nodes in k-Group(k 个一组翻转链表) 2 | 3 | **LeetCode 25** 4 | 5 | - [英文版](https://leetcode.com/problems/reverse-nodes-in-k-group/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/reverse-nodes-in-k-group/) 8 | 9 | ## 题目 10 | 给出一个链表,每 k 个节点一组进行翻转,并返回翻转后的链表。 11 | 12 | k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么将最后剩余节点保持原有顺序。 13 | 14 | 示例 : 15 | ``` 16 | 给定这个链表:1->2->3->4->5 17 | 18 | 当 k = 2 时,应当返回: 2->1->4->3->5 19 | 20 | 当 k = 3 时,应当返回: 3->2->1->4->5 21 | ``` 22 | 23 | 说明 : 24 | 25 | 你的算法只能使用常数的额外空间。 26 | 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。 27 | 28 | ## 思路 29 |
30 | 点击展开 31 | 32 | 该题有两种解法,递归和迭代。 33 | 34 | 递归:取前 k 个节点,进行翻转,如果不足 k 个,则不翻转。剩下的链表其实是题目的子问题,递归调用即可。将递归调用后的链表与前 k 个翻转的链表进行连接。连接后的结果返回,就是目标解。 35 | 36 | 迭代:迭代的解法比递归的难。需要借助辅助节点。开始时辅助节点指向头节点。 37 | 用两个指针(prev、back)分别记录前驱后继,另外两个指针(begin、end)记录子链表首尾;子链表翻转后将其与前面已翻转链表和后面未翻转链表进行连接。 38 | 39 |
40 | 41 | ## 代码实现 42 | | C++ | Java | Swift | Python | JavaScript | Go | 43 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 44 | | [😀](./ReverseNodesKGroup.cpp) | 🤔 | 🤔 | 🤔 | [😀](./ReverseNodesKGroup.js)| 🤔 | 45 | 46 | -------------------------------------------------------------------------------- /LinkedList/MergeSortedLists/MergeSortedLists.cpp: -------------------------------------------------------------------------------- 1 | /// 迭代 2 | class Solution { 3 | public: 4 | ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) { 5 | ListNode *mergeNode = new ListNode(0); 6 | ListNode *newHead = mergeNode; 7 | while(l1 && l2) { 8 | if(l1->val < l2->val) { 9 | mergeNode->next = l1; 10 | l1 = l1->next; 11 | } 12 | else { 13 | mergeNode->next = l2; 14 | l2 = l2->next; 15 | } 16 | mergeNode = mergeNode->next; 17 | } 18 | mergeNode->next = l1 ? l1 : l2; 19 | return newHead->next; 20 | } 21 | }; 22 | 23 | /// 递归 24 | class Solution { 25 | public: 26 | ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) { 27 | if (l1 && l2) { 28 | if(l1->val < l2->val){ 29 | l1->next = mergeTwoLists(l1->next, l2); 30 | return l1; 31 | } 32 | else { 33 | l2->next = mergeTwoLists(l1, l2->next); 34 | return l2; 35 | } 36 | } 37 | return l1 ? l1 : l2; 38 | } 39 | }; -------------------------------------------------------------------------------- /dp/regular-expression-matching/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @param {string} p 4 | * @return {boolean} 5 | */ 6 | var isMatch = function(s, p) { 7 | const dp = new Array(s.length + 1); 8 | for (let i = 0; i <= s.length; ++i) { 9 | dp[i] = (new Array(p.length + 1)).fill(false) 10 | } 11 | 12 | // base case 13 | dp[0][0] = true; 14 | for (let i = 0; i < p.length; ++i) { 15 | if (p[i] === '*') { 16 | dp[0][i+1] = dp[0][i-1]; 17 | } 18 | } 19 | 20 | for (let i = 0; i < s.length; ++i) { 21 | for (let j = 0; j < p.length; ++j) { 22 | if (p[j] === s[i] || p[j] === '.') { 23 | dp[i+1][j+1] = dp[i][j]; 24 | } 25 | 26 | if (p[j] === '*') { 27 | if (p[j-1] !== s[i] && p[j-1] !== '.') { 28 | // 0 occurrence 29 | dp[i+1][j+1] = dp[i+1][j-1]; 30 | } else { 31 | // 1 occurrence dp[i+1][j] 32 | // n occurrence dp[i][j-1] 33 | dp[i+1][j+1] = (dp[i][j+1] || dp[i+1][j-1] || dp[i+1][j]); 34 | } 35 | } 36 | } 37 | } 38 | 39 | return !!dp[s.length][p.length]; 40 | }; -------------------------------------------------------------------------------- /LinkedList/ReverseLinkedList/ReverseLinkedList.cpp: -------------------------------------------------------------------------------- 1 | /// 迭代 2 | class Solution { 3 | public: 4 | ListNode* reverseList(ListNode *head) { 5 | ListNode *prev = nullptr; 6 | ListNode *back; 7 | while(head) { 8 | back = head->next; 9 | head->next = prev; 10 | prev = head; 11 | head = back; 12 | } 13 | return prev; 14 | } 15 | }; 16 | 17 | 18 | /// 递归一: 19 | class Solution { 20 | public: 21 | ListNode* _reverseList(ListNode *head, ListNode *prev = nullptr){ 22 | if (head == nullptr) { return prev; } 23 | ListNode *back = head->next; 24 | head->next = prev; 25 | return _reverseList(back, head); 26 | } 27 | 28 | ListNode* reverseList(ListNode* head) { 29 | return _reverseList(head); 30 | } 31 | }; 32 | 33 | 34 | /// 递归二: 35 | class Solution { 36 | public: 37 | ListNode* reverseList(ListNode *head) { 38 | if(head == nullptr || head->next == nullptr) { return head; } 39 | ListNode *new_head = reverseList(head->next); 40 | head->next->next = head; 41 | head->next = nullptr; 42 | return new_head; 43 | } 44 | }; 45 | -------------------------------------------------------------------------------- /Queue/05.SlidingWindowMaximum/README.md: -------------------------------------------------------------------------------- 1 | # Sliding Window Maximum(滑动窗口最大值) 2 | 3 | **LeetCode 239** 4 | 5 | - [英文版](https://leetcode.com/problems/sliding-window-maximum/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/sliding-window-maximum/) 8 | 9 | ## 题目 10 | 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口 k 内的数字。滑动窗口每次只向右移动一位。 11 | 12 | 返回滑动窗口最大值。 13 | 14 | 示例: 15 | ``` 16 | 输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3 17 | 输出: [3,3,5,5,6,7] 18 | 解释: 19 | 20 | 滑动窗口的位置 最大值 21 | --------------- ----- 22 | [1 3 -1] -3 5 3 6 7 3 23 | 1 [3 -1 -3] 5 3 6 7 3 24 | 1 3 [-1 -3 5] 3 6 7 5 25 | 1 3 -1 [-3 5 3] 6 7 5 26 | 1 3 -1 -3 [5 3 6] 7 6 27 | 1 3 -1 -3 5 [3 6 7] 7 28 | ``` 29 | 注意: 30 | 31 | 你可以假设 k 总是有效的,1 ≤ k ≤ 输入数组的大小,且输入数组不为空。 32 | 33 | 进阶: 34 | 35 | 你能在线性时间复杂度内解决此题吗? 36 | ## 思路 37 |
38 | 点击展开 39 | // TODO 40 |
41 | 42 | ## 代码实现 43 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 44 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 45 | | 🤔 | [😀](./SlidingWindowMaximum.cpp) | 🤔 | 🤔 | 🤔 | 🤔 | [😀](./SlidingWindowMaximum.js) | 🤔 | 🤔 | 46 | 47 | -------------------------------------------------------------------------------- /Array/ThreeSum/ThreeSum.cpp: -------------------------------------------------------------------------------- 1 | 2 | class Solution { 3 | public: 4 | vector> threeSum(vector& nums) { 5 | vector> res; 6 | if(nums.size() < 3) { return res; } 7 | sort(nums.begin(), nums.end()); 8 | for(int i=0; i 0) { break; } 10 | if(i>0 && nums[i] == nums[i-1]) { continue; } 11 | int l = i + 1, r = nums.size() - 1; 12 | while(l < r) { 13 | int sum = nums[i] + nums[l] + nums[r]; 14 | if(sum == 0) { 15 | res.push_back({nums[i], nums[l], nums[r]}); 16 | while(l < r && nums[l] == nums[l+1]) { l++; } 17 | while(l < r && nums[r] == nums[r-1]) { r--; } 18 | l++; 19 | r--; 20 | } 21 | else if(sum < 0) { 22 | while(l < r && nums[l] == nums[l+1]) { l++; } 23 | l++; 24 | } 25 | else { 26 | while(l < r && nums[r] == nums[r-1]) { r--; } 27 | r--; 28 | } 29 | } 30 | } 31 | return res; 32 | } 33 | }; -------------------------------------------------------------------------------- /Array/ThreeSum/ThreeSum.py: -------------------------------------------------------------------------------- 1 | # O(n * n) 2 | class Solution(object): 3 | def threeSum(self, nums): 4 | """ 5 | :type nums: List[int] 6 | :rtype: List[List[int]] 7 | """ 8 | res = [] 9 | nums.sort() # 排序 10 | for i in xrange(0, len(nums) - 2): 11 | # 如果与前一个值相同,则跳过 12 | # 避免重复计算 13 | if i > 0 and nums[i] == nums[i-1]: 14 | continue 15 | l, r = i + 1, len(nums) - 1 16 | while l < r: 17 | s = nums[i] + nums[l] + nums[r] 18 | if s < 0: 19 | # 和过小,增大 nums[l] 20 | l += 1 21 | elif s > 0: 22 | # 值过大,减小 nums[r] 23 | r -= 1 24 | else: 25 | # 存储目标结果 26 | res.append((nums[i], nums[l], nums[r])) 27 | # 避免 l,r 重复计算 28 | while l < r and nums[l] == nums[l + 1]: 29 | l += 1 30 | while l < r and nums[r] == nums[r - 1]: 31 | r -= 1 32 | # 下一组目标值 33 | l += 1 34 | r -= 1 35 | return res 36 | -------------------------------------------------------------------------------- /Queue/05.SlidingWindowMaximum/SlidingWindowMaximum.js: -------------------------------------------------------------------------------- 1 | /** O(n) 在元素大小分布均匀的情况下,这种解法可以认为复杂度是 O(n) 的 2 | * @param {number[]} nums 3 | * @param {number} k 4 | * @return {number[]} 5 | */ 6 | var maxSlidingWindow = function(nums, k) { 7 | if (!nums || !nums.length) return []; 8 | if (k === 0) return nums; 9 | 10 | // 按照元素的从大到小保存元素在 nums 中下标 11 | // 如果新进来的元素比已有的元素大,需要先移除已有的元素 12 | // window 中元素的个数在 1~k 13 | let window = []; 14 | 15 | // 保存结果 16 | let res = []; 17 | 18 | for (let i = 0; i < nums.length; ++i) { 19 | // 如果最大值已经失效,将其移除 20 | // i > k 时最大值有可能已经出窗口了 21 | // 如果 window 中第一个元素的下标 + k <= i 22 | // 说明这个下标已经滑过窗口,不能再参与最大值比较了 23 | if (i >= k && window[0] <= i - k) { 24 | window.shift(); 25 | } 26 | 27 | // 新元素与 window 中的最后一个(最小)元素对比 28 | // 如果比 window 中下标对应的元素大,就将 window 中的元素从后往前逐个移除 29 | while (window.length > 0 && nums[window.slice(-1)[0]] <= nums[i]) { 30 | window.pop(); 31 | } 32 | 33 | // 添加新元素的下标 34 | window.push(i); 35 | 36 | // 从 i >= k - 1 开始每次迭代保存一个最大值 37 | // 第一个元素就是是最大值 38 | if (i >= k - 1) { 39 | res.push(nums[window[0]]); 40 | } 41 | } 42 | 43 | return res; 44 | }; 45 | -------------------------------------------------------------------------------- /LinkedList/LinkedListCycle2/README.md: -------------------------------------------------------------------------------- 1 | # Linked List Cycle II(环形链表 II) 2 | 3 | **LeetCode 142** 4 | 5 | - [英文版](https://leetcode.com/problems/linked-list-cycle-ii/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/linked-list-cycle-ii/) 8 | 9 | ## 题目 10 | 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。 11 | 12 | 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。 13 | 14 | 说明:不允许修改给定的链表。 15 | 16 | 示例 1: 17 | ``` 18 | 输入:head = [3,2,0,-4], pos = 1 19 | 输出:tail connects to node index 1 20 | 解释:链表中有一个环,其尾部连接到第二个节点。 21 | ``` 22 | 示例 2: 23 | ``` 24 | 输入:head = [1,2], pos = 0 25 | 输出:tail connects to node index 0 26 | 解释:链表中有一个环,其尾部连接到第一个节点。 27 | ``` 28 | 29 | 示例 3: 30 | ``` 31 | 输入:head = [1], pos = -1 32 | 输出:no cycle 33 | 解释:链表中没有环。 34 | ``` 35 | 36 | 进阶: 37 | 你是否可以不用额外空间解决此题? 38 | 39 | ## 思路 40 |
41 | 点击展开 42 | 快慢指针找到相遇点;快指针指回链表头部,慢指针指向相遇点,每次将它们向前移动一步,直到再次相遇,相遇点就是环的入口。 43 | 44 | 说明: 45 | 46 | 设链表头部到环的入口长度为`a`,环的长度为`b`,环的入口到相遇点的长度为`c`:则`f=2s=s+nb`,`s=nb=a+c+(n-1)b`,`b=a+c`,即慢指针从相遇点继续前进`a`步就是环的入口。 47 |
48 | 49 | ## 代码实现 50 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 51 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 52 | | 🤔 | [😀](./LinkedListCycle2.cpp) | 🤔 | 🤔 | 🤔 | [😀](./LinkedListCycle2.py) | 🤔 | 🤔 | 🤔 | 53 | -------------------------------------------------------------------------------- /LinkedList/ReverseNodesKGroup/ReverseNodesKGroup.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * struct ListNode { 4 | * int val; 5 | * ListNode *next; 6 | * ListNode(int x) : val(x), next(NULL) {} 7 | * }; 8 | */ 9 | class Solution { 10 | public: 11 | ListNode* _reverseKGroup(ListNode* head) { 12 | ListNode *prev = nullptr, *curr = head, *back; 13 | while (curr) { 14 | back = curr->next; 15 | curr->next = prev; 16 | prev = curr; 17 | curr = back; 18 | } 19 | return prev; 20 | } 21 | 22 | ListNode* reverseKGroup(ListNode* head, int k) { 23 | ListNode *dummy = new ListNode(0); dummy->next = head; 24 | ListNode *end, *begin = head; // 链表首尾 25 | ListNode *back, *prev = dummy; // 前驱后继 26 | while(1){ 27 | end = begin; 28 | for(int i=1; inext; } 29 | if(end == nullptr) { break; } 30 | back = end->next; // 记录后继 31 | // 链表反转 32 | end->next = nullptr; 33 | prev->next = _reverseKGroup(begin); // 连接前面已翻转链表 34 | begin->next = back; // 连接后面未翻转链表 35 | prev = begin; // 更新前驱 36 | begin = back; // 更新链表首 37 | } 38 | return dummy->next; 39 | } 40 | }; -------------------------------------------------------------------------------- /Array/FirstMissingPositive/README.md: -------------------------------------------------------------------------------- 1 | # First Missing Positive(缺失的第一个正数) 2 | 3 | ## LeetCode 41 4 | 5 | - [英文版](https://leetcode.com/problems/first-missing-positive/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/first-missing-positive/) 8 | 9 | ## 题目 10 | 11 | 给定一个未排序的整数数组,找出其中没有出现的最小的正整数。 12 | 13 | 示例 1: 14 | 15 | ```js 16 | 输入: [3,4,-1,1] 17 | 输出: 2 18 | ``` 19 | 20 | 示例 3: 21 | 22 | ```js 23 | 输入: [7,8,9,11,12] 24 | 输出: 1 25 | ``` 26 | 27 | 说明: 28 | 29 | 你的算法的时间复杂度应为O(n),并且只能使用常数级别的空间。 30 | 31 | ## 思路 32 | 33 |
34 | 点击展开 35 | 这道题如果对空间复杂度没有限制,遍历一次数组,将元素作为 key 存入字典;再遍历一次字典,查找从 [1, n) 中缺失的最小 key 即可。 36 | 37 | 然而,题目说只能使用常数空间,说明只能在原地倒腾数组,数组的特性是下标有序,而题目中查找缺失的最小正整数,肯定要按照 [1, n) 的顺序排除查找,它们之间恰好存在差为 1 的关系。 38 | 39 | 因此,我们可以遍历一次数组,如果当前元素的值没有超过数组大小,就交换到 [元素值 - 1] 的下标,交换完成后,再次遍历新数组,[下标 + 1] 应该等于当前的元素值,否者就是缺失的最小正整数。 40 | 41 | 交换后的数组:a[0] = 1, a[1] = 2, a[2] = 3… 42 | 43 | 大致思路已经有了,看上去也并不难,但这是一道 Hard 的题目,还是有坑的。以 [3, 4, -1, 1] 为例,交换到下标 1 后,变为 [-1, 1, 3, 4],此次交换虽然元素 3 交换到了目标位置,然而 1 并没有,元素 1 应该在下标 0 处的,否者第二次遍历检测不到元素 1。 44 | 45 | 因此在交换成功后,不能立即交换下一个元素,而是要再次交换当前元素,直到当前元素不满足交换条件为止。 46 |
47 | 48 | ## 代码实现 49 | 50 | | C++ | Java | Python | JavaScript | Go | PHP | 51 | | :--: | :--: | :--: | :--: | :--: | :--: | 52 | | [😀](FirstMissingPositive.cpp) | 🤔 | [😀](FirstMissingPositive.py) | [😀](./index) | 🤔 | 🤔 | 53 | -------------------------------------------------------------------------------- /LinkedList/MergeSortedLists/MergeSortedLists.php: -------------------------------------------------------------------------------- 1 | val = $val; } 9 | * } 10 | */ 11 | class Solution 12 | { 13 | 14 | /** 15 | * @param ListNode $l1 16 | * @param ListNode $l2 17 | * @return ListNode 18 | */ 19 | function mergeTwoLists($l1, $l2) 20 | { 21 | $pc = $newList = new ListNode(null); 22 | while ($l1 && $l2) { 23 | if ($l1->val <= $l2->val) { 24 | $newList->next = $l1; 25 | $newList = $newList->next; 26 | $l1 = $l1->next; 27 | } else { 28 | $newList->next = $l2; 29 | $newList = $newList->next; 30 | $l2 = $l2->next; 31 | } 32 | 33 | } 34 | $newList->next = $l1 ?? $l2; 35 | return $pc->next; 36 | } 37 | 38 | //递归 39 | function mergeTwoListsForRecursion($l1, $l2) 40 | { 41 | if (!$l1) return $l2; 42 | if (!$l2) return $l1; 43 | 44 | if ($l1->val <= $l2->val) { 45 | $l1->next = $this->mergeTwoLists($l1->next, $l2); 46 | return $l1; 47 | } else { 48 | $l2->next = $this->mergeTwoLists($l2->next, $l1); 49 | return $l2; 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /Stack/05.EvaluateReversePolishNotation/README.md: -------------------------------------------------------------------------------- 1 | # Evaluate Reverse Polish Notatio(逆波兰表达式求值) 2 | 3 | **LeetCode 150** 4 | 5 | - [英文版](https://leetcode.com/problems/evaluate-reverse-polish-notation/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/evaluate-reverse-polish-notation/) 8 | 9 | ## 题目 10 | 根据[逆波兰表示法](https://baike.baidu.com/item/%E9%80%86%E6%B3%A2%E5%85%B0%E5%BC%8F/128437),求表达式的值。 11 | 12 | 有效的运算符包括 `+, -, *, / `。每个运算对象可以是整数,也可以是另一个逆波兰表达式。 13 | 14 | 说明: 15 | 16 | 整数除法只保留整数部分。 17 | 给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。 18 | 示例 1: 19 | ``` 20 | 输入: ["2", "1", "+", "3", "*"] 21 | 输出: 9 22 | 解释: ((2 + 1) * 3) = 9 23 | ``` 24 | 示例 2: 25 | ``` 26 | 输入: ["4", "13", "5", "/", "+"] 27 | 输出: 6 28 | 解释: (4 + (13 / 5)) = 6 29 | 示例 3: 30 | 31 | 输入: ["10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"] 32 | 输出: 22 33 | 解释: 34 | ((10 * (6 / ((9 + 3) * -11))) + 17) + 5 35 | = ((10 * (6 / (12 * -11))) + 17) + 5 36 | = ((10 * (6 / -132)) + 17) + 5 37 | = ((10 * 0) + 17) + 5 38 | = (0 + 17) + 5 39 | = 17 + 5 40 | = 22 41 | ``` 42 | ## 思路 43 |
44 | 点击展开 45 | // TODO 46 |
47 | 48 | ## 代码实现 49 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 50 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 51 | | 🤔 | [😀](./evaluateReversePolishNotation.cpp) | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | [😀](./evaluate_reverse_polish_notation.go) | 🤔 | 52 | 53 | -------------------------------------------------------------------------------- /Stack/05.EvaluateReversePolishNotation/evaluateReversePolishNotation.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int evalRPN(vector& tokens) { 4 | stack myStack; 5 | for(auto str : tokens) { 6 | if(str != "+" && str != "-" && str != "*" && str != "/") { 7 | myStack.push(stoi(str)); 8 | } 9 | else { 10 | int second = myStack.top(); myStack.pop(); 11 | int first = myStack.top(); myStack.pop(); 12 | int result; 13 | switch (str[0]) { 14 | case '+':{ 15 | result = first + second; 16 | break; 17 | } 18 | case '-':{ 19 | result = first - second; 20 | break; 21 | } 22 | case '*':{ 23 | result = first * second; 24 | break; 25 | } 26 | case '/':{ 27 | result = first / second; 28 | break; 29 | } 30 | default:{ 31 | result = 0; 32 | break; 33 | } 34 | } 35 | myStack.push(result); 36 | } 37 | } 38 | return myStack.size() == 1 ? myStack.top() : 0; 39 | } 40 | }; -------------------------------------------------------------------------------- /BackTracking/03.RegularExpressingMatching/README.md: -------------------------------------------------------------------------------- 1 | # Regular Expression Matching(正则表达式匹配) 2 | 3 | **LeetCode 10** 4 | 5 | - [英文版](https://leetcode.com/problems/regular-expression-matching/) 6 | 7 | - [中文版](https://leetcode-cn.com/problems/regular-expression-matching/) 8 | 9 | ## 题目 10 | 给定一个字符串 (s) 和一个字符模式 (p)。实现支持 `'.'` 和 `'*'` 的正则表达式匹配。 11 | ``` 12 | - '.' 匹配任意单个字符。 13 | - '*' 匹配零个或多个前面的元素。 14 | ``` 15 | 16 | 匹配应该覆盖整个字符串 (s) ,而不是部分字符串。 17 | 18 | 说明: 19 | 20 | s 可能为空,且只包含从 a-z 的小写字母。 21 | p 可能为空,且只包含从 a-z 的小写字母,以及字符 `.` 和 `*`。 22 | 23 | 示例 1: 24 | 25 | ``` 26 | 输入: 27 | s = "aa" 28 | p = "a" 29 | 输出: false 30 | 解释: "a" 无法匹配 "aa" 整个字符串。 31 | ``` 32 | 33 | 示例 2: 34 | ``` 35 | 输入: 36 | s = "aa" 37 | p = "a*" 38 | 输出: true 39 | 解释: `'*'` 代表可匹配零个或多个前面的元素, 即可以匹配 'a' 。因此, 重复 'a' 一次, 字符串可变为 "aa"。 40 | ``` 41 | 42 | 示例 3: 43 | ``` 44 | 输入: 45 | s = "ab" 46 | p = ".*" 47 | 输出: true 48 | 解释: ".*" 表示可匹配零个或多个('*')任意字符('.')。 49 | ``` 50 | 51 | 示例 4: 52 | ``` 53 | 输入: 54 | s = "aab" 55 | p = "c*a*b" 56 | 输出: true 57 | 解释: 'c' 可以不被重复, 'a' 可以被重复一次。因此可以匹配字符串 "aab"。 58 | ``` 59 | 60 | 示例 5: 61 | ``` 62 | 输入: 63 | s = "mississippi" 64 | p = "mis*is*p*." 65 | 输出: false 66 | ``` 67 | 68 | ## 思路 69 |
70 | 点击展开 71 | // TODO 72 |
73 | 74 | ## 代码实现 75 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 76 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 77 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 78 | 79 | -------------------------------------------------------------------------------- /BackTracking/01.N-Queens/N-Queens.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def solveNQueens(self, n): 3 | self.res = [] 4 | nQueens = ['.' * n for b in range(n)] 5 | self.dfs(nQueens, 0, n) 6 | return self.res 7 | 8 | def dfs(self, nQueens, row, n): 9 | if (row == n): 10 | self.res.append(list(nQueens)) 11 | return; 12 | for col in range(n): 13 | if self.isValid(nQueens, row, col, n): 14 | # 放 Q 15 | strList = list(nQueens[row]) # 先将字符串转为 list,再修改 16 | strList[col] = 'Q' 17 | nQueens[row] = ''.join(strList) 18 | self.dfs(nQueens, row+1, n) 19 | # 结束后,恢复 . 20 | strList[col] = '.' 21 | nQueens[row] = ''.join(strList) 22 | 23 | def isValid(self, nQueens, row, col, n): 24 | leftup = col - 1; 25 | rightup = col + 1 26 | for i in range(row-1, -1, -1): # row-1 to 0 27 | if (nQueens[i][col] == 'Q'): 28 | return False 29 | if (leftup >= 0): 30 | if (nQueens[i][leftup] == 'Q'): 31 | return False 32 | if (rightup < n): 33 | if (nQueens[i][rightup] == 'Q'): 34 | return False 35 | leftup -= 1 36 | rightup += 1 37 | 38 | return True 39 | 40 | s = Solution() 41 | r = s.solveNQueens(4) 42 | print('result', r) 43 | 44 | -------------------------------------------------------------------------------- /Queue/03.QueueUsingStacks/QueueUsingStacks.php: -------------------------------------------------------------------------------- 1 | stock)) { 25 | array_unshift($this->temp, array_shift($this->stock)); 26 | } 27 | array_unshift($this->stock, $x); 28 | 29 | while (!empty($this->temp)) { 30 | array_unshift($this->stock, array_shift($this->temp)); 31 | } 32 | 33 | } 34 | 35 | /** 36 | * Removes the element from in front of queue and returns that element. 37 | * @return Integer 38 | */ 39 | function pop() 40 | { 41 | return array_shift($this->stock); 42 | } 43 | 44 | /** 45 | * Get the front element. 46 | * @return Integer 47 | */ 48 | function peek() 49 | { 50 | return current($this->stock); 51 | } 52 | 53 | /** 54 | * Returns whether the queue is empty. 55 | * @return Boolean 56 | */ 57 | function empty() 58 | { 59 | return empty($this->stock); 60 | } 61 | } 62 | 63 | /** 64 | * Your MyQueue object will be instantiated and called as such: 65 | * $obj = MyQueue(); 66 | * $obj->push($x); 67 | * $ret_2 = $obj->pop(); 68 | * $ret_3 = $obj->peek(); 69 | * $ret_4 = $obj->empty(); 70 | */ -------------------------------------------------------------------------------- /String/StringToInteger/README.md: -------------------------------------------------------------------------------- 1 | # String to Integer (atoi)(字符串转换整数 (atoi)) 2 | 3 | **LeetCode 8** 4 | 5 | - [英文版](https://leetcode.com/problems/string-to-integer-atoi/) 6 | - [中文版](https://leetcode-cn.com/problems/string-to-integer-atoi/) 7 | 8 | ## 题目 9 | 请你来实现一个 atoi 函数,使其能将字符串转换成整数。 10 | 11 | 首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。 12 | 13 | 当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。 14 | 15 | 该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。 16 | 17 | 注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。 18 | 19 | 在任何情况下,若函数不能进行有效的转换时,请返回 0。 20 | 21 | 说明: 22 | 23 | 假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,qing返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。 24 | 25 | 示例 1: 26 | ``` 27 | 输入: "42" 28 | 输出: 42 29 | ``` 30 | 31 | 示例 2: 32 | ``` 33 | 输入: " -42" 34 | 输出: -42 35 | 解释: 第一个非空白字符为 '-', 它是一个负号。 36 | 我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。 37 | ``` 38 | 39 | 示例 3: 40 | ``` 41 | 输入: "4193 with words" 42 | 输出: 4193 43 | 解释: 转换截止于数字 '3' ,因为它的下一个字符不为数字。 44 | ``` 45 | 46 | 示例 4: 47 | ``` 48 | 输入: "words and 987" 49 | 输出: 0 50 | 解释: 第一个非空字符是 'w', 但它不是数字或正、负号。 51 | 因此无法执行有效的转换。 52 | ``` 53 | 示例 5: 54 | ``` 55 | 输入: "-91283472332" 56 | 输出: -2147483648 57 | 解释: 数字 "-91283472332" 超过 32 位有符号整数范围。 58 | 因此返回 INT_MIN (−231) 。 59 | ``` 60 | 61 | ## 思路 62 |
63 | 点击展开 64 | // TODO 65 |
66 | 67 | ## 代码实现 68 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 69 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 70 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 71 | 72 | -------------------------------------------------------------------------------- /Array/FindAllDuplicates/FindAllDuplicates.py: -------------------------------------------------------------------------------- 1 | def findAllDuplicates(numlist): 2 | for index, value in enumerate(numlist): 3 | exist_index = abs(numlist[index]) - 1 4 | if numlist[exist_index] < 0: 5 | yield value 6 | else: 7 | numlist[exist_index] = -numlist[exist_index] 8 | 9 | 10 | if __name__ == "__main__": 11 | print(list(findAllDuplicates([1, 1, 2, 3, 3]))) 12 | -------------------------------------------------------------------------------- /String/longest-palindromic-substring/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=5 lang=javascript 3 | * 4 | * [5] Longest Palindromic Substring 5 | */ 6 | /** 7 | * @param {string} s 8 | * @return {string} 9 | */ 10 | 11 | // Time: O(n^2) 12 | var longestPalindrome = function(s) { 13 | // 检测字符串 s 是否是回文 14 | const isPalindrome = (s) => { 15 | for (let i = 0, len = s.length; i < parseInt(len/2); ++i) { 16 | if (s.charAt(i) === s.charAt(len - i - 1)) { 17 | continue; 18 | } 19 | return false; 20 | } 21 | return true; 22 | } 23 | 24 | let longestPal = ''; 25 | for (let i = 0, len = s.length; i < len; ++i) { 26 | for (let j = i + 1; j <= len; ++j) { 27 | const ts = s.slice(i, j); 28 | if (ts.length > longestPal.length && isPalindrome(ts)) { 29 | longestPal = ts; 30 | } 31 | } 32 | } 33 | 34 | return longestPal; 35 | }; 36 | 37 | // Time: O(n*m) 38 | var longestPalindrome2 = function(s) { 39 | const len = s.length; 40 | let start = maxLen = 0; 41 | 42 | // 最长回文探测 43 | const palindromeDetect = (s, left, right) => { 44 | while (left >= 0 && right < len && s.charAt(left) === s.charAt(right)) { 45 | left--; 46 | right++; 47 | } 48 | if (maxLen < right - left - 1) { 49 | start = left + 1; 50 | maxLen = right - left - 1; 51 | } 52 | } 53 | 54 | for (let i = 0; i <= len - 1; ++i) { 55 | palindromeDetect(s, i, i); // 奇数长度 56 | palindromeDetect(s, i, i+1); // 偶数长度 57 | } 58 | 59 | return s.slice(start, start + maxLen); 60 | } -------------------------------------------------------------------------------- /Queue/03.QueueUsingStacks/implementQueueUsingStacks.hpp: -------------------------------------------------------------------------------- 1 | #ifndef IMPLEMENTQUEUEUSINGSTACKS_HPP 2 | #define IMPLEMENTQUEUEUSINGSTACKS_HPP 3 | 4 | /* 5 | * 232. Implement Queue using Stacks 6 | * https://leetcode.com/problems/implement-queue-using-stacks/ 7 | */ 8 | 9 | #include 10 | 11 | using namespace std; 12 | 13 | class MyQueue { 14 | public: 15 | stack s1; 16 | stack s2; 17 | 18 | /** Initialize your data structure here. */ 19 | MyQueue() { } 20 | 21 | /** Push element x to the back of queue. */ 22 | void push(int x) { 23 | s1.push(x); 24 | } 25 | 26 | /** Removes the element from in front of queue and returns that element. */ 27 | int pop() { 28 | if (s2.empty()) { 29 | while (!s1.empty()) { 30 | s2.push(s1.top()); 31 | s1.pop(); 32 | } 33 | } 34 | int front = s2.top(); 35 | s2.pop(); 36 | return front; 37 | } 38 | 39 | /** Get the front element. */ 40 | int peek() { 41 | if (s2.empty()) { 42 | while (!s1.empty()) { 43 | s2.push(s1.top()); 44 | s1.pop(); 45 | } 46 | } 47 | return s2.top(); 48 | } 49 | 50 | /** Returns whether the queue is empty. */ 51 | bool empty() { 52 | return s1.empty() && s2.empty(); 53 | } 54 | }; 55 | 56 | /** 57 | * Your MyQueue object will be instantiated and called as such: 58 | * MyQueue* obj = new MyQueue(); 59 | * obj->push(x); 60 | * int param_2 = obj->pop(); 61 | * int param_3 = obj->peek(); 62 | * bool param_4 = obj->empty(); 63 | */ 64 | 65 | 66 | #endif //IMPLEMENTQUEUEUSINGSTACKS_HPP 67 | -------------------------------------------------------------------------------- /Array/ThreeSum/ThreeSum.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @note leetcode-三数之和为0 4 | * @apiNote 思路为 先排序, 然后有两个指针 head和end。 要计算的第一个数一定是负数,所以只要后两个数相加等于 5 | * 0-第一个数 即可。 6 | * @since 19-3-18 10:27 by jdk 1.8 7 | */ 8 | public class ThreeSum { 9 | 10 | private static List> threeSum(int[] nums) { 11 | List> result = new ArrayList<>(); 12 | //进行排序 13 | Arrays.sort(nums); 14 | for (int i = 0; i < nums.length; i++) { 15 | if (nums[i] > 0) { 16 | return result; 17 | } 18 | //之前的相等,我选择跳过 19 | if (i > 0 && nums[i] == nums[i - 1]) { 20 | continue; 21 | } 22 | int header = i + 1; 23 | int end = nums.length - 1; 24 | int val = 0 - nums[i]; 25 | while (header < end) { 26 | if (nums[header] + nums[end] == val) { 27 | List list = Arrays.asList(nums[i], nums[header], nums[end]); 28 | result.add(list); 29 | while (header < end && nums[end] == nums[end - 1]) end--; 30 | while (header < end && nums[header] == nums[header + 1]) header++; 31 | end--; 32 | header++; 33 | } else if (nums[header] + nums[end] > val) { 34 | end--; 35 | } else { 36 | header++; 37 | } 38 | } 39 | } 40 | 41 | 42 | return result; 43 | } 44 | 45 | public static void main(String[] args) { 46 | int[] nums = {}; 47 | List> lists = threeSum(nums); 48 | System.out.println(lists); 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Array/ThreeSum/three_sum.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func threeSum(nums []int) [][]int { 6 | if len(nums) < 3 { 7 | return nil 8 | } 9 | //quick sort 10 | quickSort(nums, 0, len(nums)-1) 11 | 12 | var result [][]int 13 | //3 sum -> 2 sum 14 | for i := 0; i < len(nums)-2; i++ { 15 | //avoid duplicate cal 16 | if i > 0 && nums[i] == nums[i-1] { 17 | continue 18 | } 19 | 20 | //find 2 sum 21 | twoSum := 0 - nums[i] 22 | start := i + 1 23 | end := len(nums) - 1 24 | 25 | //head-tail pointers 26 | for start < end { 27 | 28 | //avoid duplicate 29 | if start > i+1 && nums[start] == nums[start-1] { 30 | start++ 31 | continue 32 | } 33 | 34 | if end < len(nums)-1 && nums[end] == nums[end+1] { 35 | end-- 36 | continue 37 | } 38 | 39 | sum := nums[start] + nums[end] 40 | 41 | if sum == twoSum { 42 | result = append(result, []int{nums[i], nums[start], nums[end]}) 43 | start++ 44 | end-- 45 | } else if sum > twoSum { 46 | end-- 47 | } else { 48 | start++ 49 | } 50 | 51 | } 52 | } 53 | 54 | return result 55 | } 56 | 57 | func quickSort(nums []int, start int, end int) { 58 | 59 | if start >= end { 60 | return 61 | } 62 | 63 | q := partion(nums, start, end) 64 | quickSort(nums, start, q-1) 65 | quickSort(nums, q+1, end) 66 | } 67 | 68 | func partion(nums []int, start int, end int) int { 69 | pivot := nums[end] 70 | middle := start 71 | for i := start; i < end; i++ { 72 | if nums[i] < pivot { 73 | nums[i], nums[middle] = nums[middle], nums[i] 74 | middle++ 75 | } 76 | } 77 | 78 | nums[middle], nums[end] = nums[end], nums[middle] 79 | 80 | return middle 81 | } 82 | 83 | func main() { 84 | 85 | fmt.Println(threeSum([]int{-1, 0, 1, 2, -1, -4})) 86 | } 87 | -------------------------------------------------------------------------------- /Stack/05.EvaluateReversePolishNotation/evaluate_reverse_polish_notation.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | import "strconv" 5 | 6 | type Stack struct { 7 | nums []int 8 | } 9 | 10 | func (self *Stack) push(num int) { 11 | self.nums = append(self.nums, num) 12 | } 13 | 14 | func (self *Stack) pop() int { 15 | top := self.nums[len(self.nums)-1] 16 | self.nums = self.nums[:len(self.nums)-1] 17 | return top 18 | } 19 | 20 | func evalRPN(tokens []string) int { 21 | 22 | if len(tokens) == 0 { 23 | panic("no num, no operations") 24 | } 25 | 26 | operations := map[string]bool{ 27 | "+": true, 28 | "-": true, 29 | "*": true, 30 | "/": true, 31 | } 32 | 33 | //handle one num case 34 | if len(tokens) == 1 && operations[tokens[0]] == false { 35 | result, err := strconv.Atoi(tokens[0]) 36 | if err == nil { 37 | return result 38 | } 39 | } 40 | 41 | stack := &Stack{} 42 | result := 0 43 | for _, token := range tokens { 44 | if operations[token] { 45 | result = calculate(token, stack.pop(), stack.pop()) 46 | stack.push(result) 47 | } else { 48 | num, err := strconv.Atoi(token) 49 | if err == nil { 50 | stack.push(num) 51 | } 52 | } 53 | } 54 | 55 | return result 56 | } 57 | 58 | func calculate(operation string, a int, b int) int { 59 | switch operation { 60 | case "+": 61 | return b + a 62 | case "-": 63 | return b - a 64 | case "*": 65 | return b * a 66 | case "/": 67 | return b / a 68 | } 69 | 70 | panic("illegal oprator") 71 | } 72 | 73 | func main() { 74 | fmt.Println(evalRPN([]string{"18"})) 75 | fmt.Println(evalRPN([]string{"2", "1", "+", "3", "*"})) 76 | fmt.Println(evalRPN([]string{"4", "13", "5", "/", "+"})) 77 | fmt.Println(evalRPN([]string{"10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"})) 78 | } 79 | -------------------------------------------------------------------------------- /LinkedList/ReverseNodesKGroup/ReverseNodesKGroup.js: -------------------------------------------------------------------------------- 1 | // 以 k 为一组翻转链表 2 | // https://leetcode.com/problems/reverse-nodes-in-k-group/ 3 | // 4 | /** 5 | * 题解,递归解法 6 | * 1. 尝试将头结点后移动 k 位,如果不足 k 位,直接返回头结点 7 | * 2. 如果存在 k 个结点,用新的头结点,递归 8 | * 3. 得到的结果连接到头 k 的节点的逆序链表后面 9 | * 4. 重新设置头结点,返回 10 | */ 11 | var reverseKGroup = function(head, k) { 12 | let curr = head; 13 | let count = 0; 14 | while (curr && count != k) { 15 | curr = curr.next; 16 | ++count; 17 | } 18 | if (count === k) { 19 | curr = reverseKGroup(curr, k); 20 | 21 | while (count-- > 0) { 22 | let tmp = head.next; 23 | head.next = curr; 24 | curr = head; 25 | head = tmp; 26 | } 27 | head = curr; 28 | } 29 | return head; 30 | }; 31 | 32 | /** 33 | * 迭代解法 34 | * 遍历链表,如果有 k 个,就翻转,然后将翻转后的 group 与已翻转和未翻转的链表合并 35 | */ 36 | 37 | // Runtime: 68 ms, faster than 92.95% of JavaScript online submissions for Reverse Nodes in k-Group. 38 | var reverseKGroup2 = function(head, k) { 39 | // 初始化一个节点用于指向头结点 40 | var dump = jump = new ListNode(0); 41 | dump.next = head; 42 | 43 | // l 前一个 group 的 head 44 | // r 后一个 group 的 head 45 | var l = r = head; 46 | 47 | while (true) { 48 | var count = 0; 49 | // r 移到下一组 group 的头部 50 | while (r && count < k) { 51 | r = r.next; 52 | count++; 53 | } 54 | // 翻转 [l, r) 之间的链表 55 | if (count === k) { 56 | let cur = l, pre = r; 57 | while(count--) { 58 | let tmp = cur.next; 59 | cur.next = pre; 60 | pre = cur; 61 | cur = tmp; 62 | } 63 | // 翻转后 pre 为当前 group 头节点 64 | // jump 为前一个 group 的尾结点或辅助节点 65 | // 将前一个 group 的尾结点指向当前 group 的节点 66 | jump.next = pre; 67 | // jump 指向当前 group 的最后一个节点 68 | jump = l; 69 | // l 指向下一组 group 的头节点 70 | l = r; 71 | } else { 72 | // 因为 dump 等于 jump 的初始 73 | // 而 jump 的初值的 next 指向链表的头部 74 | return dump.next; 75 | } 76 | } 77 | }; 78 | -------------------------------------------------------------------------------- /Graph/02.ValidSudoku/README.md: -------------------------------------------------------------------------------- 1 | # Valid Sudoku(有效的数独) 2 | 3 | **LeetCode 36** 4 | 5 | - [英文版](https://leetcode.com/problems/valid-sudoku/) 6 | 7 | - [中文](https://leetcode-cn.com/problems/valid-sudoku/) 8 | 9 | ## 题目 10 | 11 | 判断一个 9x9 的数独是否有效。只需要根据以下规则,验证已经填入的数字是否有效即可。 12 | 13 | 数字 1-9 在每一行只能出现一次。 14 | 数字 1-9 在每一列只能出现一次。 15 | 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。 16 | 17 | 18 | 上图是一个部分填充的有效的数独。 19 | 20 | 数独部分空格内已填入了数字,空白格用 '.' 表示。 21 | 22 | 示例 1: 23 | ``` 24 | 输入: 25 | [ 26 | ["5","3",".",".","7",".",".",".","."], 27 | ["6",".",".","1","9","5",".",".","."], 28 | [".","9","8",".",".",".",".","6","."], 29 | ["8",".",".",".","6",".",".",".","3"], 30 | ["4",".",".","8",".","3",".",".","1"], 31 | ["7",".",".",".","2",".",".",".","6"], 32 | [".","6",".",".",".",".","2","8","."], 33 | [".",".",".","4","1","9",".",".","5"], 34 | [".",".",".",".","8",".",".","7","9"] 35 | ] 36 | 输出: true 37 | ``` 38 | 示例 2: 39 | ``` 40 | 输入: 41 | [ 42 | ["8","3",".",".","7",".",".",".","."], 43 | ["6",".",".","1","9","5",".",".","."], 44 | [".","9","8",".",".",".",".","6","."], 45 | ["8",".",".",".","6",".",".",".","3"], 46 | ["4",".",".","8",".","3",".",".","1"], 47 | ["7",".",".",".","2",".",".",".","6"], 48 | [".","6",".",".",".",".","2","8","."], 49 | [".",".",".","4","1","9",".",".","5"], 50 | [".",".",".",".","8",".",".","7","9"] 51 | ] 52 | 输出: false 53 | ``` 54 | 解释: 除了第一行的第一个数字从 5 改为 8 以外,空格内其他数字均与 示例1 相同。但由于位于左上角的 3x3 宫内有两个 8 存在, 因此这个数独是无效的。 55 | 56 | 说明: 57 | 58 | - 一个有效的数独(部分已被填充)不一定是可解的。 59 | - 只需要根据以上规则,验证已经填入的数字是否有效即可。 60 | - 给定数独序列只包含数字 1-9 和字符 '.' 。 61 | - 给定数独永远是 9x9 形式的。 62 | 63 | ## 思路 64 |
65 | 点击展开 66 | // TODO 67 |
68 | 69 | ## 代码实现 70 | | C | C++ | Java | Objective-C | Swift | Python | JavaScript | Go | PHP | 71 | | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | 72 | | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 🤔 | 73 | 74 | -------------------------------------------------------------------------------- /LinkedList/MergeKSortedLists/ListNode.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @note: 链表辅助类 3 | * @since 18-10-22 13:58 by jdk 1.8 4 | */ 5 | 6 | public class ListNode { 7 | public Integer val; 8 | public ListNode next; 9 | 10 | public ListNode(Integer val) { 11 | this.val = val; 12 | } 13 | 14 | 15 | public static ListNode buildListNode(int[] input) { 16 | ListNode first = null, last = null, newNode; 17 | if (input.length > 0) { 18 | for (int anInput : input) { 19 | newNode = new ListNode(anInput); 20 | newNode.next = null; 21 | if (first == null) { 22 | first = newNode; 23 | last = newNode; 24 | } else { 25 | last.next = newNode; 26 | last = newNode; 27 | } 28 | } 29 | } 30 | return first; 31 | } 32 | 33 | //给定指定的位置,然后创建一个环形链表。由尾部连接 34 | //1-2-3-4-5 35 | public static ListNode buildCycleNode(ListNode node, int n) { 36 | //空链表校验 37 | if (node == null) { 38 | return null; 39 | } 40 | //n 代表位置 41 | //如果是末尾的位置的话,那就不能自己相交 42 | ListNode head = new ListNode(0); 43 | head.next= node; 44 | ListNode currentNode = node; 45 | int findCount = 0; 46 | //找到尾部 47 | while (currentNode.next != null) { 48 | currentNode = currentNode.next; 49 | } 50 | //寻找指定n位置的节点 51 | //1-2-3-4-5 52 | while (findCount < n && head!=null) { 53 | ++findCount; 54 | head = head.next; 55 | if (findCount == n) { 56 | currentNode.next = head; 57 | break; 58 | } 59 | } 60 | return node; 61 | } 62 | 63 | 64 | public static void main(String[] args) { 65 | int[] a = {1, 2, 3, 4}; 66 | ListNode listNode = buildListNode(a); 67 | ListNode listNode1 = buildCycleNode(listNode, 0); 68 | System.out.println(listNode1); 69 | } 70 | } -------------------------------------------------------------------------------- /LinkedList/MergeKSortedLists/MergeKSortedLists.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @note 合并K个有序链表,相关辅助类在ListNode中给出 4 | * @apiNote 这个我需要采用merge算法,一次合并两个(归并排序思想) 5 | * @since 19-3-18 15:50 by jdk 1.8 6 | */ 7 | public class MergeKSortedLists { 8 | 9 | public ListNode mergeKLists(ListNode[] lists) { 10 | return mergeList(lists,0,lists.length-1); 11 | } 12 | 13 | public ListNode mergeList(ListNode[] listNodes, int begin, int end) { 14 | if (begin > end) { 15 | return null; 16 | } 17 | if (begin == end) 18 | return listNodes[begin]; 19 | int mid = (begin +end)>> 1; 20 | ListNode listNode1 = mergeList(listNodes, begin, mid); 21 | ListNode listNode2 = mergeList(listNodes, mid + 1, end); 22 | ListNode merges = merge(listNode1, listNode2); 23 | return merges; 24 | } 25 | 26 | private ListNode merge(ListNode a, ListNode b) { 27 | ListNode listNode = new ListNode(0); 28 | ListNode currentNode= listNode; 29 | //接下来要砍头的 30 | while (true) { 31 | if (a == null && b == null) { 32 | break; 33 | } else if (a != null && (b == null || a.val <= b.val)) { 34 | currentNode.next = a; 35 | a = a.next; 36 | } else if (a == null || b.val < a.val) { 37 | currentNode.next = b; 38 | b = b.next; 39 | } 40 | currentNode = currentNode.next; 41 | } 42 | return listNode.next; 43 | } 44 | 45 | 46 | public static void main(String[] args) { 47 | ListNode[] nodes = new ListNode[3]; 48 | ListNode listNode1 = ListNode.buildListNode(new int[]{1, 1, 3, 4}); 49 | ListNode listNode2 = ListNode.buildListNode(new int[]{1, 2, 2, 3}); 50 | ListNode listNode3 = ListNode.buildListNode(new int[]{1, 3, 5, 6}); 51 | nodes[0] = listNode1; 52 | nodes[1] = listNode2; 53 | nodes[2] = listNode3; 54 | ListNode listNode = new Solution5().mergeList(nodes, 0, 2); 55 | System.out.println(listNode); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Queue/04.CircularDeque/CircularDeque.hpp: -------------------------------------------------------------------------------- 1 | class MyCircularDeque { 2 | public: 3 | vector _vec; 4 | int _head; 5 | int _tail; 6 | int _size; 7 | 8 | public: 9 | /** Initialize your data structure here. Set the size of the deque to be k. */ 10 | MyCircularDeque(int k) { 11 | _size = k + 1; // tail不存数据,循环队列会浪费一个数组的存储空间 12 | _vec.resize(_size, 0); 13 | _head = _tail = 0; 14 | } 15 | 16 | /** Adds an item at the front of Deque. Return true if the operation is successful. */ 17 | bool insertFront(int value) { 18 | if (isFull()) { return false; } 19 | _head = (_head - 1 + _size) % _size; 20 | _vec[_head] = value; 21 | return true; 22 | } 23 | 24 | /** Adds an item at the rear of Deque. Return true if the operation is successful. */ 25 | bool insertLast(int value) { 26 | if (isFull()) { return false; } 27 | _vec[_tail] = value; 28 | _tail = (_tail + 1) % _size; 29 | return true; 30 | } 31 | 32 | /** Deletes an item from the front of Deque. Return true if the operation is successful. */ 33 | bool deleteFront() { 34 | if (isEmpty()) { return false; } 35 | _head = (_head + 1) % _size; 36 | return true; 37 | } 38 | 39 | /** Deletes an item from the rear of Deque. Return true if the operation is successful. */ 40 | bool deleteLast() { 41 | if (isEmpty()) { return false; } 42 | _tail = (_tail - 1 + _size) % _size; 43 | return true; 44 | } 45 | 46 | /** Get the front item from the deque. */ 47 | int getFront() { 48 | if (isEmpty()) { return -1; } 49 | return _vec[_head]; 50 | } 51 | 52 | /** Get the last item from the deque. */ 53 | int getRear() { 54 | if (isEmpty()) { return -1; } 55 | return _vec[(_tail - 1 + _size) % _size]; 56 | } 57 | 58 | /** Checks whether the circular deque is empty or not. */ 59 | bool isEmpty() { 60 | return _head == _tail; 61 | } 62 | 63 | /** Checks whether the circular deque is full or not. */ 64 | bool isFull() { 65 | return (_tail + 1) % _size == _head; 66 | } 67 | }; -------------------------------------------------------------------------------- /LinkedList/MergeKSortedLists/MergeKSortedLists.php: -------------------------------------------------------------------------------- 1 | val = $val; } 9 | * } 10 | */ 11 | class Solution 12 | { 13 | 14 | /** 15 | * @param ListNode[] $lists 16 | * @return ListNode 17 | *暴力破解法 18 | * 取出所有的数 排序 重新生成一个新的链表e 19 | */ 20 | function mergeKLists($lists) 21 | { 22 | $res = []; 23 | for ($i = 0; $i < count($lists); $i++) { 24 | $node = $lists[$i]; 25 | while ($node) { 26 | $res[] = $node->val; 27 | $node = $node->next; 28 | } 29 | } 30 | // sort($res); 不使用php内置函数排序 31 | $res = $this->merge_sort($res); 32 | $result = $newList = new listNode(-1); 33 | 34 | foreach ($res as $item) { 35 | $newList->next = new listNode($item); 36 | $newList = $newList->next; 37 | 38 | } 39 | return $result->next; 40 | } 41 | 42 | function merge_sort($nums) 43 | { 44 | if (count($nums) <= 1) { 45 | return $nums; 46 | } 47 | $this->merge_sort_c($nums, 0, count($nums) - 1); 48 | return $nums; 49 | } 50 | 51 | function merge_sort_c(&$nums, $p, $r) 52 | { 53 | if ($p >= $r) { 54 | return; 55 | } 56 | $middle = $p + (($r - $p) >> 1); 57 | $this->merge_sort_c($nums, $p, $middle); 58 | $this->merge_sort_c($nums, $middle + 1, $r); 59 | $this->merge($nums, ['start' => $p, 'end' => $middle], ['start' => $middle + 1, 'end' => $r]); 60 | } 61 | 62 | function merge(&$nums, $array_p, $array_r) 63 | { 64 | $temp = []; 65 | $p = $array_p['start']; 66 | $r = $array_r['start']; 67 | $k = 0; 68 | while ($p <= $array_p['end'] && $r <= $array_r['end']) { 69 | if ($nums[$p] < $nums[$r]) { 70 | $temp[$k++] = $nums[$p++]; 71 | } else { 72 | $temp[$k++] = $nums[$r++]; 73 | } 74 | } 75 | while ($p <= $array_p['end']) { 76 | $temp[$k++] = $nums[$p++]; 77 | } 78 | while ($r <= $array_r['end']) { 79 | $temp[$k++] = $nums[$r++]; 80 | } 81 | 82 | for ($i = 0; $i < $k; $i++) { 83 | $nums[$i + $array_p['start']] = $temp[$i]; 84 | } 85 | 86 | } 87 | 88 | 89 | } -------------------------------------------------------------------------------- /LinkedList/MergeKSortedLists/MergeKSortedLists.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 递归 3 | * Runtime: 324 ms 4 | * Memory Usage: 43.1 MB 5 | */ 6 | class Solution { 7 | public: 8 | ListNode* mergeKLists(vector& lists) { 9 | lists.erase(remove(lists.begin(), lists.end(), nullptr), lists.end()); 10 | if(lists.empty()) { return nullptr; } 11 | auto min_iter = min_element(lists.begin(), lists.end(), [](ListNode *p1, ListNode *p2){ return p1->val < p2->val; }); 12 | ListNode *minNode = *min_iter; 13 | *min_iter = (*min_iter)->next; 14 | if(*min_iter == nullptr) { lists.erase(min_iter); } 15 | minNode->next = mergeKLists(lists); 16 | return minNode; 17 | } 18 | }; 19 | 20 | /* 21 | * 分治1(迭代实现归并) 22 | * Runtime: 24 ms 23 | * Memory Usage: 11.1 MB 24 | */ 25 | class Solution { 26 | public: 27 | ListNode* _mergeTwolists(ListNode* l1, ListNode* l2) { 28 | ListNode *dummy = new ListNode(0); 29 | ListNode *newHead = dummy; 30 | while (l1 && l2) { 31 | if(l1->val < l2->val) { 32 | dummy->next = l1; 33 | l1 = l1->next; 34 | } 35 | else { 36 | dummy->next = l2; 37 | l2 = l2->next; 38 | } 39 | dummy = dummy->next; 40 | } 41 | dummy->next = l1 ? l1 : l2; 42 | return newHead->next; 43 | } 44 | 45 | ListNode* mergeKLists(vector& lists) { 46 | if(lists.empty()) { return nullptr; } 47 | int interval = 1; 48 | while(interval < lists.size()) { 49 | for(int i=0; ival < l2->val) { 70 | dummy->next = l1; 71 | l1 = l1->next; 72 | } 73 | else { 74 | dummy->next = l2; 75 | l2 = l2->next; 76 | } 77 | dummy = dummy->next; 78 | } 79 | dummy->next = l1 ? l1 : l2; 80 | return newHead->next; 81 | } 82 | 83 | ListNode* _mergeKLists(vector& lists, int l, int r) { 84 | if (l == r) { return lists[l]; } 85 | int mid = (l+r) / 2; 86 | ListNode *l1 = _mergeKLists(lists, l, mid); 87 | ListNode *l2 = _mergeKLists(lists, mid+1, r); 88 | return _mergeTwolists(l1, l2); 89 | } 90 | 91 | ListNode* mergeKLists(vector& lists) { 92 | if(lists.empty()) { return nullptr; } 93 | return _mergeKLists(lists, 0, lists.size()-1); 94 | } 95 | }; -------------------------------------------------------------------------------- /Queue/04.CircularDeque/CircularDeque.py: -------------------------------------------------------------------------------- 1 | class MyCircularDeque(object): 2 | 3 | def __init__(self, k): 4 | """ 5 | Initialize your data structure here. Set the size of the deque to be k. 6 | :type k: int 7 | """ 8 | self._capacity = k 9 | self._front, self._rear = 0, 0 10 | self._size = 0 11 | self._data = [-1] * k 12 | 13 | def insertFront(self, value): 14 | """ 15 | Adds an item at the front of Deque. Return true if the operation is successful. 16 | :type value: int 17 | :rtype: bool 18 | """ 19 | if self.isFull(): 20 | return False 21 | if self.isEmpty(): 22 | self._data[self._front] = value 23 | else: 24 | self._front = (self._front + 1) % self._capacity 25 | self._data[self._front] = value 26 | self._size += 1 27 | return True 28 | 29 | def insertLast(self, value): 30 | """ 31 | Adds an item at the rear of Deque. Return true if the operation is successful. 32 | :type value: int 33 | :rtype: bool 34 | """ 35 | if self.isFull(): 36 | return False 37 | if self.isEmpty(): 38 | self._data[self._rear] = value 39 | else: 40 | self._rear = (self._rear - 1) % self._capacity 41 | self._data[self._rear] = value 42 | self._size += 1 43 | return True 44 | 45 | def deleteFront(self): 46 | """ 47 | Deletes an item from the front of Deque. Return true if the operation is successful. 48 | :rtype: bool 49 | """ 50 | if self.isEmpty(): 51 | return False 52 | self._data[self._front] = -1 53 | self._front = (self._front - 1) % self._capacity 54 | self._size -= 1 55 | if self.isEmpty(): 56 | self._rear = self._front 57 | return True 58 | 59 | def deleteLast(self): 60 | """ 61 | Deletes an item from the rear of Deque. Return true if the operation is successful. 62 | :rtype: bool 63 | """ 64 | if self.isEmpty(): 65 | return False 66 | self._data[self._rear] = -1 67 | self._rear = (self._rear + 1) % self._capacity 68 | self._size -= 1 69 | if self.isEmpty(): 70 | self._front = self._rear 71 | return True 72 | 73 | def getFront(self): 74 | """ 75 | Get the front item from the deque. 76 | :rtype: int 77 | """ 78 | return self._data[self._front] 79 | 80 | 81 | def getRear(self): 82 | """ 83 | Get the last item from the deque. 84 | :rtype: int 85 | """ 86 | return self._data[self._rear] 87 | 88 | def isEmpty(self): 89 | """ 90 | Checks whether the circular deque is empty or not. 91 | :rtype: bool 92 | """ 93 | return self._size == 0 94 | 95 | def isFull(self): 96 | """ 97 | Checks whether the circular deque is full or not. 98 | :rtype: bool 99 | """ 100 | return self._size == self._capacity 101 | 102 | -------------------------------------------------------------------------------- /Queue/04.CircularDeque/desisn-circular-deque-2.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type MyCircularDeque struct { 6 | nums []int 7 | count int 8 | head int 9 | tail int 10 | } 11 | 12 | /** Initialize your data structure here. Set the size of the deque to be k. */ 13 | func Constructor(k int) MyCircularDeque { 14 | nums := make([]int, k) 15 | return MyCircularDeque{nums: nums} 16 | } 17 | 18 | /** Adds an item at the front of Deque. Return true if the operation is successful. */ 19 | func (this *MyCircularDeque) InsertFront(value int) bool { 20 | if this.IsFull() { 21 | return false 22 | } 23 | 24 | index := this.head - 1 25 | if index < 0 { 26 | index = len(this.nums) - 1 27 | } 28 | this.nums[index] = value 29 | this.head = index 30 | this.count++ 31 | return true 32 | } 33 | 34 | /** Adds an item at the rear of Deque. Return true if the operation is successful. */ 35 | func (this *MyCircularDeque) InsertLast(value int) bool { 36 | if this.IsFull() { 37 | return false 38 | } 39 | 40 | this.nums[this.tail] = value 41 | this.tail = (this.tail + 1) % len(this.nums) 42 | this.count++ 43 | return true 44 | } 45 | 46 | /** Deletes an item from the front of Deque. Return true if the operation is successful. */ 47 | func (this *MyCircularDeque) DeleteFront() bool { 48 | if this.IsEmpty() { 49 | return false 50 | } 51 | 52 | this.head = (this.head + 1) % len(this.nums) 53 | this.count-- 54 | return true 55 | } 56 | 57 | /** Deletes an item from the rear of Deque. Return true if the operation is successful. */ 58 | func (this *MyCircularDeque) DeleteLast() bool { 59 | if this.IsEmpty() { 60 | return false 61 | } 62 | 63 | this.tail = this.tail - 1 64 | if this.tail < 0 { 65 | this.tail = len(this.nums) - 1 66 | } 67 | this.count-- 68 | return true 69 | } 70 | 71 | /** Get the front item from the deque. */ 72 | func (this *MyCircularDeque) GetFront() int { 73 | if this.IsEmpty() { 74 | return -1 75 | } 76 | 77 | return this.nums[this.head] 78 | } 79 | 80 | /** Get the last item from the deque. */ 81 | func (this *MyCircularDeque) GetRear() int { 82 | if this.IsEmpty() { 83 | return -1 84 | } 85 | 86 | index := this.tail - 1 87 | if index < 0 { 88 | index = len(this.nums) - 1 89 | } 90 | return this.nums[index] 91 | } 92 | 93 | /** Checks whether the circular deque is empty or not. */ 94 | func (this *MyCircularDeque) IsEmpty() bool { 95 | return this.count == 0 96 | } 97 | 98 | /** Checks whether the circular deque is full or not. */ 99 | func (this *MyCircularDeque) IsFull() bool { 100 | return this.count == len(this.nums) 101 | } 102 | 103 | /** 104 | * Your MyCircularDeque object will be instantiated and called as such: 105 | * obj := Constructor(k); 106 | * param_1 := obj.InsertFront(value); 107 | * param_2 := obj.InsertLast(value); 108 | * param_3 := obj.DeleteFront(); 109 | * param_4 := obj.DeleteLast(); 110 | * param_5 := obj.GetFront(); 111 | * param_6 := obj.GetRear(); 112 | * param_7 := obj.IsEmpty(); 113 | * param_8 := obj.IsFull(); 114 | */ 115 | func main() { 116 | obj := Constructor(3) 117 | fmt.Println(obj.InsertLast(1)) 118 | fmt.Println(obj.InsertLast(2)) 119 | fmt.Println(obj.InsertFront(3)) 120 | fmt.Println(obj.InsertFront(4)) 121 | fmt.Println(obj.GetRear()) 122 | fmt.Println(obj.IsFull()) 123 | fmt.Println(obj.DeleteLast()) 124 | fmt.Println(obj.InsertFront(4)) 125 | fmt.Println(obj.GetFront()) 126 | 127 | } 128 | -------------------------------------------------------------------------------- /Queue/04.CircularDeque/desisn-circular-deque.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type Node struct { 6 | val int 7 | next *Node 8 | prev *Node 9 | } 10 | 11 | type MyCircularDeque struct { 12 | capacity int 13 | size int 14 | head *Node 15 | tail *Node 16 | } 17 | 18 | /** Initialize your data structure here. Set the size of the deque to be k. */ 19 | func Constructor(k int) MyCircularDeque { 20 | return MyCircularDeque{capacity: k} 21 | } 22 | 23 | /** Adds an item at the front of Deque. Return true if the operation is successful. */ 24 | func (this *MyCircularDeque) InsertFront(value int) bool { 25 | 26 | if this.IsFull() { 27 | return false 28 | } 29 | 30 | if this.head == nil { 31 | this.head = &Node{val: value} 32 | this.tail = this.head 33 | } else { 34 | node := &Node{val: value} 35 | node.next = this.head 36 | this.head.prev = node 37 | this.head = node 38 | } 39 | 40 | this.size++ 41 | 42 | return true 43 | } 44 | 45 | /** Adds an item at the rear of Deque. Return true if the operation is successful. */ 46 | func (this *MyCircularDeque) InsertLast(value int) bool { 47 | if this.IsFull() { 48 | return false 49 | } 50 | 51 | if this.tail == nil { 52 | this.tail = &Node{val: value} 53 | this.head = this.tail 54 | } else { 55 | node := &Node{val: value} 56 | this.tail.next = node 57 | node.prev = this.tail 58 | this.tail = node 59 | } 60 | 61 | this.size++ 62 | 63 | return true 64 | } 65 | 66 | /** Deletes an item from the front of Deque. Return true if the operation is successful. */ 67 | func (this *MyCircularDeque) DeleteFront() bool { 68 | if this.IsEmpty() { 69 | return false 70 | } 71 | 72 | if this.size == 1 { 73 | this.head = nil 74 | this.tail = nil 75 | } else { 76 | this.head.next.prev = nil 77 | this.head = this.head.next 78 | } 79 | 80 | this.size-- 81 | 82 | return true 83 | 84 | } 85 | 86 | /** Deletes an item from the rear of Deque. Return true if the operation is successful. */ 87 | func (this *MyCircularDeque) DeleteLast() bool { 88 | if this.IsEmpty() { 89 | return false 90 | } 91 | 92 | if this.size == 1 { 93 | this.head = nil 94 | this.tail = nil 95 | } else { 96 | this.tail.prev.next = nil 97 | this.tail = this.tail.prev 98 | } 99 | 100 | this.size-- 101 | 102 | return true 103 | } 104 | 105 | /** Get the front item from the deque. */ 106 | func (this *MyCircularDeque) GetFront() int { 107 | if this.IsEmpty() { 108 | return -1 109 | } 110 | 111 | return this.head.val 112 | } 113 | 114 | /** Get the last item from the deque. */ 115 | func (this *MyCircularDeque) GetRear() int { 116 | if this.IsEmpty() { 117 | return -1 118 | } 119 | 120 | return this.tail.val 121 | } 122 | 123 | /** Checks whether the circular deque is empty or not. */ 124 | func (this *MyCircularDeque) IsEmpty() bool { 125 | return this.size == 0 126 | } 127 | 128 | /** Checks whether the circular deque is full or not. */ 129 | func (this *MyCircularDeque) IsFull() bool { 130 | return this.size == this.capacity 131 | } 132 | 133 | /** 134 | * Your MyCircularDeque object will be instantiated and called as such: 135 | * obj := Constructor(k); 136 | * param_1 := obj.InsertFront(value); 137 | * param_2 := obj.InsertLast(value); 138 | * param_3 := obj.DeleteFront(); 139 | * param_4 := obj.DeleteLast(); 140 | * param_5 := obj.GetFront(); 141 | * param_6 := obj.GetRear(); 142 | * param_7 := obj.IsEmpty(); 143 | * param_8 := obj.IsFull(); 144 | */ 145 | 146 | func main() { 147 | obj := Constructor(3) 148 | fmt.Println(obj.InsertLast(1)) 149 | fmt.Println(obj.InsertLast(2)) 150 | fmt.Println(obj.InsertFront(3)) 151 | fmt.Println(obj.InsertFront(4)) 152 | fmt.Println(obj.GetRear()) 153 | fmt.Println(obj.IsFull()) 154 | fmt.Println(obj.DeleteLast()) 155 | fmt.Println(obj.InsertFront(4)) 156 | fmt.Println(obj.GetFront()) 157 | 158 | } 159 | -------------------------------------------------------------------------------- /dp/regular-expression-matching/README.md: -------------------------------------------------------------------------------- 1 | # 正则表达式匹配 2 | 3 | ## 题目 4 | 5 | 给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。 6 | 7 | '.' 匹配任意单个字符 8 | '*' 匹配零个或多个前面的那一个元素 9 | 所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。 10 | 11 | 说明: 12 | 13 | s 可能为空,且只包含从 a-z 的小写字母。 14 | p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *。 15 | 16 | 示例 1: 17 | 18 | ``` 19 | 输入: 20 | s = "aa" 21 | p = "a" 22 | 输出: false 23 | ``` 24 | 25 | 解释: "a" 无法匹配 "aa" 整个字符串。 26 | 27 | 示例 2: 28 | 29 | ``` 30 | 输入: 31 | s = "aa" 32 | p = "a*" 33 | 输出: true 34 | ``` 35 | 36 | 解释: 因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。 37 | 38 | 示例 3: 39 | 40 | ``` 41 | 输入: 42 | s = "ab" 43 | p = ".*" 44 | 输出: true 45 | ``` 46 | 47 | 解释: ".*" 表示可匹配零个或多个('*')任意字符('.')。 48 | 49 | 示例 4: 50 | 51 | ``` 52 | 输入: 53 | s = "aab" 54 | p = "c*a*b" 55 | 输出: true 56 | ``` 57 | 58 | 解释: 因为 '*' 表示零个或多个,这里 'c' 为 0 个, 'a' 被重复一次。因此可以匹配字符串 "aab"。 59 | 示例 5: 60 | 61 | ``` 62 | 输入: 63 | s = "mississippi" 64 | p = "mis*is*p*." 65 | 输出: false 66 | ``` 67 | 68 | ## 思路 69 | 70 | 两个字符串进行比较,容易想到的是采用两层循环对比。但是这两个字符串并不是一对一进行比较的, `*` 字符存在匹配 0 个或者多个字符的情况,因此需要额外的变量保存前面已经遍历过的状态。 71 | 72 | 维护零散的变量并不是简单的事情,我们可以考虑将这些变量使用集合来维护。 73 | 74 | 在遍历过程中,当前的匹配状态依赖于子串的匹配状态的。因此我们可以考虑使用动态规划来做。 75 | 76 | 动态规划的三要素: 77 | 78 | 1. base case 79 | 2. 最优子结构 80 | 3. 状态转移方程 81 | 82 | 我们采用二维数组 dp,来存储子串的匹配状态,横向表示 p 字符,纵向表示 s 字符。 83 | 84 | ![20200130104438.png](https://raw.githubusercontent.com/iostalks/images/master/blog/20200130104438.png) 85 | 86 | ## 1.base case 87 | 88 | base case 是状态转移的初始值,横向初始值是以 s 作为空字符串("")与 p 模式字符进行匹配的结果,纵向初始值是以 s 字符串与空模式串 p 进行匹配的结果。 89 | 90 | 模式串 p 为空字符串时,当且仅当 s 为空字符时才会匹配。 91 | 92 | 当 s 为空字符时,就不仅仅只与空字符串 p 匹配了。它还与 `a*` 、 `a*b*` 、 `a*b*c*` 、... 匹配。 93 | 94 | 因此在遇到 `*` 时,空字符串 s 与 p 的匹配情况需要根据 `*` 向前退两个字符的子串匹配情况决定。 95 | 96 | > 根据题意 `*` 能够与重复它前面一个字符 0 次或者多次的字符匹配,因此 `*` 前面的字符必然不能为空字符。 97 | 98 | 以 `s = ""` 和 `p = "a.b*"` 为例子, 当遇到 `*` 时, `"a.b*"` 回退两位的子串是 `"a."` , `s = ""` 和 `"a."` 不匹配,所以 `s = ""` 与 `a*b*` 也不匹配。 99 | 100 | ![20200130111146.png](https://raw.githubusercontent.com/iostalks/images/master/blog/20200130111146.png) 101 | 102 | 用伪代码表示: 103 | 104 | ``` js 105 | if (p[j] == '*') { 106 | dp[i][j] = dp[i][j - 2]; 107 | } 108 | ``` 109 | 110 | ## 2. 最优子结构 111 | 112 | s 的子串 s[0:i] 和 p 的子串 p[0:j] 的匹配关系,可以根据 p 在下标 j 处的字符内容分为三种子结构: 113 | 114 | 1. p[j] == a-z 115 | 2. p[j] == '.' 116 | 3. p[j] == '*' 117 | 118 | 如果 p[j] 字符为 a-z ,并且 p[j] != s[i] 那么 dp[i][j] 必然是 false。如果 p[j] == s[i] 或者 p[j] = '.' 字符,s[0:i] 和 p[0:j] 的匹配关系由 dp[i][j] 由 dp[i-1][j-1] 决定。 119 | 120 | 如果 p[j] 为 `*` ,要考虑当前 s[i] 字符与 `*` 前一个字符 p[j-1] 发生匹配的次数。分为 0 次、1 次和多次情况来讨论。 121 | 122 | 上述情况都可以由 s[0:i] 和 p[0:j] 子串的三种子结构记录在 dp[i][j] 数组内的状态推导而来。 123 | 124 | ## 3. 状态转移方程 125 | 126 | 1. p[j] == s[i],p[i] 和 s[j] 字符相同,则 s[0:i] 和 p[0:j] 子串的匹配情况由 s[0:i-1] 和 p[0:i-1] 的情况决定; 127 | 2. p[j] == '.', `.` 点符号能够匹配任意的字符,因此 p[0:i] 和 p[0:j] 子串匹配情况由 s[0:i-1] 和 p[0:i-1] 的情况决定; 128 | 3. p[j] == '*', `*` 的处理需分为匹配次数来讨论,我们接下来会讨论; 129 | 4. 其它情况均不匹配。 130 | 131 | ### 星号匹配 0 次 132 | 133 | 如果星号匹配 0 次,则需要忽略星号以及它前面的一个字符,dp[i][j] 的前一个状态由 s[i] 与 p[j-2] 字符串的匹配情况 dp[i][j-2] 推导。 134 | 135 | ![20200130160917.png](https://raw.githubusercontent.com/iostalks/images/master/blog/20200130160917.png) 136 | 137 | ### 星号匹配 1 次 138 | 139 | 模式串 `a.b*` 与 `aab` 中的 `b` 发生一次匹配。它们的匹配关系由 `a.b` 和 `aab` 的匹配关系 dp[i][j-1] 推导而来。 140 | 141 | ![20200130162435.png](https://raw.githubusercontent.com/iostalks/images/master/blog/20200130162435.png) 142 | 143 | ### 星号匹配多次 144 | 145 | 模式串 `a.b*` 与 `aabb` 中的 `b` 发生多次匹配。它们的匹配关系由 `a.b*` 和 `aab` 的匹配关系 dp[i-1][j] 推导而来。 146 | 147 | ![20200130164551.png](https://raw.githubusercontent.com/iostalks/images/master/blog/20200130164551.png) 148 | 149 | 为什么? 150 | 151 | 多次匹配的推导关系有点难以理解,它为什么不是由 dp[i-1][j-1] 推导而来呢?如果由 dp[i-1][j-1] 推导而来,前一个字符可能和当前字符不相同,就不属于重复匹配了。 152 | 153 | 多次匹配的前提是已经发生了一次匹配,即在 `a.b*` 和 `aab` 的基础上的匹配情况,也就是 dp[i-1][j] 的值。 154 | 155 | > 注:图中 dp 数组的维度会比 s 和 p 字符的长度大 1,新增的维度用于存储推导初始值。文中为了方便当前待匹配情况用 dp[i][j] 表示,代码中实际使用的是 dp[i+1][j+1]。 156 | 157 | ## 链接 158 | 159 | [LeetCode](https://leetcode.com/problems/regular-expression-matching/) 160 | 161 | [力扣](https://leetcode-cn.com/problems/regular-expression-matching/) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Image](./banner.png) 2 | 3 | ![Image](https://img.shields.io/badge/language-muti-brightgreen.svg) ![Image](https://img.shields.io/badge/leetcode-50%2B-orange.svg) 4 | 5 | ## [《数据结构与算法之美》](http://t.cn/EvWJWn4)专栏导航 6 | 7 | ### 数据结构 8 | 9 | - 线性表 10 | - [数组](./Array) 11 | - [数组:为什么很多编程语言中数组都从0开始编号?](https://time.geekbang.org/column/article/40961) 12 | - [链表](./LinkedList) 13 | - [链表(上):如何实现LRU缓存淘汰算法?](https://time.geekbang.org/column/article/41013) 14 | - [链表(下):如何轻松写出正确的链表代码?](https://time.geekbang.org/column/article/41149) 15 | - [栈](./Stack) 16 | - [栈:如何实现浏览器的前进和后退功能?](https://time.geekbang.org/column/article/41222) 17 | - [队列](./Queue) 18 | - [队列:队列在线程池等有限资源池中的应用](https://time.geekbang.org/column/article/41330) 19 | - 跳表 20 | - [跳表:为什么Redis一定要用跳表来实现有序集合?](https://time.geekbang.org/column/article/42896) 21 | - 散列表 22 | - [散列表(上):Word文档中的单词拼写检查功能是如何实现的?](64233) 23 | - [散列表(中):如何打造一个工业级水平的散列表?](https://time.geekbang.org/column/article/64586) 24 | - [散列表(下):为什么散列表和链表经常会一起使用?](https://time.geekbang.org/column/article/64858) 25 | - 树 26 | - [二叉树](./BinaryTree) 27 | - [二叉树基础(上):什么样的二叉树适合用数组来存储?](https://time.geekbang.org/column/article/67856) 28 | - [二叉树基础(下):有了如此高效的散列表,为什么还需要二叉树?](https://time.geekbang.org/column/article/68334) 29 | - 平衡二叉树 30 | - 红黑树 31 | - [红黑树(上):为什么工程中都用红黑树这种二叉树?](https://time.geekbang.org/column/article/68638) 32 | - [红黑树(下):掌握这些技巧,你也可以实现一个红黑树](https://time.geekbang.org/column/article/68976) 33 | - 堆 34 | - [堆和堆排序:为什么说堆排序没有快速排序快?](https://time.geekbang.org/column/article/69913) 35 | - [堆的应用:如何快速获取到Top 10最热门的搜索关键词?](https://time.geekbang.org/column/article/70187) 36 | - [图](./Graph) 37 | - 无向图、有向图、带权图 38 | - [图的表示:如何存储微博、微信等社交网络中的好友关系?](https://time.geekbang.org/column/article/70537) 39 | 40 | ### 算法 41 | 42 | - 复杂度分析 43 | - [复杂度分析(上):如何分析算法的执行效率和资源消耗](https://time.geekbang.org/column/article/40036) 44 | - [复杂度分析(下):浅析最好、最坏、平均、均摊时间复杂度](https://time.geekbang.org/column/article/40447) 45 | - [排序](./Sort) 46 | - 冒泡排序、插入排序、选择排序 47 | - [排序(上):为什么插入排序比冒泡排序更受欢迎?](https://time.geekbang.org/column/article/41802) 48 | - 归并排序、快速排序 49 | - [排序(下):如何用快排思想在O(n)内查找第K大元素?](https://time.geekbang.org/column/article/41913) 50 | - 桶排序、计数排序、基数排序 51 | - [线性排序:如何根据年龄给100万用户数据排序?](https://time.geekbang.org/column/article/42038) 52 | - [排序优化:如何实现一个通用的、高性能的排序函数?](https://time.geekbang.org/column/article/42359) 53 | - 递归 54 | - [递归:如何用三行代码找到“最终推荐人”?](https://time.geekbang.org/column/article/41440) 55 | - [递归树:如何借助树来求解递归算法的时间复杂度?](https://time.geekbang.org/column/article/69388) 56 | - [查找](./Search) 57 | - 二分查找 58 | - [二分查找(上):如何用最省内存的方式实现快速查找功能?](https://time.geekbang.org/column/article/42520) 59 | - [二分查找(下):如何快速定位IP对应的省份地址?](https://time.geekbang.org/column/article/42733) 60 | - 广度、深度优先搜索 61 | - [深度和广度优先搜索:如何找出社交网络中的三度好友关系?](https://time.geekbang.org/column/article/70891) 62 | - 哈希算法 63 | - [哈希算法(上):如何防止数据库中的用户信息被脱库?](https://time.geekbang.org/column/article/65312) 64 | - [哈希算法(下):哈希算法在分布式系统中有哪些应用?](https://time.geekbang.org/column/article/67388) 65 | - [字符串](./String) 66 | - BF、RK 算法 67 | - [字符串匹配基础(上):如何借助哈希算法实现高效字符串匹配?](https://time.geekbang.org/column/article/71187) 68 | - BM 算法 69 | - [字符串匹配基础(中):如何实现文本编辑器中的查找功能?](https://time.geekbang.org/column/article/71525) 70 | - KMP 算法 71 | - [字符串匹配基础(下):如何借助BM算法轻松理解KMP算法?](https://time.geekbang.org/column/article/71845) 72 | - Trie 树 73 | - [Trie树:如何实现搜索引擎的搜索关键词提示功能?](https://time.geekbang.org/column/article/72414) 74 | - AC 自动机 75 | - [AC自动机:如何用多模式串匹配实现敏感词过滤功能?](https://time.geekbang.org/column/article/72810) 76 | - 算法思想 77 | - 贪心算法 78 | - [贪心算法:如何用贪心算法实现Huffman压缩编码?](https://time.geekbang.org/column/article/73188) 79 | - [分治算法](./DivideAndConquer) 80 | - [分治算法:谈一谈大规模计算框架MapReduce中的分治思想](https://time.geekbang.org/column/article/73503) 81 | - [回溯算法](./BackTracking) 82 | - [回溯算法:从电影《蝴蝶效应》中学习回溯算法的核心思想](https://time.geekbang.org/column/article/74287) 83 | - [动态规划](./DynamicProgramming) 84 | - [初识动态规划:如何巧妙解决“双十一”购物时的凑单问题?](https://time.geekbang.org/column/article/74788) 85 | - [动态规划理论:一篇文章带你彻底搞懂最优子结构、无后效性和重复子问题](https://time.geekbang.org/column/article/75702) 86 | 87 | ### 高级篇 88 | - [拓扑排序:如何确定代码源文件的编译依赖关系?](https://time.geekbang.org/column/article/76207) 89 | 90 | - [最短路径:地图软件是如何计算出最优出行路径的?](https://time.geekbang.org/column/article/76468) 91 | 92 | - [位图:如何实现网页爬虫中的URL去重功能?](https://time.geekbang.org/column/article/76827) 93 | 94 | - [概率统计:如何利用朴素贝叶斯算法过滤垃圾短信?](https://time.geekbang.org/column/article/77142) 95 | 96 | - [向量空间:如何实现一个简单的音乐推荐系统?](https://time.geekbang.org/column/article/77457) 97 | 98 | - [B+树:MySQL数据库索引是如何实现的?](https://time.geekbang.org/column/article/77830) 99 | 100 | - [搜索:如何用A`*`搜索算法实现游戏中的寻路功能?](https://time.geekbang.org/column/article/78175) 101 | 102 | - [索引:如何在海量数据中快速查找某个数据?](https://time.geekbang.org/column/article/78449) 103 | 104 | - [并行算法:如何利用并行处理提高算法的执行效率?](https://time.geekbang.org/column/article/78795) 105 | 106 | ### 实战篇 107 | - [算法实战(一):剖析Redis常用数据类型对应的数据结构](https://time.geekbang.org/column/article/79159) 108 | 109 | - [算法实战(二):剖析搜索引擎背后的经典数据结构和算法](https://time.geekbang.org/column/article/79433) 110 | 111 | - [算法实战(三):剖析高性能队列Disruptor背后的数据结构和算法](https://time.geekbang.org/column/article/79871) 112 | 113 | - [算法实战(四):剖析微服务接口鉴权限流背后的数据结构和算法](https://time.geekbang.org/column/article/80388) 114 | 115 | - [算法实战(五):如何用学过的数据结构和算法实现一个短网址系统?](https://time.geekbang.org/column/article/80850) 116 | --------------------------------------------------------------------------------