├── .gitignore ├── 02-Binary-Search ├── Type-1 │ ├── 0004-median-of-two-sorted-arrays │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0033-search-in-rotated-sorted-array │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ ├── Solution5.java │ │ │ └── Solution6.java │ ├── 0034-find-first-and-last-position-of-element-in-sorted-array │ │ └── src │ │ │ └── Solution.java │ ├── 0035-search-insert-position │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0069-sqrtx │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── Solution3.java │ ├── 0074-search-a-2d-matrix │ │ └── src │ │ │ └── Solution.java │ ├── 0081-search-in-rotated-sorted-array-ii │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ └── Solution5.java │ ├── 0153-find-minimum-in-rotated-sorted-array │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── Solution3.java │ ├── 0154-find-minimum-in-rotated-sorted-array-ii │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0162-find-peak-element │ │ └── src │ │ │ └── Solution.java │ ├── 0274-h-index │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0275-h-index-ii │ │ └── src │ │ │ └── Solution.java │ ├── 0278-first-bad-version │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ ├── 0374-guess-number-higher-or-lower │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── Solution3.java │ ├── 0378-kth-smallest-element-in-a-sorted-matrix │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ ├── 0410-split-array-largest-sum │ │ └── src │ │ │ └── Solution.java │ ├── 0436-find-right-interval │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0611-valid-triangle-number │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── Solution3.java │ ├── 0658-find-k-closest-elements │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ ├── 0704-binary-search │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── Solution3.java │ ├── 0744-find-smallest-letter-greater-than-target │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0911-online-election │ │ └── src │ │ │ └── TopVotedCandidate.java │ ├── 1095-find-in-mountain-array │ │ └── src │ │ │ └── Solution.java │ ├── 1237-find-positive-integer-solution-for-a-given-equation │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ └── 1292-maximum-side-length-of-a-square-with-sum-less-than-or-equal-to-threshold │ │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── Type-2 │ ├── 0287-find-the-duplicate-number │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ └── 1300-sum-of-mutated-array-closest-to-target │ │ └── src │ │ ├── Solution.java │ │ └── Solution2.java └── Type-3 │ ├── 0852-peak-index-in-a-mountain-array │ └── src │ │ └── Solution.java │ ├── 0875-koko-eating-bananas │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 1011-capacity-to-ship-packages-within-d-days │ └── src │ │ └── Solution.java │ ├── 1482-minimum-number-of-days-to-make-m-bouquets │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 1552-magnetic-force-between-two-balls │ └── src │ │ └── Solution.java │ └── LCP-12-xiao-zhang-shua-ti-ji-hua │ └── src │ └── Solution.java ├── 03-Basic-Sorting ├── BubbleSort │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── Insertion-Sort-Visualization │ ├── README.md │ └── src │ │ ├── AlgoFrame.java │ │ ├── AlgoVisHelper.java │ │ ├── AlgoVisualizer.java │ │ └── InsertSortData.java ├── Insertion-Sort │ └── src │ │ ├── ISortAlgorithm.java │ │ ├── InsertionSort.java │ │ ├── InsertionSort2.java │ │ ├── InsertionSortOptimizer.java │ │ ├── InsertionSortOptimizer2.java │ │ ├── InsertionSortOptimizer3.java │ │ ├── InsertionSortOptimizer4.java │ │ ├── InsertionSortOptimizer5.java │ │ ├── InsertionSortOptimizer6.java │ │ ├── ShellSort1.java │ │ ├── ShellSort2.java │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution的副本.java │ │ └── SortTestHelper.java ├── Selection-Sort-Visualization │ ├── README.md │ └── src │ │ ├── AlgoFrame.java │ │ ├── AlgoVisHelper.java │ │ ├── AlgoVisualizer.java │ │ └── SelectionSortData.java ├── Selection-Sort │ └── src │ │ ├── SelectionSort.java │ │ └── Solution2.java ├── Shell-Sort │ └── src │ │ ├── Solution.java │ │ └── Solution2.java └── Sorting-Algorithms │ └── src │ ├── HelloWorld.java │ └── cn │ └── leetcode │ ├── examples │ ├── GenerateNearlySortedArrayStrategy.java │ ├── GenerateRandomArrayStrategy.java │ ├── GenerateReversedArrayStrategy.java │ └── IGenerateArrayStrategy.java │ ├── sorting │ ├── BubbleSort.java │ ├── BubbleSortOptimize.java │ ├── BucketSort.java │ ├── CountingSort.java │ ├── ISortingAlgorithm.java │ ├── InsertionSort.java │ ├── InsertionSort2.java │ ├── InsertionSortOptimize.java │ ├── InsertionSortOptimize2.java │ ├── InsertionSortOptimize3.java │ ├── MergeSort.java │ ├── MergeSortBottomUp.java │ ├── MergeSortInPlace.java │ ├── MergeSortOptimize.java │ ├── QuickSort.java │ ├── QuickSortOptimizer.java │ ├── QuickSortThreeWays.java │ ├── QuickSortTwoWays.java │ ├── RadixSort.java │ ├── SelectionSort.java │ ├── ShellSort.java │ └── ShellSort2.java │ └── utils │ └── SortingUtil.java ├── 03-Loop-Invariant ├── 0026-remove-duplicates-from-sorted-array │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0027-remove-element │ └── src │ │ └── Solution.java ├── 0080-remove-duplicates-from-sorted-array-ii │ └── src │ │ ├── Solution.java │ │ └── Solution2.java └── 0283-move-zeroes │ └── src │ └── Solution.java ├── 04-Merge-Sort ├── 0051-shu-zu-zhong-de-ni-xu-dui-lcof │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0088-merge-sorted-array │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── Merge-Sort │ └── src │ │ ├── ISortAlgorithm.java │ │ ├── MergeSort.java │ │ ├── MergeSort1.java │ │ ├── MergeSort2.java │ │ ├── MergeSort3.java │ │ ├── MergeSortBU.java │ │ ├── MergeSortDebug.java │ │ ├── MergeSortOptimize.java │ │ └── MergeSortOptimize_1.java └── MergeSort │ └── src │ ├── Solution.java │ ├── Solution2.java │ └── Solution3.java ├── 04-Quick-Sort ├── 0075-sort-colors-2 │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0075-sort-colors │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── 04-Quick-Sort │ └── src │ │ ├── ISortAlgorithm.java │ │ ├── QuickSort.java │ │ ├── QuickSortOptimize.java │ │ ├── QuickSortThreeWays.java │ │ ├── QuickSortTwoWays.java │ │ └── SortHelper.java ├── 0451-sort-characters-by-frequency │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java └── QuickSort │ └── src │ ├── Solution.java │ ├── Solution2.java │ ├── Solution3.java │ └── Solution4.java ├── 05-Non-comparative-Sorting ├── 0041-first-missing-positive │ └── src │ │ └── Solution.java ├── 0442-find-all-duplicates-in-an-array │ └── src │ │ └── Solution.java ├── 0448-find-all-numbers-disappeared-in-an-array │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ ├── Solution6.java │ │ └── Solution7.java ├── BucketSort │ └── src │ │ ├── BucketSort.java │ │ └── Solution.java ├── CountingSort │ └── src │ │ ├── CountingSort.java │ │ ├── Solution.java │ │ └── Solution2.java └── RadixSort │ └── src │ ├── RadixSort.java │ └── Solution.java ├── 06-1-Sliding-Window ├── 1-Basic │ ├── 0003-longest-substring-without-repeating-characters │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ └── Solution5.java │ ├── 0076-minimum-window-substring │ │ ├── out │ │ │ └── production │ │ │ │ └── 0076-minimum-window-substring │ │ │ │ └── META-INF │ │ │ │ └── 0076-minimum-window-substring.kotlin_module │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0209-minimum-size-subarray-sum │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ ├── 0438-find-all-anagrams-in-a-string │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ └── 0567-permutation-in-string │ │ └── src │ │ ├── Solution.java │ │ └── Solution2.java └── 2-Advance │ ├── 0424-longest-repeating-character-replacement │ └── src │ │ └── Solution.java │ ├── 0480-sliding-window-median │ └── src │ │ └── Solution.java │ ├── 0643-maximum-average-subarray-i │ └── src │ │ └── Solution.java │ ├── 0978-longest-turbulent-subarray │ └── src │ │ └── Solution.java │ ├── 0992-subarrays-with-k-different-integers │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ └── 1493-longest-subarray-of-1s-after-deleting-one-element │ └── src │ └── Solution.java ├── 06-two-pointers ├── 0763-partition-labels │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0777-swap-adjacent-in-lr-string │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 1-Basic │ ├── 0009-palindrome-number │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0011-container-with-most-water │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── Solution3.java │ ├── 0026-remove-duplicates-from-sorted-array │ │ └── src │ │ │ └── Solution.java │ ├── 0125-valid-palindrome │ │ └── src │ │ │ └── Solution.java │ ├── 0151-reverse-words-in-a-string │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0167-two-sum-ii-input-array-is-sorted │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0344-reverse-string │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0345-reverse-vowels-of-a-string │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0658-find-k-closest-elements │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ └── 0977-squares-of-a-sorted-array │ │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 2-Importance │ ├── 0015-3sum │ │ └── src │ │ │ └── Solution.java │ ├── 0016-3sum-closest │ │ └── src │ │ │ └── Solution.java │ ├── 0018-4sum │ │ └── src │ │ │ └── Solution.java │ ├── 0042-trapping-rain-water │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ ├── Solution5.java │ │ │ ├── Solution6.java │ │ │ └── Solution7.java │ └── 0088-merge-sorted-array │ │ └── src │ │ └── Solution.java ├── 3-Advance │ ├── 0334-increasing-triplet-subsequence │ │ └── src │ │ │ └── Solution.java │ ├── 0713-subarray-product-less-than-k │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ └── Solution5.java │ ├── 0925-long-pressed-name │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ └── 0986-interval-list-intersections │ │ └── src │ │ └── Solution.java └── Python │ ├── 0011-container-with-most-water(双指针).py │ ├── 0011-container-with-most-water(暴力求解).py │ ├── 0015-3sum(指针对撞).py │ ├── 0015-3sum(暴力解法).py │ ├── 0016-3sum-closest.py │ ├── 0080-remove-duplicates-from-sorted-array-ii.py │ ├── 0125-valid-palindrome-2.py │ ├── 0125-valid-palindrome.py │ ├── 0167-two-sum-ii-input-array-is-sorted(双指针).py │ ├── 0334-increasing-triplet-subsequence.py │ ├── 0344-reverse-string(双指针).py │ ├── 0345-reverse-vowels-of-a-string(双指针).py │ └── 0611-valid-triangle-number(双指针).py ├── 07-Linked-List ├── 1-Basic │ ├── 0002-add-two-numbers │ │ └── src │ │ │ ├── ListNode.java │ │ │ └── Solution.java │ ├── 0024-swap-nodes-in-pairs │ │ └── src │ │ │ ├── ListNode.java │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0025-reverse-nodes-in-k-group │ │ └── src │ │ │ ├── ListNode.java │ │ │ └── Solution.java │ ├── 0061-rotate-list │ │ └── src │ │ │ ├── ListNode.java │ │ │ └── Solution.java │ ├── 0082-remove-duplicates-from-sorted-list-ii │ │ └── src │ │ │ ├── ListNode.java │ │ │ └── Solution.java │ ├── 0083-remove-duplicates-from-sorted-list │ │ └── src │ │ │ ├── ListNode.java │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0086-partition-list │ │ └── src │ │ │ ├── ListNode.java │ │ │ └── Solution.java │ ├── 0203-remove-linked-list-elements │ │ └── src │ │ │ ├── ListNode.java │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0206-reverse-linked-list │ │ └── src │ │ │ ├── ListNode.java │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0234-palindrome-linked-list │ │ └── src │ │ │ ├── ListNode.java │ │ │ └── Solution.java │ ├── 0237-delete-node-in-a-linked-list │ │ └── src │ │ │ ├── ListNode.java │ │ │ └── Solution.java │ ├── 0328-odd-even-linked-list │ │ └── src │ │ │ ├── ListNode.java │ │ │ └── Solution.java │ ├── 0445-add-two-numbers-ii │ │ └── src │ │ │ ├── ListNode.java │ │ │ └── Solution.java │ └── 0876-middle-of-the-linked-list │ │ └── src │ │ ├── ListNode.java │ │ └── Solution.java ├── 2-Importance │ ├── 0019-remove-nth-node-from-end-of-list │ │ └── src │ │ │ ├── ListNode.java │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0021-merge-two-sorted-lists │ │ └── src │ │ │ ├── ListNode.java │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0023-merge-k-sorted-lists │ │ └── src │ │ │ ├── ListNode.java │ │ │ └── Solution.java │ ├── 0092-reverse-linked-list-ii │ │ └── src │ │ │ ├── ListNode.java │ │ │ └── Solution.java │ ├── 0141-linked-list-cycle │ │ └── src │ │ │ ├── ListNode.java │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ ├── 0142-linked-list-cycle-ii │ │ └── src │ │ │ ├── ListNode.java │ │ │ └── Solution.java │ ├── 0143-reorder-list │ │ └── src │ │ │ ├── ListNode.java │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0146-lru-cache │ │ └── src │ │ │ └── LRUCache.java │ ├── 0147-insertion-sort-list │ │ └── src │ │ │ ├── ListNode.java │ │ │ └── Solution.java │ ├── 0148-sort-list │ │ └── src │ │ │ ├── ListNode.java │ │ │ └── Solution.java │ ├── 0160-intersection-of-two-linked-lists │ │ └── src │ │ │ ├── ListNode.java │ │ │ └── Solution.java │ ├── 0355-design-twitter │ │ └── src │ │ │ └── Twitter.java │ ├── 0460-lfu-cache │ │ └── src │ │ │ └── LFUCache.java │ └── 0707-design-linked-list │ │ └── src │ │ ├── MyLinkedList.java │ │ └── MyLinkedList2.java ├── 3-Advance │ └── 1290-convert-binary-number-in-a-linked-list-to-integer │ │ └── src │ │ ├── ListNode.java │ │ ├── Solution.java │ │ └── Solution2.java └── 补充 │ ├── 0002-add-two-numbers │ └── src │ │ └── Solution.java │ ├── 0019-remove-nth-node-from-end-of-list │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 0021-merge-two-sorted-lists │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 0023-merge-k-sorted-lists │ └── src │ │ ├── ListNode.java │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ └── Solution6.java │ ├── 0024-swap-nodes-in-pairs │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java │ ├── 0025-reverse-nodes-in-k-group │ └── src │ │ └── Solution.java │ ├── 0061-rotate-list │ └── src │ │ └── Solution.java │ ├── 0082-remove-duplicates-from-sorted-list-ii │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 0083-remove-duplicates-from-sorted-list │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 0086-partition-list │ └── src │ │ └── Solution.java │ ├── 0092-reverse-linked-list-ii │ └── src │ │ ├── ListNode.java │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 0141-linked-list-cycle │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java │ ├── 0142-linked-list-cycle-ii │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 0143-reorder-list │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 0146-lru-cache │ └── src │ │ └── LRUCache.java │ ├── 0147-insertion-sort-list │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java │ ├── 0148-sort-list │ └── src │ │ ├── ListNode.java │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java │ ├── 0160-intersection-of-two-linked-lists │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java │ ├── 0203-remove-linked-list-elements │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java │ ├── 0206-reverse-linked-list-2 │ └── src │ │ ├── ListNode.java │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 0206-reverse-linked-list │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 0234-palindrome-linked-list │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java │ ├── 0237-delete-node-in-a-linked-list │ └── src │ │ └── Solution.java │ ├── 0328-odd-even-linked-list │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 0355-design-twitter │ └── src │ │ └── Twitter.java │ ├── 0445-add-two-numbers-ii │ └── src │ │ └── Solution.java │ ├── 0460-lfu-cache │ └── src │ │ └── LFUCache.java │ ├── 05-Array │ └── src │ │ ├── Array.java │ │ ├── Main.java │ │ └── Student.java │ ├── 0707-design-linked-list │ └── src │ │ ├── MyLinkedList.java │ │ └── MyLinkedList2.java │ ├── 0876-middle-of-the-linked-list │ └── src │ │ └── Solution.java │ └── 1290-convert-binary-number-in-a-linked-list-to-integer │ └── src │ ├── Solution.java │ └── Solution2.java ├── 08-1-Stack ├── 1-Basic │ ├── 0020-valid-parentheses │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── Solution4.java │ ├── 0071-simplify-path │ │ └── src │ │ │ └── Solution.java │ ├── 0150-evaluate-reverse-polish-notation │ │ └── src │ │ │ └── Solution.java │ ├── 0155-min-stack │ │ └── src │ │ │ ├── Main.java │ │ │ ├── Main2.java │ │ │ ├── MinStack.java │ │ │ ├── MinStack2.java │ │ │ ├── MinStack3.java │ │ │ ├── MinStack4.java │ │ │ └── MinStack5Debug.java │ ├── 0225-implement-stack-using-queues │ │ └── src │ │ │ └── MyStack.java │ ├── 0232-implement-queue-using-stacks │ │ └── src │ │ │ └── MyQueue.java │ └── 1047-remove-all-adjacent-duplicates-in-string │ │ └── src │ │ └── Solution.java ├── 2-Advance │ ├── 0284-peeking-iterator │ │ └── src │ │ │ └── PeekingIterator.java │ ├── 0331-verify-preorder-serialization-of-a-binary-tree │ │ └── src │ │ │ └── Solution.java │ ├── 0341-flatten-nested-list-iterator │ │ └── src │ │ │ ├── NestedIterator.java │ │ │ ├── NestedIterator2.java │ │ │ └── NestedIterator3.java │ ├── 0682-baseball-game │ │ └── src │ │ │ └── Solution.java │ ├── 0735-asteroid-collision │ │ └── src │ │ │ └── Solution.java │ ├── 0946-validate-stack-sequences │ │ └── src │ │ │ └── Solution.java │ └── 1111-maximum-nesting-depth-of-two-valid-parentheses-strings │ │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── 3-Monotonic-Stack │ ├── 0042-trapping-rain-water │ │ └── src │ │ │ └── Solution.java │ ├── 0084-largest-rectangle-in-histogram │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── Solution3.java │ ├── 0316-remove-duplicate-letters │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0402-remove-k-digits │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ ├── Solution5.java │ │ │ └── Solution6.java │ ├── 0496-next-greater-element-i │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0503-next-greater-element-ii │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ ├── 0739-daily-temperatures │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── Solution3.java │ ├── 0901-online-stock-span │ │ └── src │ │ │ └── StockSpanner.java │ └── 1081-smallest-subsequence-of-distinct-characters │ │ └── src │ │ └── Solution.java ├── 数组实现的栈 │ └── 07-ArrayStack │ │ └── src │ │ ├── Array.java │ │ ├── ArrayStack.java │ │ ├── Main.java │ │ └── Stack.java └── 补充 │ ├── 0242-valid-anagram │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java │ ├── 0394-decode-string │ ├── out │ │ └── production │ │ │ └── 0394-decode-string │ │ │ └── META-INF │ │ │ └── 0394-decode-string.kotlin_module │ └── src │ │ └── Solution.java │ ├── 0844-backspace-string-compare(栈) │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 1028-recover-a-tree-from-preorder-traversal(栈、难题) │ └── src │ │ ├── Solution.java │ │ └── TreeNode.java │ ├── 1249-minimum-remove-to-make-valid-parentheses │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 1249-minimum-remove-to-make-valid-parentheses(栈) │ └── src │ │ └── Solution.java │ └── 1544-make-the-string-great(栈) │ └── src │ └── Solution.java ├── 08-2-Queue ├── 1-Basic │ ├── 0621-task-scheduler │ │ ├── out │ │ │ └── production │ │ │ │ └── 0621-task-scheduler │ │ │ │ └── META-INF │ │ │ │ └── 0621-task-scheduler.kotlin_module │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ ├── 0622-design-circular-queue │ │ └── src │ │ │ └── MyCircularQueue.java │ ├── 0641-design-circular-deque │ │ └── src │ │ │ └── MyCircularDeque.java │ ├── 0933-number-of-recent-calls │ │ └── src │ │ │ └── RecentCounter.java │ ├── 1284-minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 1311-get-watched-videos-by-your-friends │ │ └── src │ │ │ └── Solution.java │ └── 1315-sum-of-nodes-with-even-valued-grandparent │ │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── TreeNode.java ├── 2-Monotonous-Queue │ └── 0239-sliding-window-maximum │ │ └── src │ │ └── Solution.java └── 数组实现的循环队列 │ └── 07-ArrayQueue │ └── src │ ├── Array.java │ ├── ArrayQueue.java │ ├── Main.java │ └── Queue.java ├── 09-Priority-Queue(Heap) ├── 06-Heap │ └── src │ │ ├── HeapSort.java │ │ ├── HeapSort1.java │ │ ├── HeapSort2.java │ │ ├── HeapSort3.java │ │ ├── ISortAlgorithm.java │ │ ├── IndexMaxHeap.java │ │ ├── IndexMaxHeap1.java │ │ ├── IndexMaxHeap2.java │ │ ├── MaxHeap.java │ │ └── SortTestHelper.java ├── 1-Basic │ ├── 0264-ugly-number-ii │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0347-top-k-frequent-elements │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── Solution3.java │ ├── 0703-kth-largest-element-in-a-stream │ │ └── src │ │ │ └── KthLargest.java │ └── 0973-k-closest-points-to-origin │ │ └── src │ │ └── Solution.java ├── 2-Importance │ ├── 0023-merge-k-sorted-lists-using-our-priorityqueue │ │ ├── out │ │ │ └── production │ │ │ │ └── 0023-merge-k-sorted-lists │ │ │ │ └── META-INF │ │ │ │ └── 0023-merge-k-sorted-lists.kotlin_module │ │ └── src │ │ │ ├── ListNode.java │ │ │ ├── PriorityQueue.java │ │ │ └── Solution.java │ ├── 0023-merge-k-sorted-lists │ │ └── src │ │ │ ├── ListNode.java │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ ├── 0215-kth-largest-element-in-an-array-using-our-priorityqueue │ │ └── src │ │ │ └── Solution.java │ ├── 0215-kth-largest-element-in-an-array │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── Solution3.java │ └── 0295-find-median-from-data-stream │ │ └── src │ │ ├── MedianFinder.java │ │ └── MedianFinder2.java ├── 3-Advance │ ├── 0218-the-skyline-problem │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ ├── Solution5.java │ │ │ ├── Solution6.java │ │ │ └── Solution7.java │ ├── 1046-last-stone-weight │ │ └── src │ │ │ └── Solution.java │ ├── 1282-group-the-people-given-the-group-size-they-belong-to │ │ └── src │ │ │ └── Solution.java │ └── 1296-divide-array-in-sets-of-k-consecutive-numbers │ │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 索引堆 │ └── IndexMaxHeap │ │ └── src │ │ ├── IndexMaxHeap.java │ │ └── IndexMaxHeap2.java └── 自己实现的堆 │ ├── Custom-Heap │ └── src │ │ ├── IndexMaxHeap.java │ │ ├── IndexMaxHeap2.java │ │ ├── IndexMinHeap.java │ │ ├── LeetCode0215.java │ │ ├── LeetCode0215WithHeapify.java │ │ ├── MaxHeap.java │ │ ├── MinHeap.java │ │ ├── Queue.java │ │ ├── SolutionLeetCode0239.java │ │ └── SolutionLeetCode0239_2.java │ └── PriorityQueue │ └── src │ ├── MaxHeap.java │ ├── Queue.java │ ├── Solution.java │ └── Solution2.java ├── 10-Union-Find ├── 1-Basic │ ├── 0130-surrounded-regions │ │ └── src │ │ │ └── Solution3.java │ ├── 0200-number-of-islands │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0547-friend-circles │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ ├── Solution5.java │ │ │ ├── Solution6.java │ │ │ └── Solution7.java │ ├── 0684-redundant-connection │ │ └── src │ │ │ └── Solution.java │ ├── 0990-satisfiability-of-equality-equations │ │ └── src │ │ │ └── Solution.java │ └── 1319-number-of-operations-to-make-network-connected │ │ └── src │ │ └── Solution.java └── 2-Advance │ ├── 0128-longest-consecutive-sequence │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java │ ├── 0399-evaluate-division │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 0685-redundant-connection-ii │ └── src │ │ └── Solution.java │ ├── 0721-accounts-merge │ └── src │ │ └── Solution.java │ ├── 0765-couples-holding-hands │ └── src │ │ └── Solution.java │ ├── 0803-bricks-falling-when-hit │ └── src │ │ └── Solution.java │ ├── 0839-similar-string-groups │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java │ ├── 0945-minimum-increment-to-make-array-unique │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java │ ├── 0947-most-stones-removed-with-same-row-or-column │ └── src │ │ └── Solution.java │ ├── 0952-largest-component-size-by-common-factor │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 0959-regions-cut-by-slashes │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java │ ├── 1202-smallest-string-with-swaps │ └── src │ │ └── Solution.java │ └── 1559-detect-cycles-in-2d-grid │ └── src │ ├── Solution.java │ └── Solution2.java ├── 11-Binary-Search-Tree ├── 1-Basic │ ├── 0235-lowest-common-ancestor-of-a-binary-search-tree │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── TreeNode.java │ ├── 0449-serialize-and-deserialize-bst │ │ └── src │ │ │ ├── Codec.java │ │ │ └── TreeNode.java │ ├── 0450-delete-node-in-a-bst │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── TreeNode.java │ ├── 0700-search-in-a-binary-search-tree │ │ └── src │ │ │ ├── Solution.java │ │ │ └── TreeNode.java │ └── 0701-insert-into-a-binary-search-tree │ │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── TreeNode.java ├── 2-Importance │ ├── 0094-binary-tree-inorder-traversal │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── TreeNode.java │ ├── 0098-validate-binary-search-tree │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ ├── Solution5.java │ │ │ └── TreeNode.java │ └── 0230-kth-smallest-element-in-a-bst │ │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ ├── Solution6.java │ │ ├── Solution7.java │ │ └── TreeNode.java ├── 3-Advance │ ├── 0173-binary-search-tree-iterator │ │ └── src │ │ │ ├── BSTIterator.java │ │ │ └── TreeNode.java │ ├── 0538-convert-bst-to-greater-tree │ │ └── src │ │ │ ├── Solution.java │ │ │ └── TreeNode.java │ ├── 0653-two-sum-iv-input-is-a-bst │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── TreeNode.java │ ├── 0669-trim-a-binary-search-tree │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── TreeNode.java │ ├── 0783-minimum-distance-between-bst-nodes │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── TreeNode.java │ └── 1008-construct-binary-search-tree-from-preorder-traversal │ │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ ├── Solution6.java │ │ ├── Solution7.java │ │ └── TreeNode.java └── BinarySearchTree │ └── src │ ├── BST.java │ └── BinarySearchTree.java ├── 11-Binary-Tree ├── 1-Basic │ ├── 0100-same-tree │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── TreeNode.java │ ├── 0101-symmetric-tree │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ └── TreeNode.java │ ├── 0102-binary-tree-level-order-traversal │ │ └── src │ │ │ ├── Solution.java │ │ │ └── TreeNode.java │ ├── 0103-binary-tree-zigzag-level-order-traversal │ │ └── src │ │ │ ├── Solution.java │ │ │ └── TreeNode.java │ ├── 0104-maximum-depth-of-binary-tree │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── TreeNode.java │ ├── 0107-binary-tree-level-order-traversal-ii │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── TreeNode.java │ ├── 0108-convert-sorted-array-to-binary-search-tree │ │ └── src │ │ │ ├── Solution.java │ │ │ └── TreeNode.java │ ├── 0109-convert-sorted-list-to-binary-search-tree │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── Solution3.java │ ├── 0110-balanced-binary-tree │ │ └── src │ │ │ ├── Solution.java │ │ │ └── TreeNode.java │ ├── 0111-minimum-depth-of-binary-tree │ │ └── src │ │ │ ├── Solution.java │ │ │ └── TreeNode.java │ ├── 0112-path-sum │ │ └── src │ │ │ ├── Solution.java │ │ │ └── TreeNode.java │ ├── 0114-flatten-binary-tree-to-linked-list │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── TreeNode.java │ ├── 0129-sum-root-to-leaf-numbers │ │ └── src │ │ │ ├── Solution.java │ │ │ └── TreeNode.java │ ├── 0144-binary-tree-preorder-traversal │ │ └── src │ │ │ ├── Solution.java │ │ │ └── TreeNode.java │ ├── 0145-binary-tree-postorder-traversal │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── TreeNode.java │ ├── 0173-binary-search-tree-iterator │ │ └── src │ │ │ ├── BSTIterator.java │ │ │ └── TreeNode.java │ ├── 0199-binary-tree-right-side-view │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ └── TreeNode.java │ ├── 0257-binary-tree-paths │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── TreeNode.java │ └── 0404-sum-of-left-leaves │ │ └── src │ │ ├── Solution.java │ │ └── TreeNode.java ├── 2-Importance │ ├── 0094-binary-tree-inorder-traversal │ │ └── src │ │ │ ├── Solution.java │ │ │ └── TreeNode.java │ ├── 0098-validate-binary-search-tree │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ └── TreeNode.java │ ├── 0105-construct-binary-tree-from-preorder-and-inorder-traversal │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── TreeNode.java │ ├── 0106-construct-binary-tree-from-inorder-and-postorder-traversal │ │ └── src │ │ │ ├── Solution.java │ │ │ └── TreeNode.java │ ├── 0226-invert-binary-tree │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ └── TreeNode.java │ ├── 0230-kth-smallest-element-in-a-bst │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ ├── Solution5.java │ │ │ └── TreeNode.java │ ├── 0235-lowest-common-ancestor-of-a-binary-search-tree │ │ └── src │ │ │ ├── Solution.java │ │ │ └── TreeNode.java │ ├── 0236-lowest-common-ancestor-of-a-binary-tree │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── TreeNode.java │ │ │ ├── Trie.java │ │ │ ├── Trie2.java │ │ │ └── WordDictionary.java │ └── 0297-serialize-and-deserialize-binary-tree │ │ └── src │ │ ├── Codec.java │ │ └── Codec2.java └── 3-Advance │ ├── 0222-count-complete-tree-nodes │ └── src │ │ ├── Solution.java │ │ └── TreeNode.java │ ├── 0437-path-sum-iii │ └── src │ │ ├── Solution.java │ │ └── TreeNode.java │ ├── 0515-find-largest-value-in-each-tree-row │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── TreeNode.java │ ├── 0652-find-duplicate-subtrees │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── TreeNode.java │ ├── 0951-flip-equivalent-binary-trees │ └── src │ │ ├── Solution.java │ │ └── TreeNode.java │ ├── 0993-cousins-in-binary-tree │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── TreeNode.java │ ├── 1302-deepest-leaves-sum │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── TreeNode.java │ ├── 1305-all-elements-in-two-binary-search-trees │ └── src │ │ ├── Solution.java │ │ └── TreeNode.java │ └── 1315-sum-of-mutated-array-closest-to-target │ └── src │ ├── Solution.java │ ├── Solution2.java │ ├── Solution3.java │ ├── Solution4.java │ ├── Solution5.java │ └── Solution6.java ├── 12-Backtracking-And-DFS ├── Type-1-Basic │ ├── 0039-combination-sum-debug │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0039-combination-sum │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ └── Solution5.java │ ├── 0040-combination-sum-ii-debug │ │ └── src │ │ │ └── Solution.java │ ├── 0040-combination-sum-ii │ │ └── src │ │ │ └── Solution.java │ ├── 0046-permutations-debug │ │ └── src │ │ │ └── Solution.java │ ├── 0046-permutations │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ ├── 0047-permutations-ii │ │ └── src │ │ │ └── Solution.java │ ├── 0060-permutation-sequence │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ ├── 0077-combinations │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ └── Solution5.java │ ├── 0078-subsets │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ ├── Solution5.java │ │ │ └── Solution6.java │ ├── 0079-word-search │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── Solution3.java │ ├── 0090-subsets-ii │ │ ├── out │ │ │ └── production │ │ │ │ └── 0090-subsets-ii │ │ │ │ └── META-INF │ │ │ │ └── 0090-subsets-ii.kotlin_module │ │ └── src │ │ │ └── Solution.java │ ├── 0113-path-sum-ii │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ ├── Solution5.java │ │ │ ├── Solution6.java │ │ │ └── TreeNode.java │ ├── 0131-palindrome-partitioning │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ ├── 0216-combination-sum-iii │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── Solution3.java │ ├── 0401-binary-watch │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0491-increasing-subsequences │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── Solution3.java │ ├── 0785-is-graph-bipartite │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── Solution3.java │ ├── 0886-possible-bipartition │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ └── 1079-letter-tile-possibilities │ │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── Type-2-String-Backtracking │ ├── 0017-letter-combinations-of-a-phone-number │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ ├── 0022-generate-parentheses │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ ├── Solution5.java │ │ │ └── Solution6.java │ ├── 0093-restore-ip-addresses │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ ├── Solution5.java │ │ │ └── Solution6.java │ └── 0784-letter-case-permutation │ │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── Type-3-FloodFill │ ├── 0130-surrounded-regions │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ ├── 0200-number-of-islands │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ ├── 0417-pacific-atlantic-water-flow │ │ └── src │ │ │ └── Solution.java │ ├── 0529-minesweeper │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0733-flood-fill │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── Solution3.java │ ├── 0994-rotting-oranges │ │ └── src │ │ │ └── Solution.java │ ├── 1020-number-of-enclaves │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 1034-coloring-a-border │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 1080-insufficient-nodes-in-root-to-leaf-paths │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── TreeNode.java │ ├── 1102-path-with-maximum-minimum-value │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ ├── 1254-number-of-closed-islands │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ ├── 1391-check-if-there-is-a-valid-path-in-a-grid │ │ └── src │ │ │ └── Solution.java │ ├── 1593-split-a-string-into-the-max-number-of-unique-substrings │ │ └── src │ │ │ └── Solution.java │ └── 1631-path-with-minimum-effort │ │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── Type-4-Play-Games │ ├── 0037-sudoku-solver │ │ └── src │ │ │ └── Solution.java │ ├── 0051-n-queens │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── Solution3.java │ ├── 0488-zuma-game │ │ └── src │ │ │ └── Solution.java │ └── 0679-24-game │ │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── Type-5-Hard │ ├── 0126-word-ladder-ii │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ ├── Solution5.java │ │ │ ├── Solution6.java │ │ │ └── Solution7.java │ └── 0140-word-break-ii │ │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── Type-6-Complex-Problem │ ├── 0306-additive-number │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ └── 0842-split-array-into-fibonacci-sequence │ │ └── src │ │ └── Solution.java └── 其它 │ ├── 0037-sudoku-solver │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 0039-combination-sum │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java │ ├── 0046-permutations │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 0077-combinations │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java │ ├── 0078-subsets │ ├── out │ │ └── production │ │ │ └── 0078-subsets │ │ │ └── META-INF │ │ │ └── 0078-subsets.kotlin_module │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java │ ├── 0079-word-search-2 │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ └── Solution6.java │ ├── 0079-word-search-3 │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 0079-word-search │ └── src │ │ └── Solution.java │ ├── 0107-binary-tree-level-order-traversal-ii │ └── src │ │ ├── Solution.java │ │ └── TreeNode.java │ ├── 1545-find-kth-bit-in-nth-binary-string(递归、DFS) │ └── src │ │ └── Solution.java │ ├── 回溯算法 │ ├── 0046-permutations │ │ └── src │ │ │ └── Solution.java │ └── 0077-combinations │ │ └── src │ │ └── Solution.java │ └── 难题Java代码 │ ├── 0212-word-search-ii │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java │ ├── 0301-remove-invalid-parentheses │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 0473-matchsticks-to-square │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java │ └── 1286-iterator-for-combination │ └── src │ ├── CombinationIterator.java │ └── CombinationIterator2.java ├── 13-Dynamic-Programming-1 ├── 13-1-introduction │ └── 0509-fibonacci-number │ │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 13-2-Repetitive-Subproblem │ ├── 0046-ba-shu-zi-fan-yi-cheng-zi-fu-chuan-lcof │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0062-unique-paths │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ └── Solution5.java │ ├── 0063-unique-paths-ii │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── Solution3.java │ ├── 0064-minimum-path-sum │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── Solution3.java │ ├── 0070-climbing-stairs │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ └── Solution5.java │ ├── 0091-decode-ways │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0096-unique-binary-search-trees │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── Solution3.java │ ├── 0221-maximal-square │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ └── 0746-min-cost-climbing-stairs │ │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ └── Solution6.java ├── 13-3-Optimal-Substructure │ ├── 0279-perfect-squares │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ ├── Solution5.java │ │ │ ├── Solution6.java │ │ │ └── Solution7.java │ ├── 0322-coin-change │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ ├── 0343-integer-break │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ └── 0377-combination-sum-iv │ │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ ├── Solution6.java │ │ ├── Solution7.java │ │ └── Solution8.java ├── 13-4-No-Aftereffect │ ├── 0120-triangle │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ ├── 0198-house-robber │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ ├── 0213-house-robber-ii │ │ └── src │ │ │ └── Solution.java │ ├── 0983-minimum-cost-for-tickets │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ └── Stock-Problems │ │ ├── 0121-best-time-to-buy-and-sell-stock │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ ├── Solution5.java │ │ │ ├── Solution6.java │ │ │ └── Solution7.java │ │ ├── 0122-best-time-to-buy-and-sell-stock-ii │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ ├── Solution5.java │ │ │ ├── Solution6.java │ │ │ └── Solution7.java │ │ ├── 0123-best-time-to-buy-and-sell-stock-iii │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── Solution3.java │ │ ├── 0188-best-time-to-buy-and-sell-stock-iv │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ │ ├── 0309-best-time-to-buy-and-sell-stock-with-cooldown │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── Solution3.java │ │ └── 0714-best-time-to-buy-and-sell-stock-with-transaction-fee │ │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── 13-5-LIS │ ├── 0300-longest-increasing-subsequence │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ ├── 0354-russian-doll-envelopes │ │ └── src │ │ │ └── Solution.java │ ├── 0646-maximum-length-of-pair-chain │ │ └── src │ │ │ └── Solution.java │ ├── 0674-longest-continuous-increasing-subsequence │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ ├── 1048-longest-string-chain │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── Solution3.java │ └── 最大子段和以及相关问题 │ │ ├── 0053-maximum-subarray │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ ├── Solution5.java │ │ │ ├── Solution6.java │ │ │ └── Solution7.java │ │ ├── 0152-maximum-product-subarray │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ │ ├── 0918-maximum-sum-circular-subarray │ │ ├── out │ │ │ └── production │ │ │ │ └── 0918-maximum-sum-circular-subarray │ │ │ │ └── META-INF │ │ │ │ └── 0918-maximum-sum-circular-subarray.kotlin_module │ │ └── src │ │ │ └── Solution.java │ │ └── 1594-maximum-non-negative-product-in-a-matrix │ │ └── src │ │ └── Solution.java └── 13-6-LCS │ ├── 0010-regular-expression-matching │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java │ ├── 0044-wildcard-matching │ └── src │ │ └── Solution.java │ ├── 0072-edit-distance │ └── src │ │ └── Solution.java │ ├── 0097-interleaving-string │ └── src │ │ └── Solution.java │ ├── 0115-distinct-subsequences │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java │ ├── 0718-maximum-length-of-repeated-subarray │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 1035-uncrossed-lines │ └── src │ │ └── Solution.java │ ├── 1092-shortest-common-supersequence │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ └── 1143-longest-common-subsequence │ └── src │ └── Solution.java ├── 14-Dynamic-Programming-2 ├── 01 背包问题 │ ├── 0416-partition-equal-subset-sum │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── Solution3.java │ ├── 0474-ones-and-zeroes-2 │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0474-ones-and-zeroes │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0494-target-sum-2 │ │ └── src │ │ │ └── Solution.java │ ├── 0494-target-sum │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ └── Solution5.java │ ├── 0879-profitable-schemes │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ ├── 0879-profitable-schemes(官方题解的写法) │ │ └── src │ │ │ └── Solution.java │ ├── 1049-last-stone-weight-ii-2 │ │ └── src │ │ │ └── Solution.java │ └── 1049-last-stone-weight-ii │ │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java └── 完全背包问题 │ ├── 0139-word-break │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ └── Solution6.java │ ├── 0322-coin-change │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ ├── Solution6.java │ │ └── Solution7.java │ ├── 0518-coin-change-2 │ └── src │ │ ├── Solution.java │ │ ├── Solution10.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ ├── Solution6.java │ │ ├── Solution7.java │ │ ├── Solution8.java │ │ └── Solution9.java │ ├── 14-3 完全包问题 │ ├── 0-1、完全背包问题选讲.pdf │ └── 0-1、完全背包问题选讲.pptx │ └── 1449-form-largest-integer-with-digits-that-add-up-to-target │ └── src │ ├── Solution.java │ └── Solution2.java ├── 15-Greedy-Algorithm ├── 0012-integer-to-roman │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0045-jump-game-ii │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ └── Solution6.java ├── 0055-jump-game │ └── src │ │ └── Solution.java ├── 0056-merge-intervals │ └── src │ │ └── Solution.java ├── 0134-gas-station │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0135-candy │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0392-is-subsequence │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 0435-non-overlapping-intervals │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0452-minimum-number-of-arrows-to-burst-balloons │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0455-assign-cookies │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0561-array-partition-i │ └── src │ │ └── Solution.java ├── 1029-two-city-scheduling │ └── src │ │ └── Solution.java ├── 1247-minimum-swaps-to-make-strings-equal │ └── src │ │ └── Solution.java └── 贪心算法 │ ├── 0056-merge-intervals │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 0057-insert-interval │ └── src │ │ ├── Interval.java │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 0135-candy │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java │ ├── 0406-queue-reconstruction-by-height(不是贪心算法) │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Tree.java │ ├── 0455-Assign-Cookies │ ├── cpp-0455 │ │ ├── main.cpp │ │ └── main2.cpp │ └── java-0455 │ │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 0860-lemonade-change │ └── src │ │ └── Solution.java │ └── 0861-score-after-flipping-matrix │ └── src │ └── Solution.java ├── 17-Hash-Table ├── 1-Basic │ ├── 0001-two-sum │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── Solution3.java │ ├── 0170-two-sum-iii-data-structure-design │ │ └── src │ │ │ └── TwoSum.java │ └── 1865-finding-pairs-with-a-certain-sum │ │ └── src │ │ └── FindSumPairs.java ├── 2-Advance │ ├── 0036-valid-sudoku │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0049-group-anagrams │ │ ├── README.md │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ ├── Solution5.java │ │ │ ├── Solution6.java │ │ │ └── Solution7.java │ ├── 0187-repeated-dna-sequences │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ ├── 0202-happy-number │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0205-isomorphic-strings │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ ├── Solution4.java │ │ │ ├── Solution5.java │ │ │ └── Solution6.java │ ├── 0217-contains-duplicate │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ ├── 0219-contains-duplicate-ii │ │ └── src │ │ │ └── Solution.java │ ├── 0290-word-pattern │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0349-intersection-of-two-arrays │ │ └── src │ │ │ └── Solution.java │ ├── 0350-intersection-of-two-arrays-ii │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ └── Solution3.java │ ├── 0352-data-stream-as-disjoint-intervals │ │ └── src │ │ │ └── SummaryRanges.java │ ├── 0387-first-unique-character-in-a-string │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ ├── 0447-number-of-boomerangs │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ ├── 0454-4sum-ii │ │ └── src │ │ │ └── Solution.java │ ├── 1207-unique-number-of-occurrences │ │ └── src │ │ │ └── Solution.java │ ├── 1371-find-the-longest-substring-containing-vowels-in-even-counts │ │ └── src │ │ │ ├── Solution.java │ │ │ └── Solution2.java │ └── 1603-design-parking-system │ │ └── src │ │ └── ParkingSystem.java └── 待分类 │ ├── 0220-contains-duplicate-iii │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ ├── Solution6.java │ │ └── TreeSetDemo.java │ ├── 0349-intersection-of-two-arrays │ └── src │ │ └── Solution.java │ ├── 0380-insert-delete-getrandom-o1 │ └── src │ │ └── RandomizedSet.java │ ├── 0381-insert-delete-getrandom-o1-duplicates-allowed │ └── src │ │ └── RandomizedCollection.java │ ├── 0389-find-the-difference │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 0409-longest-palindrome │ └── src │ │ └── Solution.java │ ├── 0706-design-hashmap │ └── src │ │ └── MyHashMap.java │ ├── 0771-jewels-and-stones │ └── src │ │ └── Solution.java │ ├── 1248-count-number-of-nice-subarrays │ └── src │ │ └── Solution.java │ └── 1546-maximum-number-of-non-overlapping-subarrays-with-sum-equals-target(前缀和、哈希表、动态规划) │ └── src │ └── Solution.java ├── 18-prefix-sum ├── 0523-continuous-subarray-sum │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── 0525-contiguous-array │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── 0560-subarray-sum-equals-k │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── 0974-subarray-sums-divisible-by-k │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java └── 1248-count-number-of-nice-subarrays │ └── src │ ├── Solution.java │ ├── Solution2.java │ └── Solution3.java ├── 19-Breadth-First-Search ├── 0127-word-ladder │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 0133-clone-graph │ └── src │ │ ├── Node.java │ │ ├── Solution.java │ │ └── Solution2.java ├── 0207-course-schedule │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0210-course-schedule-ii │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0279-perfect-squares │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0310-minimum-height-trees │ └── src │ │ └── Solution.java ├── 0322-coin-change │ └── src │ │ └── Solution.java ├── 0515-find-largest-value-in-each-tree-row │ └── src │ │ ├── Solution.java │ │ └── TreeNode.java ├── 0542-01-matrix │ └── src │ │ ├── MinHeap.java │ │ └── Solution.java ├── 0637-average-of-levels-in-binary-tree │ └── src │ │ ├── Solution.java │ │ └── TreeNode.java ├── 0690-employee-importance │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0695-max-area-of-island │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 1091-shortest-path-in-binary-matrix │ └── src │ │ └── Solution.java ├── 1162-as-far-from-land-as-possible │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 1203-sort-items-by-groups-respecting-dependencies │ └── src │ │ └── Solution.java └── 1306-jump-game-iii │ └── src │ └── Solution.java ├── 20-graph ├── 0778-swim-in-rising-water │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 1203-sort-items-by-groups-respecting-dependencies │ └── src │ │ └── Solution.java ├── 1631-path-with-minimum-effort │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── Bellman-Ford │ └── 0787-cheapest-flights-within-k-stops │ │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ ├── Solution6.java │ │ └── Solution7.java ├── Dijkstra 算法 │ ├── 0505-the-maze-ii │ │ └── src │ │ │ ├── Solution.java │ │ │ ├── Solution2.java │ │ │ ├── Solution3.java │ │ │ └── Solution4.java │ └── 0818-race-car │ │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java └── 最小生成树-例题 │ └── 1135-connecting-cities-with-minimum-cost │ └── src │ ├── Kruskal.java │ ├── Prim.java │ ├── Solution.java │ └── Solution2.java ├── 22-divide-and-conquer └── 0095-unique-binary-search-trees-ii │ └── src │ ├── Solution.java │ ├── Solution2.java │ ├── Solution3.java │ └── TreeNode.java ├── 23-trie ├── 0208-implement-trie-prefix-tree │ └── src │ │ ├── Trie.java │ │ ├── Trie2.java │ │ ├── Trie3.java │ │ ├── Trie4.java │ │ └── Trie5.java ├── 0211-add-and-search-word-data-structure-design │ └── src │ │ ├── WordDictionary.java │ │ ├── WordDictionary2.java │ │ └── WordDictionary3.java ├── 0212-word-search-ii │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0336-palindrome-pairs-2 │ └── src │ │ └── Solution.java ├── 0336-palindrome-pairs │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0421-maximum-xor-of-two-numbers-in-an-array │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0425-word-squares │ └── src │ │ └── Solution.java ├── 0648-replace-words-2 │ └── src │ │ └── Solution.java ├── 0648-replace-words │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0677-map-sum-pairs │ └── src │ │ ├── MapSum.java │ │ └── MapSum2.java ├── 0720-longest-word-in-dictionary-2 │ └── src │ │ └── Solution.java ├── 0720-longest-word-in-dictionary │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0820-short-encoding-of-words(Trie) │ └── src │ │ └── Solution.java ├── 15-Trie │ └── src │ │ ├── Main.java │ │ └── Trie.java └── python │ ├── 0208-implement-trie-prefix-tree-2.py │ ├── 0208-implement-trie-prefix-tree.py │ ├── 0211-add-and-search-word-data-structure-design-2.py │ ├── 0211-add-and-search-word-data-structure-design-3.py │ ├── 0211-add-and-search-word-data-structure-design.py │ ├── 0677-map-sum-pairs-2.py │ ├── 0677-map-sum-pairs-3.py │ ├── 0677-map-sum-pairs.py │ ├── 0720-longest-word-in-dictionary(排序解法).py │ ├── 0720-longest-word-in-dictionary(看不懂的解答).py │ └── 0720(字典树).py ├── 28-string └── 1-Basic │ ├── 0006-zigzag-conversion │ └── src │ │ └── Solution.java │ ├── 0008-string-to-integer-atoi │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java │ ├── 0013-roman-to-integer │ └── src │ │ └── Solution.java │ ├── 0014-longest-common-prefix │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 0028-implement-strstr │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java │ ├── 0031-next-permutation │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 0058-length-of-last-word │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 0067-add-binary │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 0165-compare-version-numbers │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 0387-first-unique-character-in-a-string │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 0415-add-strings │ └── src │ │ └── Solution.java │ ├── 0443-string-compression │ └── src │ │ └── Solution.java │ ├── 0459-repeated-substring-pattern │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java │ ├── 0521-longest-uncommon-subsequence-i │ └── src │ │ └── Solution.java │ ├── 0541-reverse-string-ii │ └── src │ │ └── Solution.java │ ├── 0557-reverse-words-in-a-string-iii │ └── src │ │ └── Solution.java │ ├── 0657-robot-return-to-origin │ └── src │ │ └── Solution.java │ ├── 0680-valid-palindrome-ii │ └── src │ │ └── Solution.java │ ├── 0686-repeated-string-match │ └── src │ │ └── Solution.java │ ├── 0819-most-common-word │ └── src │ │ └── Solution.java │ ├── 0824-goat-latin │ └── src │ │ └── Solution.java │ ├── 0844-backspace-string-compare │ └── src │ │ └── Solution.java │ ├── 0859-buddy-strings │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 1081-smallest-subsequence-of-distinct-characters │ └── src │ │ ├── Solution.java │ │ └── Solution2.java │ ├── 1169-invalid-transactions │ └── src │ │ └── Solution.java │ ├── 1309-decrypt-string-from-alphabet-to-integer-mapping │ └── src │ │ └── Solution.java │ └── 1324-print-words-vertically │ └── src │ └── Solution.java ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | Solutions/ 2 | .idea/ 3 | 临时空间/ 4 | 测试/ 5 | test/ 6 | *.iml 7 | *.class 8 | */*/out/ 9 | */*/cmake-build-debug/ 10 | cmake-build-*/ 11 | CMakeLists.txt 12 | 待整理/ -------------------------------------------------------------------------------- /02-Binary-Search/Type-1/0033-search-in-rotated-sorted-array/src/Solution4.java: -------------------------------------------------------------------------------- 1 | public class Solution4 { 2 | 3 | // 最朴素的解法,时间复杂度不符合要求 4 | 5 | public int search(int[] nums, int target) { 6 | int len = nums.length; 7 | for (int i = 0; i < len; i++) { 8 | if (nums[i] == target) { 9 | return i; 10 | } 11 | } 12 | return -1; 13 | } 14 | } -------------------------------------------------------------------------------- /02-Binary-Search/Type-1/0069-sqrtx/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 暴力解法 4 | 5 | public int mySqrt(int x) { 6 | if (x <= 1) { 7 | return x; 8 | } 9 | for (int i = 1; i <= x; ++i) { 10 | if (i == x / i) { 11 | return i; 12 | } else if (i > x / i) { 13 | return i - 1; 14 | } 15 | } 16 | throw new IllegalArgumentException("参数出错"); 17 | } 18 | } -------------------------------------------------------------------------------- /02-Binary-Search/Type-1/0153-find-minimum-in-rotated-sorted-array/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int findMin(int[] nums) { 4 | int len = nums.length; 5 | int left = 0; 6 | int right = len - 1; 7 | // 在区间 [left..right] 里查找目标元素 8 | while (left < right) { 9 | int mid = left + (right - left) / 2; 10 | if (nums[mid] < nums[right]) { 11 | // 下一轮搜索区间 [left..mid] 12 | right = mid; 13 | } else { 14 | // 下一轮搜索区间 [mid + 1..right] 15 | left = mid + 1; 16 | } 17 | } 18 | return nums[left]; 19 | } 20 | } -------------------------------------------------------------------------------- /02-Binary-Search/Type-1/0153-find-minimum-in-rotated-sorted-array/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public int findMin(int[] nums) { 4 | int len = nums.length; 5 | int left = 0; 6 | int right = len - 1; 7 | // 在区间 [left..right] 里查找目标元素 8 | while (left < right) { 9 | int mid = left + (right - left) / 2; 10 | if (nums[mid] > nums[right]) { 11 | // 下一轮搜索区间 [mid + 1..right] 12 | left = mid + 1; 13 | } else { 14 | // 下一轮搜索区间 [left..mid] 15 | right = mid; 16 | } 17 | } 18 | return nums[left]; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /02-Binary-Search/Type-1/0153-find-minimum-in-rotated-sorted-array/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | public int findMin(int[] nums) { 4 | return findMin(nums, 0, nums.length - 1); 5 | } 6 | 7 | private int findMin(int[] nums, int left, int right) { 8 | if (nums[left] == nums[right]) { 9 | return nums[left]; 10 | } 11 | 12 | int mid = (left + right) / 2; 13 | if (nums[mid] > nums[right]) { 14 | return findMin(nums, mid + 1, right); 15 | } else { 16 | return findMin(nums, left, mid); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /02-Binary-Search/Type-1/0154-find-minimum-in-rotated-sorted-array-ii/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int findMin(int[] nums) { 4 | int len = nums.length; 5 | int left = 0; 6 | int right = len - 1; 7 | // 在区间 [left, right] 里查找目标元素 8 | while (left < right) { 9 | int mid = left + (right - left) / 2; 10 | if (nums[mid] == nums[right]) { 11 | right--; 12 | } else if (nums[mid] < nums[right]) { 13 | // 下一轮搜索区间是 [left, mid] 14 | right = mid; 15 | } else { 16 | // 下一轮搜索区间是 [mid + 1, right] 17 | left = mid + 1; 18 | } 19 | } 20 | return nums[left]; 21 | } 22 | } -------------------------------------------------------------------------------- /02-Binary-Search/Type-1/0162-find-peak-element/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 返回任何一个峰值,看相邻位置 4 | 5 | public int findPeakElement(int[] nums) { 6 | int len = nums.length; 7 | int left = 0; 8 | int right = len - 1; 9 | while (left < right) { 10 | int mid = left + (right - left) / 2; 11 | // 正好看到的是右边元素,分支排除了左边界,并且使用左中位数,可以保证逻辑是完备的 12 | if (nums[mid] < nums[mid + 1]) { 13 | left = mid + 1; 14 | } else { 15 | right = mid; 16 | } 17 | } 18 | // 峰值元素一定存在,因此无需后处理 19 | return left; 20 | } 21 | } -------------------------------------------------------------------------------- /02-Binary-Search/Type-1/0278-first-bad-version/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 extends VersionControl { 2 | 3 | /** 4 | * @param n n 是所有的版本数 5 | * @return 第一个出错的版本 6 | */ 7 | public int firstBadVersion(int n) { 8 | int left = 1; 9 | int right = n; 10 | // 注意:这里使用的是小于号 11 | while (left < right) { 12 | int mid = left + (right - left) / 2; 13 | if (isBadVersion(mid)) { 14 | right = mid; 15 | } else { 16 | left = mid + 1; 17 | } 18 | } 19 | return right; 20 | } 21 | } -------------------------------------------------------------------------------- /02-Binary-Search/Type-1/0278-first-bad-version/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 extends VersionControl { 2 | 3 | /** 4 | * @param n n 是所有的版本数 5 | * @return 第一个出错的版本 6 | */ 7 | public int firstBadVersion(int n) { 8 | int left = 1; 9 | int right = n; 10 | // 注意:这里使用的是小于号 11 | while (left <= right) { 12 | int mid = left + (right - left) / 2; 13 | if (isBadVersion(mid)) { 14 | right = mid - 1; 15 | } else { 16 | left = mid + 1; 17 | } 18 | } 19 | return left; 20 | } 21 | } -------------------------------------------------------------------------------- /02-Binary-Search/Type-1/0278-first-bad-version/src/Solution4.java: -------------------------------------------------------------------------------- 1 | public class Solution4 extends VersionControl { 2 | 3 | public int firstBadVersion(int n) { 4 | int left = 1; 5 | int right = n; 6 | while (left < right) { 7 | int mid = left + (right - left) / 2; 8 | if (!isBadVersion(mid)) { 9 | left = mid + 1; 10 | } else { 11 | right = mid; 12 | } 13 | } 14 | return left; 15 | } 16 | } -------------------------------------------------------------------------------- /02-Binary-Search/Type-1/0374-guess-number-higher-or-lower/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 extends GuessGame { 2 | 3 | public int guessNumber(int n) { 4 | int left = 1; 5 | int right = n; 6 | while (left <= right) { 7 | int mid = left + (right - left) / 2; 8 | int guessNum = guess(mid); 9 | if (guessNum == 0) { 10 | return mid; 11 | } else if (guessNum == -1) { 12 | right = mid - 1; 13 | } else { 14 | left = mid + 1; 15 | } 16 | } 17 | return -1; 18 | } 19 | } -------------------------------------------------------------------------------- /02-Binary-Search/Type-1/0374-guess-number-higher-or-lower/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 extends GuessGame { 2 | 3 | public int guessNumber(int n) { 4 | int left = 1; 5 | int right = n; 6 | while (left < right) { 7 | int mid = left + (right - left + 1) / 2; 8 | int guessNum = guess(mid); 9 | if (guessNum == -1) { 10 | // 目标数字小, mid 大 11 | right = mid - 1; 12 | } else { 13 | left = mid; 14 | } 15 | } 16 | // 最后剩下的数一定是所求,无需后处理 17 | return left; 18 | } 19 | } -------------------------------------------------------------------------------- /02-Binary-Search/Type-1/0704-binary-search/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public int search(int[] nums, int target) { 4 | int len = nums.length; 5 | if (len == 0) { 6 | return -1; 7 | } 8 | int left = 0; 9 | int right = len - 1; 10 | while (left < right) { 11 | int mid = (left + right) >>> 1; 12 | if (nums[mid] < target) { 13 | // mid 的左边也一定小于 target,下一轮搜索的区间是 [mid + 1..right] 14 | left = mid + 1; 15 | } else { 16 | right = mid; 17 | } 18 | } 19 | if (nums[left] == target) { 20 | return left; 21 | } 22 | return -1; 23 | } 24 | } -------------------------------------------------------------------------------- /02-Binary-Search/Type-1/0704-binary-search/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | // 不建议的写法 4 | 5 | public int search(int[] nums, int target) { 6 | int len = nums.length; 7 | if (len == 0) { 8 | return -1; 9 | } 10 | int left = 0; 11 | int right = len - 1; 12 | while (left + 1 < right) { 13 | int mid = (left + right) >>> 1; 14 | if (nums[mid] < target) { 15 | left = mid; 16 | } else { 17 | right = mid; 18 | } 19 | } 20 | if (nums[left] == target) { 21 | return left; 22 | } 23 | if (nums[right] == target) { 24 | return right; 25 | } 26 | return -1; 27 | } 28 | } -------------------------------------------------------------------------------- /02-Binary-Search/Type-1/0744-find-smallest-letter-greater-than-target/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public char nextGreatestLetter(char[] letters, char target) { 4 | int len = letters.length; 5 | if (target >= letters[len - 1]) { 6 | return letters[0]; 7 | } 8 | 9 | int left = 0; 10 | int right = len - 1; 11 | while (left < right) { 12 | int mid = left + (right - left) / 2; 13 | if (letters[mid] <= target) { 14 | // 下一轮搜索的区间是:[mid + 1, right] 15 | left = mid + 1; 16 | } else { 17 | right = mid; 18 | } 19 | } 20 | return letters[left]; 21 | } 22 | } -------------------------------------------------------------------------------- /02-Binary-Search/Type-2/0287-find-the-duplicate-number/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 原地哈希(不符合题目要求) 4 | 5 | public int findDuplicate(int[] nums) { 6 | int len = nums.length; 7 | for (int i = 0; i < len; i++) { 8 | while (nums[i] != i + 1) { 9 | if (nums[i] == nums[nums[i] - 1]) { 10 | return nums[i]; 11 | } 12 | swap(nums, i, nums[i] - 1); 13 | } 14 | } 15 | // 数组中没有重复的整数,测试用例错误 16 | return 0; 17 | } 18 | 19 | private void swap(int[] nums, int index1, int index2) { 20 | int temp = nums[index1]; 21 | nums[index1] = nums[index2]; 22 | nums[index2] = temp; 23 | } 24 | } -------------------------------------------------------------------------------- /02-Binary-Search/Type-2/0287-find-the-duplicate-number/src/Solution4.java: -------------------------------------------------------------------------------- 1 | public class Solution4 { 2 | 3 | public int findDuplicate(int[] nums) { 4 | int len = nums.length; 5 | int left = 1; 6 | // 注意这里的边界 7 | int right = len - 1; 8 | while (left < right) { 9 | int mid = left + (right - left + 1) / 2; 10 | int count = 0; 11 | for (int num : nums) { 12 | if (num < mid) { 13 | count++; 14 | } 15 | } 16 | // 容易出错,需要仔细分析 17 | if (count < mid) { 18 | left = mid; 19 | } else { 20 | right = mid - 1; 21 | } 22 | } 23 | return left; 24 | } 25 | } -------------------------------------------------------------------------------- /02-Binary-Search/Type-3/0852-peak-index-in-a-mountain-array/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int peakIndexInMountainArray(int[] arr) { 4 | int len = arr.length; 5 | int left = 1; 6 | int right = len - 2; 7 | while (left < right) { 8 | int mid = (left + right) / 2; 9 | if (arr[mid] < arr[mid + 1]) { 10 | // 下一轮搜索区间在 [mid + 1..right] 11 | left = mid + 1; 12 | } else { 13 | right = mid; 14 | } 15 | } 16 | return left; 17 | } 18 | } -------------------------------------------------------------------------------- /03-Basic-Sorting/BubbleSort/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 冒泡排序(基础版):超时 4 | 5 | public int[] sortArray(int[] nums) { 6 | int len = nums.length; 7 | for (int i = len - 1; i >= 0; i--) { 8 | // 只要发生一次交换,就必须进行下一轮比较, 9 | for (int j = 0; j < i; j++) { 10 | if (nums[j] > nums[j + 1]) { 11 | swap(nums, j, j + 1); 12 | } 13 | } 14 | } 15 | return nums; 16 | } 17 | 18 | private void swap(int[] nums, int index1, int index2) { 19 | int temp = nums[index1]; 20 | nums[index1] = nums[index2]; 21 | nums[index2] = temp; 22 | } 23 | } -------------------------------------------------------------------------------- /03-Basic-Sorting/Insertion-Sort-Visualization/README.md: -------------------------------------------------------------------------------- 1 | # 插入排序可视化 2 | 3 | 参考了刘宇波老师的 GitHub 代码仓库: [《看得见的算法》](https://github.com/liuyubobobo/Play-with-Algorithm-Visualization)。 4 | 5 | 程序入口文件是 `AlgoVisualizer`。 -------------------------------------------------------------------------------- /03-Basic-Sorting/Insertion-Sort/src/ISortAlgorithm.java: -------------------------------------------------------------------------------- 1 | public interface ISortAlgorithm { 2 | 3 | /** 4 | * 排序算法的名字 5 | * 6 | * @return 7 | */ 8 | String getName(); 9 | 10 | /** 11 | * 排序算法的实现 12 | * 13 | * @param arr 待排序数组 14 | */ 15 | void sort(int[] arr); 16 | } -------------------------------------------------------------------------------- /03-Basic-Sorting/Insertion-Sort/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int[] sortArray(int[] nums) { 4 | int len = nums.length; 5 | for (int i = 1; i < len; i++) { 6 | for (int j = i; j > 0; j--) { 7 | // 注意:前面的数严格大于后面的数才交换 8 | if (nums[j - 1] > nums[j]) { 9 | swap(nums, j, j - 1); 10 | } else { 11 | break; 12 | } 13 | } 14 | } 15 | return nums; 16 | } 17 | 18 | private void swap(int[] arr, int index1, int index2) { 19 | int temp = arr[index1]; 20 | arr[index1] = arr[index2]; 21 | arr[index2] = temp; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /03-Basic-Sorting/Insertion-Sort/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | // 「力扣」第 912 题:排序数组 4 | // 链接:https://leetcode-cn.com/problems/sort-an-array/ 5 | 6 | public int[] sortArray(int[] nums) { 7 | int len = nums.length; 8 | // 循环不变量:将 nums[i] 插入到区间 [0..i) 使之成为有序数组 9 | for (int i = 1; i < len; i++) { 10 | // 先暂存这个元素,然后之前数值严格小于 temp 的所有元素逐个后移 11 | int temp = nums[i]; 12 | int j = i; 13 | // 注意边界 j > 0 14 | while (j > 0 && nums[j - 1] > temp) { 15 | nums[j] = nums[j - 1]; 16 | j--; 17 | } 18 | 19 | // 最后这一步容易忽略 20 | nums[j] = temp; 21 | } 22 | return nums; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /03-Basic-Sorting/Selection-Sort-Visualization/README.md: -------------------------------------------------------------------------------- 1 | # 选择排序可视化 2 | 3 | 参考了刘宇波老师的 GitHub 代码仓库: [《看得见的算法》](https://github.com/liuyubobobo/Play-with-Algorithm-Visualization)。 4 | 5 | 程序主入口在 `AlgoVisualizer` 。 -------------------------------------------------------------------------------- /03-Basic-Sorting/Sorting-Algorithms/src/cn/leetcode/examples/IGenerateArrayStrategy.java: -------------------------------------------------------------------------------- 1 | package cn.leetcode.examples; 2 | 3 | /** 4 | * 生成用于验证排序算法测试用例的接口,采用策略设计模式 5 | * 6 | * @author liweiwei1419 7 | * @date 2019/9/8 3:58 AM 8 | */ 9 | public interface IGenerateArrayStrategy { 10 | 11 | /** 12 | * @return 测试用例特征的文字描述 13 | */ 14 | String getFeature(); 15 | 16 | /** 17 | * @return 测试用例数组 18 | */ 19 | int[] generateArray(); 20 | 21 | /** 22 | * @return 测试用例数组的长度 23 | */ 24 | int getLen(); 25 | 26 | /** 27 | * @return 测试用例数组的最小值,默认值是 1 28 | */ 29 | int getMin(); 30 | 31 | /** 32 | * @return 测试用例数组的最大值,默认值是数组的长度 33 | */ 34 | int getMax(); 35 | } -------------------------------------------------------------------------------- /03-Basic-Sorting/Sorting-Algorithms/src/cn/leetcode/sorting/ISortingAlgorithm.java: -------------------------------------------------------------------------------- 1 | package cn.leetcode.sorting; 2 | 3 | /** 4 | * @author liweiwei1419 5 | * @date 2019/9/6 5:01 AM 6 | */ 7 | public interface ISortingAlgorithm { 8 | 9 | void sort(int[] arr); 10 | } -------------------------------------------------------------------------------- /03-Loop-Invariant/0026-remove-duplicates-from-sorted-array/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int removeDuplicates(int[] nums) { 4 | int len = nums.length; 5 | if (len < 2) { 6 | return len; 7 | } 8 | // 循环不变量:nums[0..j)是移除重复元素以后的数组 9 | int j = 1; 10 | for (int i = 1; i < len; i++) { 11 | if (nums[i] != nums[j - 1]) { 12 | // 注意顺序:先更新值,再递增下标 13 | nums[j] = nums[i]; 14 | j++; 15 | } 16 | } 17 | return j; 18 | } 19 | } -------------------------------------------------------------------------------- /03-Loop-Invariant/0026-remove-duplicates-from-sorted-array/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public int removeDuplicates(int[] nums) { 4 | int len = nums.length; 5 | if (len < 2) { 6 | return len; 7 | } 8 | // 循环不变量:nums[0..j] 是移除重复元素以后的数组 9 | int j = 0; 10 | for (int i = 1; i < len; i++) { 11 | if (nums[i] != nums[j]) { 12 | j++; 13 | nums[j] = nums[i]; 14 | } 15 | } 16 | return j + 1; 17 | } 18 | } -------------------------------------------------------------------------------- /03-Loop-Invariant/0027-remove-element/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int removeElement(int[] nums, int val) { 4 | int len = nums.length; 5 | if (len == 0) { 6 | return len; 7 | } 8 | 9 | // 循环不变量:nums[0..j) != val 10 | // j 指向了下一个要赋值的元素的位置 11 | int j = 0; 12 | for (int i = 0; i < len; i++) { 13 | if (nums[i] != val) { 14 | nums[j] = nums[i]; 15 | j++; 16 | } 17 | } 18 | return j; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /03-Loop-Invariant/0080-remove-duplicates-from-sorted-array-ii/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int removeDuplicates(int[] nums) { 4 | int len = nums.length; 5 | if (len < 2){ 6 | return len; 7 | } 8 | 9 | // 循环不变量:nums[0..j) 是有序的,并且相同元素最多保留 2 次 10 | // j 指向下一个要赋值的元素的位置 11 | int j = 2; 12 | for (int i = 2; i < len; i++) { 13 | if (nums[i] != nums[j - 2]){ 14 | nums[j] = nums[i]; 15 | j++; 16 | } 17 | } 18 | return j; 19 | } 20 | } -------------------------------------------------------------------------------- /03-Loop-Invariant/0080-remove-duplicates-from-sorted-array-ii/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public int removeDuplicates(int[] nums) { 4 | int len = nums.length; 5 | if (len < 2){ 6 | return len; 7 | } 8 | 9 | // 循环不变量:nums[0..j] 是有序的,并且相同元素最多保留 2 次 10 | // j 已经赋值过的元素的最后一个位置 11 | int j = 1; 12 | for (int i = 2; i < len; i++) { 13 | if (nums[i] != nums[j - 1]){ 14 | j++; 15 | nums[j] = nums[i]; 16 | } 17 | } 18 | return j + 1; 19 | } 20 | } -------------------------------------------------------------------------------- /03-Loop-Invariant/0283-move-zeroes/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public void moveZeroes(int[] nums) { 4 | int len = nums.length; 5 | 6 | // 循环不变量:nums[0..j) !=0, nums[j..i) = 0 7 | // j 指向了下一个要赋值的元素的位置 8 | int j = 0; 9 | for (int i = 0; i < len; i++) { 10 | if (nums[i] != 0) { 11 | nums[j] = nums[i]; 12 | j++; 13 | } 14 | } 15 | 16 | for (int i = j; i < len; i++) { 17 | nums[i] = 0; 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /04-Merge-Sort/0088-merge-sorted-array/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | public void merge(int[] nums1, int m, int[] nums2, int n) { 4 | int len = m + n; 5 | int r1 = m - 1; 6 | int r2 = n - 1; 7 | for (int k = len - 1; k >= 0; k--) { 8 | if (r1 == -1) { 9 | nums1[k] = nums2[r2]; 10 | r2--; 11 | } else if (r2 == -1) { 12 | nums1[k] = nums1[r1]; 13 | r1--; 14 | } else if (nums1[r1] >= nums2[r2]) { 15 | nums1[k] = nums1[r1]; 16 | r1--; 17 | } else { 18 | nums1[k] = nums2[r2]; 19 | r2--; 20 | } 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /04-Merge-Sort/Merge-Sort/src/ISortAlgorithm.java: -------------------------------------------------------------------------------- 1 | public interface ISortAlgorithm { 2 | 3 | /** 4 | * 排序算法的名字 5 | * 6 | * @return 7 | */ 8 | String getName(); 9 | 10 | /** 11 | * 排序算法的实现 12 | * 13 | * @param arr 待排序数组 14 | */ 15 | void sort(int[] arr); 16 | } 17 | -------------------------------------------------------------------------------- /04-Quick-Sort/04-Quick-Sort/src/ISortAlgorithm.java: -------------------------------------------------------------------------------- 1 | public interface ISortAlgorithm { 2 | 3 | /** 4 | * 排序算法的名字 5 | * 6 | * @return 7 | */ 8 | String getName(); 9 | 10 | /** 11 | * 排序算法的实现 12 | * 13 | * @param arr 待排序数组 14 | */ 15 | void sort(int[] arr); 16 | } 17 | -------------------------------------------------------------------------------- /05-Non-comparative-Sorting/CountingSort/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | // 计数排序(非稳定) 4 | 5 | private static final int OFFSET = 50000; 6 | 7 | public int[] sortArray(int[] nums) { 8 | int len = nums.length; 9 | int size = 10_0000; 10 | 11 | // 计数数组 12 | int[] count = new int[size]; 13 | count[0] = 0; 14 | // 计算计数数组 15 | for (int num : nums) { 16 | count[num + OFFSET]++; 17 | } 18 | 19 | int index = 0; 20 | for (int i = 0; i < size; i++) { 21 | for (int j = 0; j < count[i]; j++) { 22 | nums[index] = i - OFFSET; 23 | index++; 24 | } 25 | } 26 | return nums; 27 | } 28 | } -------------------------------------------------------------------------------- /06-1-Sliding-Window/1-Basic/0076-minimum-window-substring/out/production/0076-minimum-window-substring/META-INF/0076-minimum-window-substring.kotlin_module: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /06-1-Sliding-Window/2-Advance/0643-maximum-average-subarray-i/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 滑动窗口(固定长度的滑动窗口) 4 | 5 | public double findMaxAverage(int[] nums, int k) { 6 | int len = nums.length; 7 | // 因为题目限制了 k <= len,因此不用做特判 8 | int windowSum = 0; 9 | for (int i = 0; i < k; i++) { 10 | windowSum += nums[i]; 11 | } 12 | int res = windowSum; 13 | 14 | // 边界问题 15 | // [left, right) 符合题意 16 | for (int right = k; right < len; right++) { 17 | // 加上一个数再减去一个数 18 | windowSum = windowSum + nums[right] - nums[right - k]; 19 | res = Math.max(res, windowSum); 20 | } 21 | return (double) res / k; 22 | } 23 | } -------------------------------------------------------------------------------- /06-two-pointers/1-Basic/0009-palindrome-number/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public boolean isPalindrome(int x) { 4 | // 如果 x < 0 直接就可以判断不是回文数 5 | if (x < 0) { 6 | return false; 7 | } 8 | return x == reverse(x); 9 | } 10 | 11 | private int reverse(int x) { 12 | int reverse = 0; 13 | while (x != 0) { 14 | reverse = reverse * 10 + x % 10; 15 | x /= 10; 16 | } 17 | return reverse; 18 | } 19 | } -------------------------------------------------------------------------------- /06-two-pointers/1-Basic/0009-palindrome-number/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public boolean isPalindrome(int x) { 4 | int origin = x; 5 | int res = 0; 6 | // 每次得到的余数 7 | int y; 8 | while (x > 0) { 9 | // 得到个位数 10 | y = x % 10; 11 | x = x / 10; 12 | res = res * 10 + y; 13 | } 14 | return res == origin; 15 | } 16 | } -------------------------------------------------------------------------------- /06-two-pointers/1-Basic/0011-container-with-most-water/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 暴力解法,时间复杂度太高,我们应该使用指针对撞的方法 4 | 5 | public int maxArea(int[] height) { 6 | int len = height.length; 7 | if (len < 2) { 8 | return 0; 9 | } 10 | int res = 0; 11 | for (int i = 0; i < len - 1; i++) { 12 | for (int j = i + 1; j < len; j++) { 13 | res = Math.max(res, Math.min(height[i], height[j]) * (j - i)); 14 | } 15 | } 16 | return res; 17 | } 18 | } -------------------------------------------------------------------------------- /06-two-pointers/1-Basic/0011-container-with-most-water/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | public int maxArea(int[] height) { 4 | int len = height.length; 5 | if (len < 2) { 6 | return 0; 7 | } 8 | 9 | int left = 0; 10 | int right = len - 1; 11 | 12 | int res = 0; 13 | while (left < right) { 14 | int minHeight = Math.min(height[left], height[right]); 15 | res = Math.max(res, minHeight * (right - left)); 16 | 17 | if (height[left] == minHeight) { 18 | left++; 19 | } else { 20 | right--; 21 | } 22 | } 23 | return res; 24 | } 25 | } -------------------------------------------------------------------------------- /06-two-pointers/1-Basic/0026-remove-duplicates-from-sorted-array/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int removeDuplicates(int[] nums) { 4 | int len = nums.length; 5 | if (len < 2) { 6 | return len; 7 | } 8 | 9 | // nums[0..j) 有序,且元素唯一 10 | // j 表示下一个需要覆盖的元素的下标 11 | int j = 1; 12 | for (int i = 1; i < len; i++) { 13 | if (nums[i] != nums[j - 1]){ 14 | nums[j] = nums[i]; 15 | j++; 16 | } 17 | } 18 | return j; 19 | } 20 | } -------------------------------------------------------------------------------- /06-two-pointers/1-Basic/0151-reverse-words-in-a-string/src/Solution2.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.Collections; 3 | 4 | public class Solution2 { 5 | 6 | public String reverseWords(String s) { 7 | String[] words = s.trim().split("\\s+"); 8 | Collections.reverse(Arrays.asList(words)); 9 | return String.join(" ", words); 10 | } 11 | } -------------------------------------------------------------------------------- /06-two-pointers/1-Basic/0167-two-sum-ii-input-array-is-sorted/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int[] twoSum(int[] numbers, int target) { 4 | int len = numbers.length; 5 | int left = 0; 6 | int right = len - 1; 7 | 8 | while (left < right) { 9 | int sum = numbers[left] + numbers[right]; 10 | if (sum == target) { 11 | return new int[]{left + 1, right + 1}; 12 | } else if (sum > target) { 13 | right--; 14 | } else { 15 | left++; 16 | } 17 | } 18 | return new int[]{-1, -1}; 19 | } 20 | } -------------------------------------------------------------------------------- /06-two-pointers/1-Basic/0344-reverse-string/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public String reverseString(char[] s) { 4 | int len = s.length; 5 | if (len < 2) { 6 | return new String(s); 7 | } 8 | 9 | int left = 0; 10 | int right = len - 1; 11 | while (left < right) { 12 | swap(s, left, right); 13 | left++; 14 | right--; 15 | } 16 | return String.valueOf(s); 17 | } 18 | 19 | private void swap(char[] arr, int index1, int index2) { 20 | char temp = arr[index1]; 21 | arr[index1] = arr[index2]; 22 | arr[index2] = temp; 23 | } 24 | } -------------------------------------------------------------------------------- /06-two-pointers/1-Basic/0344-reverse-string/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public String reverseString(char[] s) { 4 | int len = s.length; 5 | 6 | int left = 0; 7 | int right = len - 1; 8 | while (left < right) { 9 | swap(s, left, right); 10 | left++; 11 | right--; 12 | } 13 | return new String(s); 14 | } 15 | 16 | private void swap(char[] s, int index1, int index2) { 17 | char temp = s[index1]; 18 | s[index1] = s[index2]; 19 | s[index2] = temp; 20 | } 21 | } -------------------------------------------------------------------------------- /06-two-pointers/1-Basic/0977-squares-of-a-sorted-array/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | public class Solution { 4 | 5 | public int[] sortedSquares(int[] A) { 6 | int len = A.length; 7 | int[] res = new int[len]; 8 | for (int i = 0; i < len; i++) { 9 | res[i] = A[i] * A[i]; 10 | } 11 | Arrays.sort(res); 12 | return res; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /06-two-pointers/1-Basic/0977-squares-of-a-sorted-array/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public int[] sortedSquares(int[] A) { 4 | int len = A.length; 5 | int[] res = new int[len]; 6 | 7 | // 从后向前赋值,平方值最大的数只能出现在输入数组的头和尾 8 | int index = len - 1; 9 | int left = 0; 10 | int right = len - 1; 11 | while (left <= right) { 12 | if (A[left] * A[left] > A[right] * A[right]) { 13 | res[index] = A[left] * A[left]; 14 | left++; 15 | } else { 16 | res[index] = A[right] * A[right]; 17 | right--; 18 | } 19 | index--; 20 | } 21 | return res; 22 | } 23 | } -------------------------------------------------------------------------------- /06-two-pointers/2-Importance/0088-merge-sorted-array/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public void merge(int[] nums1, int m, int[] nums2, int n) { 4 | int i = m - 1; 5 | int j = n - 1; 6 | 7 | int end = m + n - 1; 8 | for (int k = end; k >= 0; k--) { 9 | if (i < 0) { 10 | nums1[k] = nums2[j]; 11 | j--; 12 | } else if (j < 0) { 13 | break; 14 | } else if (nums1[i] >= nums2[j]) { 15 | nums1[k] = nums1[i]; 16 | i--; 17 | } else { 18 | nums1[k] = nums2[j]; 19 | j--; 20 | } 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /06-two-pointers/3-Advance/0334-increasing-triplet-subsequence/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 思想:双指针 4 | // 空间复杂度:O(N) 5 | // 时间复杂度:O(1) 6 | 7 | public boolean increasingTriplet(int[] nums) { 8 | // 注意:两个都是小于等于 9 | int one = Integer.MAX_VALUE; 10 | int two = Integer.MAX_VALUE; 11 | for (int num : nums) { 12 | if (num <= one) { 13 | one = num; 14 | } else if (num <= two) { 15 | // 执行到这里一定有 num > one 16 | two = num; 17 | } else { 18 | // 执行到这里一定有 num > two > one 19 | return true; 20 | } 21 | } 22 | return false; 23 | } 24 | } -------------------------------------------------------------------------------- /06-two-pointers/3-Advance/0713-subarray-product-less-than-k/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 暴力解法:超时 4 | 5 | public int numSubarrayProductLessThanK(int[] nums, int k) { 6 | int len = nums.length; 7 | int count = 0; 8 | for (int left = 0; left < len; left++) { 9 | for (int right = left; right < len; right++) { 10 | int product = 1; 11 | for (int i = left; i <= right; i++) { 12 | product *= nums[i]; 13 | } 14 | // 注意:乘积可能越界 15 | if (product > 0 && product < k) { 16 | count++; 17 | } 18 | } 19 | } 20 | return count; 21 | } 22 | } -------------------------------------------------------------------------------- /06-two-pointers/3-Advance/0713-subarray-product-less-than-k/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | // 滑动窗口 4 | 5 | public int numSubarrayProductLessThanK(int[] nums, int k) { 6 | if (k <= 1) { 7 | return 0; 8 | } 9 | int len = nums.length; 10 | int left = 0; 11 | int count = 0; 12 | int product = 1; 13 | for (int right = 0; right < len; right++) { 14 | product *= nums[right]; 15 | while (product >= k) { 16 | product /= nums[left]; 17 | left++; 18 | } 19 | count += (right - left + 1); 20 | } 21 | return count; 22 | } 23 | } -------------------------------------------------------------------------------- /06-two-pointers/3-Advance/0713-subarray-product-less-than-k/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | public int numSubarrayProductLessThanK(int[] nums, int k) { 4 | if (k <= 1) { 5 | return 0; 6 | } 7 | int len = nums.length; 8 | int left = 0; 9 | int right = 0; 10 | int count = 0; 11 | int product = 1; 12 | // 循环不变量:nums[left..right] 里所有元素的乘积严格小于 k 13 | while (right < len) { 14 | product *= nums[right]; 15 | while (product >= k) { 16 | product /= nums[left]; 17 | left++; 18 | } 19 | count += (right - left + 1); 20 | right++; 21 | } 22 | return count; 23 | } 24 | } -------------------------------------------------------------------------------- /06-two-pointers/3-Advance/0713-subarray-product-less-than-k/src/Solution4.java: -------------------------------------------------------------------------------- 1 | public class Solution4 { 2 | 3 | public int numSubarrayProductLessThanK(int[] nums, int k) { 4 | // 特殊用例判断 5 | if (k <= 1) { 6 | return 0; 7 | } 8 | int len = nums.length; 9 | int left = 0; 10 | int right = 0; 11 | int res = 0; 12 | int product = 1; 13 | // 循环不变量:nums[left..right) 里所有元素的乘积严格小于 k 14 | while (right < len) { 15 | product *= nums[right]; 16 | right++; 17 | while (product >= k) { 18 | product /= nums[left]; 19 | left++; 20 | } 21 | res += (right - left); 22 | } 23 | return res; 24 | } 25 | } -------------------------------------------------------------------------------- /06-two-pointers/Python/0011-container-with-most-water(双指针).py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def maxArea(self, height: List[int]) -> int: 6 | size = len(height) 7 | if size < 2: 8 | return 0 9 | 10 | left = 0 11 | right = size - 1 12 | res = 0 13 | while left < right: 14 | min_h = min(height[left], height[right]) 15 | res = max(res, (right - left) * min_h) 16 | if min_h == height[left]: 17 | left += 1 18 | else: 19 | right -= 1 20 | return res -------------------------------------------------------------------------------- /06-two-pointers/Python/0011-container-with-most-water(暴力求解).py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | 6 | # 该解法超时 7 | 8 | def maxArea(self, height: List[int]) -> int: 9 | size = len(height) 10 | if size < 2: 11 | return 0 12 | 13 | res = 0 14 | for left in range(0, size - 1): 15 | for right in range(left + 1, size): 16 | res = max(res, min(height[left], height[right]) * (right - left)) 17 | return res 18 | 19 | 20 | if __name__ == '__main__': 21 | height = [1, 8, 6, 2, 5, 4, 8, 3, 7] 22 | solution = Solution() 23 | result = solution.maxArea(height) 24 | print(result) 25 | -------------------------------------------------------------------------------- /06-two-pointers/Python/0015-3sum(暴力解法).py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | 6 | # 暴力解法:去重复是一个问题 7 | 8 | def threeSum(self, nums: List[int]) -> List[List[int]]: 9 | size = len(nums) 10 | res = [] 11 | if size < 3: 12 | return res 13 | 14 | for i in range(size - 2): 15 | for j in range(i + 1, size - 1): 16 | for k in range(j + 1, size): 17 | if nums[i] + nums[j] + nums[k] == 0: 18 | res.append([nums[i], nums[j], nums[k]]) 19 | 20 | return res 21 | 22 | 23 | if __name__ == '__main__': 24 | nums = [-2, 0, 0, 2, 2] 25 | solution = Solution() 26 | result = solution.threeSum(nums) 27 | print(result) 28 | -------------------------------------------------------------------------------- /06-two-pointers/Python/0080-remove-duplicates-from-sorted-array-ii.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def removeDuplicates(self, nums: List[int]) -> int: 6 | size = len(nums) 7 | if size <= 2: 8 | return size 9 | # counter 表示下一个要覆盖的下标 10 | counter = 2 11 | # 下标为 0 和 1 的数一定会被保留,因此遍历从下标 2 开始 12 | for i in range(2, size): 13 | if nums[i] != nums[counter - 2]: 14 | nums[counter] = nums[i] 15 | counter += 1 16 | return counter -------------------------------------------------------------------------------- /06-two-pointers/Python/0125-valid-palindrome-2.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def isPalindrome(self, s: str) -> bool: 3 | left = 0 4 | right = len(s) - 1 5 | while left < right: 6 | # 只考虑字母和数字字符 7 | while left < right and not s[left].isalnum(): 8 | left += 1 9 | while left < right and not s[right].isalnum(): 10 | right -= 1 11 | if s[left].lower() != s[right].lower(): 12 | return False 13 | left += 1 14 | right -= 1 15 | return True 16 | -------------------------------------------------------------------------------- /06-two-pointers/Python/0125-valid-palindrome.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def isPalindrome(self, s: str) -> bool: 3 | left = 0 4 | right = len(s) - 1 5 | while left < right: 6 | # 只考虑字母和数字字符 7 | if not s[left].isalnum(): 8 | left += 1 9 | continue 10 | if not s[right].isalnum(): 11 | right -= 1 12 | continue 13 | if s[left].lower() != s[right].lower(): 14 | return False 15 | left += 1 16 | right -= 1 17 | return True 18 | -------------------------------------------------------------------------------- /06-two-pointers/Python/0167-two-sum-ii-input-array-is-sorted(双指针).py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def twoSum(self, numbers: List[int], target: int) -> List[int]: 6 | size = len(numbers) 7 | if size < 2: 8 | return [] 9 | left = 0 10 | right = size - 1 11 | while left < right: 12 | if numbers[left] + numbers[right] == target: 13 | return [left + 1, right + 1] 14 | elif numbers[left] + numbers[right] < target: 15 | left += 1 16 | else: 17 | right -= 1 18 | return [] -------------------------------------------------------------------------------- /06-two-pointers/Python/0334-increasing-triplet-subsequence.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def increasingTriplet(self, nums: List[int]) -> bool: 6 | one = float('inf') 7 | two = float('inf') 8 | 9 | for num in nums: 10 | if num <= one: 11 | one = num 12 | elif num <= two: 13 | two = num 14 | else: 15 | return True 16 | return False -------------------------------------------------------------------------------- /06-two-pointers/Python/0344-reverse-string(双指针).py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def reverseString(self, s: List[str]) -> None: 6 | """ 7 | Do not return anything, modify s in-place instead. 8 | """ 9 | size = len(s) 10 | if size < 2: 11 | return 12 | 13 | left = 0 14 | right = size - 1 15 | while left < right: 16 | s[left], s[right] = s[right], s[left] 17 | left += 1 18 | right -= 1 19 | -------------------------------------------------------------------------------- /06-two-pointers/Python/0345-reverse-vowels-of-a-string(双指针).py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def reverseVowels(self, s: str) -> str: 3 | vowels = {'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'} 4 | s = list(s) 5 | left = 0 6 | right = len(s) - 1 7 | while left < right: 8 | if s[left] not in vowels: 9 | left += 1 10 | elif s[right] not in vowels: 11 | right -= 1 12 | else: 13 | s[left], s[right] = s[right], s[left] 14 | left += 1 15 | right -= 1 16 | return ''.join(s) 17 | -------------------------------------------------------------------------------- /07-Linked-List/1-Basic/0002-add-two-numbers/src/ListNode.java: -------------------------------------------------------------------------------- 1 | public class ListNode { 2 | 3 | int val; 4 | ListNode next; 5 | 6 | ListNode(int x) { 7 | val = x; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /07-Linked-List/1-Basic/0024-swap-nodes-in-pairs/src/ListNode.java: -------------------------------------------------------------------------------- 1 | public class ListNode { 2 | 3 | int val; 4 | ListNode next; 5 | 6 | ListNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /07-Linked-List/1-Basic/0024-swap-nodes-in-pairs/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | // 方法二:递归 4 | 5 | public ListNode swapPairs(ListNode head) { 6 | // 特判 7 | if (head == null || head.next == null) { 8 | return head; 9 | } 10 | 11 | // 没有必要设置虚拟头结点了 12 | ListNode p1 = head; 13 | ListNode p2 = head.next; 14 | 15 | p1.next = swapPairs(p2.next); 16 | p2.next = p1; 17 | return p2; 18 | } 19 | } -------------------------------------------------------------------------------- /07-Linked-List/1-Basic/0025-reverse-nodes-in-k-group/src/ListNode.java: -------------------------------------------------------------------------------- 1 | public class ListNode { 2 | 3 | int val; 4 | ListNode next; 5 | 6 | ListNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /07-Linked-List/1-Basic/0061-rotate-list/src/ListNode.java: -------------------------------------------------------------------------------- 1 | public class ListNode { 2 | 3 | int val; 4 | ListNode next; 5 | 6 | ListNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /07-Linked-List/1-Basic/0082-remove-duplicates-from-sorted-list-ii/src/ListNode.java: -------------------------------------------------------------------------------- 1 | public class ListNode { 2 | 3 | int val; 4 | ListNode next; 5 | 6 | ListNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /07-Linked-List/1-Basic/0083-remove-duplicates-from-sorted-list/src/ListNode.java: -------------------------------------------------------------------------------- 1 | public class ListNode { 2 | 3 | int val; 4 | ListNode next; 5 | 6 | ListNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /07-Linked-List/1-Basic/0083-remove-duplicates-from-sorted-list/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public ListNode deleteDuplicates(ListNode head) { 4 | if (head == null || head.next == null) { 5 | return head; 6 | } 7 | ListNode cur = head; 8 | while (cur.next != null) { 9 | if (cur.next.val == cur.val) { 10 | ListNode deleteNode = cur.next; 11 | cur.next = deleteNode.next; 12 | deleteNode.next = null; 13 | } else { 14 | cur = cur.next; 15 | } 16 | } 17 | return head; 18 | } 19 | } -------------------------------------------------------------------------------- /07-Linked-List/1-Basic/0086-partition-list/src/ListNode.java: -------------------------------------------------------------------------------- 1 | public class ListNode { 2 | 3 | int val; 4 | ListNode next; 5 | 6 | ListNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /07-Linked-List/1-Basic/0203-remove-linked-list-elements/src/ListNode.java: -------------------------------------------------------------------------------- 1 | public class ListNode { 2 | 3 | int val; 4 | ListNode next; 5 | 6 | ListNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /07-Linked-List/1-Basic/0203-remove-linked-list-elements/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 穿针引线 4 | 5 | public ListNode removeElements(ListNode head, int val) { 6 | ListNode dummyNode = new ListNode(-1); 7 | dummyNode.next = head; 8 | ListNode cur = dummyNode; 9 | while (cur.next != null) { 10 | if (cur.next.val == val) { 11 | // 待删除的结点 12 | ListNode deleteNode = cur.next; 13 | cur.next = deleteNode.next; 14 | deleteNode.next = null; 15 | } else { 16 | cur = cur.next; 17 | } 18 | } 19 | return dummyNode.next; 20 | } 21 | } -------------------------------------------------------------------------------- /07-Linked-List/1-Basic/0203-remove-linked-list-elements/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | // 递归 4 | 5 | public ListNode removeElements(ListNode head, int val) { 6 | if (head == null) { 7 | return head; 8 | } 9 | // 假设小一个规模的问题已经解决 10 | head.next = removeElements(head.next, val); 11 | if (head.val == val) { 12 | return head.next; 13 | } else { 14 | return head; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /07-Linked-List/1-Basic/0206-reverse-linked-list/src/ListNode.java: -------------------------------------------------------------------------------- 1 | public class ListNode { 2 | int val; 3 | ListNode next; 4 | 5 | ListNode(int x) { 6 | val = x; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /07-Linked-List/1-Basic/0206-reverse-linked-list/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 方法一:穿针引线 4 | 5 | public ListNode reverseList(ListNode head) { 6 | // 特判 7 | if (head == null || head.next == null) { 8 | return head; 9 | } 10 | 11 | ListNode preNode = null; 12 | ListNode curNode = head; 13 | while (curNode != null) { 14 | ListNode nextNode = curNode.next; 15 | curNode.next = preNode; 16 | preNode = curNode; 17 | curNode = nextNode; 18 | } 19 | return preNode; 20 | } 21 | } -------------------------------------------------------------------------------- /07-Linked-List/1-Basic/0206-reverse-linked-list/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | // 方法二:递归 4 | 5 | public ListNode reverseList(ListNode head) { 6 | // 特判 7 | if (head == null || head.next == null) { 8 | return head; 9 | } 10 | 11 | ListNode nextNode = head.next; 12 | ListNode newNode = reverseList(nextNode); 13 | nextNode.next = head; 14 | // 这里不要忘记切断引用,否则会出现错误:Error - Found cycle in the ListNode 15 | head.next = null; 16 | return newNode; 17 | } 18 | } -------------------------------------------------------------------------------- /07-Linked-List/1-Basic/0234-palindrome-linked-list/src/ListNode.java: -------------------------------------------------------------------------------- 1 | public class ListNode { 2 | 3 | int val; 4 | ListNode next; 5 | 6 | ListNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /07-Linked-List/1-Basic/0237-delete-node-in-a-linked-list/src/ListNode.java: -------------------------------------------------------------------------------- 1 | public class ListNode { 2 | 3 | int val; 4 | ListNode next; 5 | 6 | ListNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /07-Linked-List/1-Basic/0237-delete-node-in-a-linked-list/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public void deleteNode(ListNode node) { 4 | // 第 1 步:把待删除结点的下一结点的值赋值给自己 5 | ListNode nextNode = node.next; 6 | node.val = nextNode.val; 7 | 8 | // 第 2 步:删除下一个结点 9 | node.next = nextNode.next; 10 | nextNode.next = null; 11 | } 12 | } -------------------------------------------------------------------------------- /07-Linked-List/1-Basic/0328-odd-even-linked-list/src/ListNode.java: -------------------------------------------------------------------------------- 1 | public class ListNode { 2 | 3 | int val; 4 | ListNode next; 5 | 6 | ListNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /07-Linked-List/1-Basic/0445-add-two-numbers-ii/src/ListNode.java: -------------------------------------------------------------------------------- 1 | public class ListNode { 2 | 3 | int val; 4 | ListNode next; 5 | 6 | ListNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /07-Linked-List/1-Basic/0876-middle-of-the-linked-list/src/ListNode.java: -------------------------------------------------------------------------------- 1 | public class ListNode { 2 | 3 | int val; 4 | ListNode next; 5 | 6 | ListNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /07-Linked-List/1-Basic/0876-middle-of-the-linked-list/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public ListNode middleNode(ListNode head) { 4 | if (head == null) { 5 | return null; 6 | } 7 | ListNode slow = head; 8 | ListNode fast = head; 9 | 10 | while (fast != null && fast.next != null) { 11 | slow = slow.next; 12 | fast = fast.next.next; 13 | } 14 | return slow; 15 | } 16 | } -------------------------------------------------------------------------------- /07-Linked-List/2-Importance/0019-remove-nth-node-from-end-of-list/src/ListNode.java: -------------------------------------------------------------------------------- 1 | public class ListNode { 2 | 3 | int val; 4 | ListNode next; 5 | 6 | ListNode(int x) { 7 | val = x; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /07-Linked-List/2-Importance/0021-merge-two-sorted-lists/src/ListNode.java: -------------------------------------------------------------------------------- 1 | public class ListNode { 2 | 3 | int val; 4 | ListNode next; 5 | 6 | ListNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /07-Linked-List/2-Importance/0023-merge-k-sorted-lists/src/ListNode.java: -------------------------------------------------------------------------------- 1 | public class ListNode { 2 | 3 | int val; 4 | ListNode next; 5 | 6 | ListNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /07-Linked-List/2-Importance/0092-reverse-linked-list-ii/src/ListNode.java: -------------------------------------------------------------------------------- 1 | public class ListNode { 2 | 3 | int val; 4 | ListNode next; 5 | 6 | ListNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /07-Linked-List/2-Importance/0092-reverse-linked-list-ii/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public ListNode reverseBetween(ListNode head, int m, int n) { 4 | // 设置 dummyNode 是这一类问题的一般做法 5 | ListNode dummyNode = new ListNode(-1); 6 | dummyNode.next = head; 7 | ListNode pre = dummyNode; 8 | for (int i = 0; i < m - 1; i++) { 9 | pre = pre.next; 10 | } 11 | ListNode cur = pre.next; 12 | ListNode next; 13 | for (int i = 0; i < n - m; i++) { 14 | next = cur.next; 15 | cur.next = next.next; 16 | next.next = pre.next; 17 | pre.next = next; 18 | } 19 | return dummyNode.next; 20 | } 21 | } -------------------------------------------------------------------------------- /07-Linked-List/2-Importance/0141-linked-list-cycle/src/ListNode.java: -------------------------------------------------------------------------------- 1 | public class ListNode { 2 | 3 | int val; 4 | ListNode next; 5 | ListNode(int x) { 6 | val = x; 7 | next = null; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /07-Linked-List/2-Importance/0141-linked-list-cycle/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public boolean hasCycle(ListNode head) { 4 | // 特判 5 | if (head == null || head.next == null) { 6 | return false; 7 | } 8 | 9 | ListNode curNode = head; 10 | int count = 0; 11 | while (curNode != null) { 12 | curNode = curNode.next; 13 | // 在遍历了 10000 个结点以后,都没有遍历完,认为链表中有环 14 | // 这是一种「取巧」的做法 15 | if (count == 10000){ 16 | return true; 17 | } 18 | count++; 19 | } 20 | return false; 21 | } 22 | } -------------------------------------------------------------------------------- /07-Linked-List/2-Importance/0141-linked-list-cycle/src/Solution2.java: -------------------------------------------------------------------------------- 1 | import java.util.HashSet; 2 | import java.util.Set; 3 | 4 | public class Solution2 { 5 | 6 | public boolean hasCycle(ListNode head) { 7 | // 特判 8 | if (head == null || head.next == null) { 9 | return false; 10 | } 11 | 12 | ListNode curNode = head; 13 | Set hashSet = new HashSet<>(); 14 | while (curNode != null) { 15 | if (hashSet.contains(curNode)) { 16 | return true; 17 | } 18 | hashSet.add(curNode); 19 | curNode = curNode.next; 20 | } 21 | return false; 22 | } 23 | } -------------------------------------------------------------------------------- /07-Linked-List/2-Importance/0141-linked-list-cycle/src/Solution3.java: -------------------------------------------------------------------------------- 1 | import java.util.HashSet; 2 | import java.util.Set; 3 | 4 | public class Solution3 { 5 | 6 | public boolean hasCycle(ListNode head) { 7 | // 特判 8 | if (head == null || head.next == null) { 9 | return false; 10 | } 11 | 12 | Set hashSet = new HashSet<>(); 13 | 14 | ListNode curNode = head; 15 | while (curNode != null) { 16 | if (hashSet.contains(curNode)) { 17 | return true; 18 | } else { 19 | hashSet.add(curNode); 20 | } 21 | curNode = curNode.next; 22 | } 23 | return false; 24 | } 25 | } -------------------------------------------------------------------------------- /07-Linked-List/2-Importance/0141-linked-list-cycle/src/Solution4.java: -------------------------------------------------------------------------------- 1 | public class Solution4 { 2 | 3 | // 快慢指针 4 | 5 | public boolean hasCycle(ListNode head) { 6 | // 特判 7 | if (head == null || head.next == null) { 8 | return false; 9 | } 10 | 11 | ListNode slow = head; 12 | ListNode fast = head; 13 | 14 | // 慢指针一次走一步、快指针一次走两步 15 | // 注意:快指针可以走的条件 fast != null && fast.next != null 16 | 17 | while (fast != null && fast.next != null) { 18 | slow = slow.next; 19 | fast = fast.next.next; 20 | if (slow == fast) { 21 | return true; 22 | } 23 | } 24 | return false; 25 | } 26 | } -------------------------------------------------------------------------------- /07-Linked-List/2-Importance/0142-linked-list-cycle-ii/src/ListNode.java: -------------------------------------------------------------------------------- 1 | public class ListNode { 2 | 3 | int val; 4 | ListNode next; 5 | 6 | ListNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /07-Linked-List/2-Importance/0143-reorder-list/src/ListNode.java: -------------------------------------------------------------------------------- 1 | public class ListNode { 2 | 3 | int val; 4 | ListNode next; 5 | 6 | ListNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /07-Linked-List/2-Importance/0147-insertion-sort-list/src/ListNode.java: -------------------------------------------------------------------------------- 1 | public class ListNode { 2 | 3 | int val; 4 | ListNode next; 5 | 6 | ListNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /07-Linked-List/2-Importance/0148-sort-list/src/ListNode.java: -------------------------------------------------------------------------------- 1 | public class ListNode { 2 | 3 | int val; 4 | ListNode next; 5 | 6 | ListNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /07-Linked-List/2-Importance/0160-intersection-of-two-linked-lists/src/ListNode.java: -------------------------------------------------------------------------------- 1 | public class ListNode { 2 | 3 | int val; 4 | ListNode next; 5 | 6 | ListNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /07-Linked-List/2-Importance/0160-intersection-of-two-linked-lists/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public ListNode getIntersectionNode(ListNode headA, ListNode headB) { 4 | if (headA == null || headB == null) { 5 | return null; 6 | } 7 | 8 | ListNode head1 = headA; 9 | ListNode head2 = headB; 10 | 11 | while (head1 != head2) { 12 | if (head1 != null) { 13 | head1 = head1.next; 14 | } else { 15 | head1 = headB; 16 | } 17 | 18 | if (head2 != null) { 19 | head2 = head2.next; 20 | } else { 21 | head2 = headA; 22 | } 23 | } 24 | return head1; 25 | } 26 | } -------------------------------------------------------------------------------- /07-Linked-List/3-Advance/1290-convert-binary-number-in-a-linked-list-to-integer/src/ListNode.java: -------------------------------------------------------------------------------- 1 | public class ListNode { 2 | 3 | int val; 4 | ListNode next; 5 | 6 | ListNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /07-Linked-List/3-Advance/1290-convert-binary-number-in-a-linked-list-to-integer/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayDeque; 2 | import java.util.Deque; 3 | 4 | public class Solution { 5 | 6 | public int getDecimalValue(ListNode head) { 7 | ListNode curNode = head; 8 | Deque stack = new ArrayDeque<>(); 9 | while (curNode != null) { 10 | stack.addLast(curNode.val); 11 | curNode = curNode.next; 12 | } 13 | 14 | int res = 0; 15 | int base = 1; 16 | while (!stack.isEmpty()) { 17 | res += base * stack.removeLast(); 18 | base *= 2; 19 | } 20 | return res; 21 | } 22 | } -------------------------------------------------------------------------------- /07-Linked-List/3-Advance/1290-convert-binary-number-in-a-linked-list-to-integer/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public int getDecimalValue(ListNode head) { 4 | ListNode curNode = head; 5 | int res = 0; 6 | 7 | while (curNode != null) { 8 | res = res * 2 + curNode.val; 9 | curNode = curNode.next; 10 | } 11 | return res; 12 | } 13 | } -------------------------------------------------------------------------------- /07-Linked-List/补充/0023-merge-k-sorted-lists/src/Solution6.java: -------------------------------------------------------------------------------- 1 | public class Solution6 { 2 | 3 | public int reversePairs(int[] nums) { 4 | int count = 0; 5 | int len = nums.length; 6 | for (int i = 0; i < len - 1; i++) { 7 | for (int j = i + 1; j < len; j++) { 8 | if (nums[i] > nums[j]) { 9 | count++; 10 | } 11 | } 12 | } 13 | return count; 14 | } 15 | 16 | public static void main(String[] args) { 17 | Solution6 solution6 = new Solution6(); 18 | int[] nums = new int[]{8, 7, 6, 5, 4, 3, 2, 1}; 19 | int res = solution6.reversePairs(nums); 20 | System.out.println(res); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /07-Linked-List/补充/0024-swap-nodes-in-pairs/src/Solution4.java: -------------------------------------------------------------------------------- 1 | public class Solution4 { 2 | 3 | public ListNode swapPairs(ListNode head) { 4 | ListNode dummy = new ListNode(-1); 5 | dummy.next = head; 6 | 7 | ListNode newHead = dummy; 8 | while (head != null && head.next != null) { 9 | ListNode first = head; 10 | ListNode second = head.next; 11 | 12 | newHead.next = second; 13 | first.next = second.next; 14 | second.next = first; 15 | 16 | newHead = first; 17 | head = first.next; 18 | } 19 | return dummy.next; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /07-Linked-List/补充/0141-linked-list-cycle/src/Solution2.java: -------------------------------------------------------------------------------- 1 | import java.util.HashSet; 2 | import java.util.Set; 3 | 4 | public class Solution2 { 5 | 6 | public boolean hasCycle(ListNode head) { 7 | // 特判 8 | if (head == null || head.next == null) { 9 | return false; 10 | } 11 | 12 | Set hashSet = new HashSet<>(); 13 | 14 | ListNode curNode = head; 15 | while (curNode != null) { 16 | if (hashSet.contains(curNode)) { 17 | return true; 18 | } else { 19 | hashSet.add(curNode); 20 | } 21 | curNode = curNode.next; 22 | } 23 | return false; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /07-Linked-List/补充/0141-linked-list-cycle/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | // 并查集的思路 4 | 5 | public boolean hasCycle(ListNode head) { 6 | // 特判 7 | if (head == null || head.next == null) { 8 | return false; 9 | } 10 | 11 | ListNode dummyNode = new ListNode(-1); 12 | 13 | ListNode curNode = head; 14 | while (curNode != null) { 15 | ListNode nextNode = curNode.next; 16 | 17 | if (curNode != dummyNode) { 18 | curNode.next = dummyNode; 19 | } else { 20 | return true; 21 | } 22 | 23 | curNode = nextNode; 24 | } 25 | return false; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /07-Linked-List/补充/0141-linked-list-cycle/src/Solution4.java: -------------------------------------------------------------------------------- 1 | public class Solution4 { 2 | 3 | public boolean hasCycle(ListNode head) { 4 | // 特判 5 | if (head == null || head.next == null) { 6 | return false; 7 | } 8 | 9 | ListNode curNode = head; 10 | int count = 0; 11 | while (curNode != null) { 12 | curNode = curNode.next; 13 | if (count == 10000){ 14 | return true; 15 | } 16 | count++; 17 | } 18 | return false; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /07-Linked-List/补充/0206-reverse-linked-list-2/src/ListNode.java: -------------------------------------------------------------------------------- 1 | public class ListNode { 2 | 3 | int val; 4 | ListNode next; 5 | 6 | ListNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /07-Linked-List/补充/0206-reverse-linked-list-2/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public ListNode reverseList(ListNode head) { 4 | if (head == null || head.next == null) { 5 | return head; 6 | } 7 | 8 | ListNode preNode = null; 9 | ListNode curNode = head; 10 | while (curNode != null) { 11 | ListNode nextNode = curNode.next; 12 | curNode.next = preNode; 13 | preNode = curNode; 14 | curNode = nextNode; 15 | } 16 | return preNode; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /07-Linked-List/补充/0206-reverse-linked-list-2/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public ListNode reverseList(ListNode head) { 4 | if (head == null || head.next == null) { 5 | return head; 6 | } 7 | 8 | ListNode nextNode = head.next; 9 | ListNode newHead = reverseList(nextNode); 10 | nextNode.next = head; 11 | head.next = null; 12 | return newHead; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /07-Linked-List/补充/0328-odd-even-linked-list/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public ListNode oddEvenList(ListNode head) { 4 | if (head == null || head.next == null) { 5 | return head; 6 | } 7 | ListNode oddHead = head; 8 | ListNode evenHead = head.next; 9 | 10 | ListNode oddCur = oddHead; 11 | ListNode evenCur = evenHead; 12 | // 执行循环的条件不能写错 13 | while (evenCur != null && evenCur.next != null) { 14 | oddCur.next = oddCur.next.next; 15 | evenCur.next = evenCur.next.next; 16 | 17 | oddCur = oddCur.next; 18 | evenCur = evenCur.next; 19 | } 20 | oddCur.next = evenHead; 21 | return oddHead; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /07-Linked-List/补充/05-Array/src/Main.java: -------------------------------------------------------------------------------- 1 | public class Main { 2 | 3 | public static void main(String[] args) { 4 | Array arr = new Array<>(); 5 | Student s1 = new Student("student1",90); 6 | Student s2 = new Student("student2",80); 7 | Student s3 = new Student("student3",70); 8 | arr.add(0,s1); 9 | arr.add(1,s2); 10 | arr.add(2,s3); 11 | System.out.println(arr); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /07-Linked-List/补充/05-Array/src/Student.java: -------------------------------------------------------------------------------- 1 | public class Student { 2 | 3 | private String name; 4 | private int score; 5 | 6 | 7 | public Student(String studentName, int studentScore) { 8 | this.name = studentName; 9 | this.score = studentScore; 10 | } 11 | 12 | 13 | @Override 14 | public String toString() { 15 | return String.format("Student(name: %s, score: %d)", name, score); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /07-Linked-List/补充/1290-convert-binary-number-in-a-linked-list-to-integer/src/Solution2.java: -------------------------------------------------------------------------------- 1 | 2 | public class Solution2 { 3 | 4 | public int getDecimalValue(ListNode head) { 5 | ListNode curNode = head; 6 | int res = 0; 7 | 8 | while (curNode != null) { 9 | res = res * 2 + curNode.val; 10 | curNode = curNode.next; 11 | } 12 | return res; 13 | } 14 | 15 | public static void main(String[] args) { 16 | // int[] arr = {1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}; 17 | int[] arr = {1, 0, 1}; 18 | ListNode head = new ListNode(arr); 19 | Solution2 solution2 = new Solution2(); 20 | int res = solution2.getDecimalValue(head); 21 | System.out.println(res); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /08-1-Stack/1-Basic/0155-min-stack/src/Main.java: -------------------------------------------------------------------------------- 1 | public class Main { 2 | 3 | public static void main(String[] args) { 4 | int a = Integer.MAX_VALUE; 5 | System.out.println(Integer.toBinaryString(a)); 6 | System.out.println(a); 7 | System.out.println(a + 1); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /08-1-Stack/1-Basic/0155-min-stack/src/Main2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 2019/7/15 10:56 PM 4 | */ 5 | public class Main2 { 6 | 7 | public static void main(String[] args) { 8 | int a = Integer.MAX_VALUE; 9 | int b = Integer.MAX_VALUE - 2; 10 | System.out.println(a + b); 11 | 12 | System.out.println(a + (b - a) / 2); 13 | // 一定要用无符号右移 14 | System.out.println((a + b) >>> 1); 15 | System.out.println((a + b) >> 1); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /08-1-Stack/2-Advance/1111-maximum-nesting-depth-of-two-valid-parentheses-strings/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 贪心算法 4 | 5 | public int[] maxDepthAfterSplit(String seq) { 6 | int len = seq.length(); 7 | int[] res = new int[len]; 8 | 9 | char[] charArray = seq.toCharArray(); 10 | for (int i = 1; i < len; i++) { 11 | if (charArray[i] == charArray[i - 1]) { 12 | res[i] = 1 - res[i - 1]; 13 | } else { 14 | res[i] = res[i - 1]; 15 | } 16 | } 17 | return res; 18 | } 19 | } -------------------------------------------------------------------------------- /08-1-Stack/2-Advance/1111-maximum-nesting-depth-of-two-valid-parentheses-strings/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | // 栈 4 | 5 | public int[] maxDepthAfterSplit(String seq) { 6 | int len = seq.length(); 7 | char[] charArray = seq.toCharArray(); 8 | int[] res = new int[len]; 9 | 10 | int left = 0; 11 | for (int i = 0; i < len; i++) { 12 | if (charArray[i] == '(') { 13 | left++; 14 | res[i] = left % 2; 15 | } else { 16 | res[i] = left % 2; 17 | left--; 18 | } 19 | } 20 | return res; 21 | } 22 | } -------------------------------------------------------------------------------- /08-1-Stack/2-Advance/1111-maximum-nesting-depth-of-two-valid-parentheses-strings/src/Solution5.java: -------------------------------------------------------------------------------- 1 | public class Solution5 { 2 | 3 | public int[] maxDepthAfterSplit(String seq) { 4 | int len = seq.length(); 5 | int[] res = new int[len]; 6 | int depth = 0; 7 | 8 | char[] charArray = seq.toCharArray(); 9 | for (int i = 0; i < len; i++) { 10 | // 遍历到左括号,连续括号个数加 1, 11 | if (charArray[i] == '(') { 12 | depth++; 13 | res[i] = depth % 2; 14 | } else { 15 | // 遍历到右括号,与当前栈顶左括号分在一组,因此先取模,再 -- 16 | // 这一步希望大家多体会,很有意思 17 | res[i] = depth % 2; 18 | depth--; 19 | } 20 | } 21 | return res; 22 | } 23 | } -------------------------------------------------------------------------------- /08-1-Stack/3-Monotonic-Stack/0402-remove-k-digits/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | public int factorial(int n) { 4 | if (n == 1) { 5 | return 1; 6 | } 7 | return n * factorial(n - 1); 8 | } 9 | 10 | public static void main(String[] args) { 11 | Solution3 solution3 = new Solution3(); 12 | int n = 5; 13 | int res = solution3.factorial(n); 14 | System.out.println(res); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /08-1-Stack/3-Monotonic-Stack/0402-remove-k-digits/src/Solution4.java: -------------------------------------------------------------------------------- 1 | public class Solution4 { 2 | 3 | public int factorial(int n) { 4 | int res = 1; 5 | for (int i = 2; i <= n; i++) { 6 | res *= i; 7 | } 8 | return res; 9 | } 10 | 11 | public static void main(String[] args) { 12 | Solution4 solution4 = new Solution4(); 13 | int n = 5; 14 | int res = solution4.factorial(n); 15 | System.out.println(res); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /08-1-Stack/3-Monotonic-Stack/0402-remove-k-digits/src/Solution5.java: -------------------------------------------------------------------------------- 1 | public class Solution5 { 2 | 3 | /** 4 | * @param n 5 | * @param res 递归函数上一层的结果,由于求的是阶乘一开始需要传入 1 6 | * @return 7 | */ 8 | public int factorial(int n, int res) { 9 | if (n == 1) { 10 | return res; 11 | } 12 | return factorial(n - 1, n * res); 13 | } 14 | 15 | public static void main(String[] args) { 16 | Solution5 solution4 = new Solution5(); 17 | int n = 5; 18 | int res = solution4.factorial(n, 1); 19 | System.out.println(res); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /08-1-Stack/3-Monotonic-Stack/0402-remove-k-digits/src/Solution6.java: -------------------------------------------------------------------------------- 1 | public class Solution6 { 2 | 3 | public int factorial(int n) { 4 | if (n == 1) { 5 | return 1; 6 | } 7 | int res = factorial(n - 1); 8 | // 在这里还能够执行一次操作,实现「分治思想」里「合并」的逻辑 9 | return n * res; 10 | } 11 | 12 | public static void main(String[] args) { 13 | Solution6 solution3 = new Solution6(); 14 | int n = 5; 15 | int res = solution3.factorial(n); 16 | System.out.println(res); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /08-1-Stack/3-Monotonic-Stack/0739-daily-temperatures/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 暴力解法 4 | 5 | public int[] dailyTemperatures(int[] temperatures) { 6 | int len = temperatures.length; 7 | if (len < 2) { 8 | return new int[len]; 9 | } 10 | 11 | int[] res = new int[len]; 12 | res[len - 1] = 0; 13 | for (int i = 0; i < len - 1; i++) { 14 | int curVal = temperatures[i]; 15 | for (int j = i + 1; j < len; j++) { 16 | if (temperatures[j] > curVal) { 17 | res[i] = j - i; 18 | break; 19 | } 20 | } 21 | } 22 | return res; 23 | } 24 | } -------------------------------------------------------------------------------- /08-1-Stack/数组实现的栈/07-ArrayStack/src/Stack.java: -------------------------------------------------------------------------------- 1 | public interface Stack { 2 | void push(E e); 3 | E pop(); 4 | E peek(); 5 | int getSize(); 6 | boolean isEmpty(); 7 | } 8 | -------------------------------------------------------------------------------- /08-1-Stack/补充/0394-decode-string/out/production/0394-decode-string/META-INF/0394-decode-string.kotlin_module: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /08-1-Stack/补充/1028-recover-a-tree-from-preorder-traversal(栈、难题)/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /08-2-Queue/1-Basic/0621-task-scheduler/out/production/0621-task-scheduler/META-INF/0621-task-scheduler.kotlin_module: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /08-2-Queue/1-Basic/0621-task-scheduler/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | public int leastInterval(char[] tasks, int n) { 4 | int[] freq = new int[26]; 5 | // 最多的执行次数 6 | int maxExec = 0; 7 | for (char task : tasks) { 8 | freq[task - 'A']++; 9 | maxExec = Math.max(maxExec, freq[task - 'A']); 10 | } 11 | 12 | // 具有最多执行次数的任务数量 13 | int maxCount = 0; 14 | for (int i = 0; i < 26; i++) { 15 | int value = freq[i]; 16 | if (value == maxExec) { 17 | maxCount++; 18 | } 19 | } 20 | return Math.max((maxExec - 1) * (n + 1) + maxCount, tasks.length); 21 | } 22 | } -------------------------------------------------------------------------------- /08-2-Queue/1-Basic/0933-number-of-recent-calls/src/RecentCounter.java: -------------------------------------------------------------------------------- 1 | import java.util.LinkedList; 2 | import java.util.Queue; 3 | 4 | public class RecentCounter { 5 | 6 | private Queue queue; 7 | 8 | public RecentCounter() { 9 | queue = new LinkedList<>(); 10 | } 11 | 12 | public int ping(int t) { 13 | while (!queue.isEmpty() && t - queue.peek() > 3000) { 14 | queue.poll(); 15 | } 16 | queue.offer(t); 17 | return queue.size(); 18 | } 19 | } -------------------------------------------------------------------------------- /08-2-Queue/1-Basic/1315-sum-of-nodes-with-even-valued-grandparent/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | private int res = 0; 4 | 5 | public int sumEvenGrandparent(TreeNode root) { 6 | dfs(root, null); 7 | return res; 8 | } 9 | 10 | private void dfs(TreeNode root, TreeNode parent) { 11 | if (root == null) { 12 | return; 13 | } 14 | 15 | if (parent != null && parent.val % 2 == 0) { 16 | if (root.left != null) { 17 | res += root.left.val; 18 | } 19 | if (root.right != null) { 20 | res += root.right.val; 21 | } 22 | } 23 | dfs(root.left, root); 24 | dfs(root.right, root); 25 | } 26 | } -------------------------------------------------------------------------------- /08-2-Queue/1-Basic/1315-sum-of-nodes-with-even-valued-grandparent/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /08-2-Queue/数组实现的循环队列/07-ArrayQueue/src/Queue.java: -------------------------------------------------------------------------------- 1 | public interface Queue { 2 | 3 | /** 4 | * 入队 5 | * @param e 6 | */ 7 | void enqueue(E e); 8 | 9 | /** 10 | * 出队 11 | * @return 12 | */ 13 | E dequeue(); 14 | 15 | /** 16 | * 看一看队首的元素 17 | * @return 18 | */ 19 | E getFront(); 20 | 21 | /** 22 | * 得到队列中的元素的个数 23 | * @return 24 | */ 25 | int getSize(); 26 | 27 | /** 28 | * 队列是否为空 29 | * @return 30 | */ 31 | boolean isEmpty(); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /09-Priority-Queue(Heap)/06-Heap/src/HeapSort2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 第 2 个版本的堆排序算法 3 | */ 4 | public class HeapSort2 implements ISortAlgorithm { 5 | 6 | @Override 7 | public String getName() { 8 | return "第 2 个版本的堆排序算法,传入数组入队,在逐个出队"; 9 | } 10 | 11 | 12 | @Override 13 | public void sort(int[] arr) { 14 | MaxHeap maxHeap = new MaxHeap(arr); 15 | int length = arr.length; 16 | for (int i = length - 1; i >= 0; i--) { 17 | arr[i] = maxHeap.extractMax(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /09-Priority-Queue(Heap)/06-Heap/src/ISortAlgorithm.java: -------------------------------------------------------------------------------- 1 | public interface ISortAlgorithm { 2 | 3 | /** 4 | * 排序算法的名字 5 | * 6 | * @return 7 | */ 8 | String getName(); 9 | 10 | /** 11 | * 排序算法的实现 12 | * 13 | * @param arr 待排序数组 14 | */ 15 | void sort(int[] arr); 16 | } 17 | -------------------------------------------------------------------------------- /09-Priority-Queue(Heap)/1-Basic/0703-kth-largest-element-in-a-stream/src/KthLargest.java: -------------------------------------------------------------------------------- 1 | import java.util.PriorityQueue; 2 | 3 | public class KthLargest { 4 | 5 | private PriorityQueue minHeap; 6 | private int k; 7 | 8 | public KthLargest(int k, int[] nums) { 9 | this.minHeap = new PriorityQueue<>(k); 10 | this.k = k; 11 | for (int num : nums) { 12 | add(num); 13 | } 14 | } 15 | 16 | public int add(int val) { 17 | minHeap.offer(val); 18 | if (minHeap.size() > k) { 19 | minHeap.poll(); 20 | } 21 | return minHeap.peek(); 22 | } 23 | } -------------------------------------------------------------------------------- /09-Priority-Queue(Heap)/2-Importance/0023-merge-k-sorted-lists-using-our-priorityqueue/out/production/0023-merge-k-sorted-lists/META-INF/0023-merge-k-sorted-lists.kotlin_module: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /09-Priority-Queue(Heap)/2-Importance/0023-merge-k-sorted-lists/src/ListNode.java: -------------------------------------------------------------------------------- 1 | public class ListNode { 2 | 3 | int val; 4 | ListNode next; 5 | 6 | ListNode() { 7 | } 8 | 9 | ListNode(int val) { 10 | this.val = val; 11 | } 12 | 13 | ListNode(int val, ListNode next) { 14 | this.val = val; 15 | this.next = next; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /09-Priority-Queue(Heap)/3-Advance/1296-divide-array-in-sets-of-k-consecutive-numbers/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | public boolean isPossibleDivide(int[] nums, int k) { 4 | int len = nums.length; 5 | if ((len % k) != 0) { 6 | return false; 7 | } 8 | 9 | int size = len / k; 10 | int[] cnt = new int[k]; 11 | 12 | for (int i = 0; i < len; i++) { 13 | cnt[nums[i] % k]++; 14 | } 15 | 16 | for (int i = 0; i < k; i++) { 17 | if (cnt[i] != size) { 18 | return false; 19 | } 20 | } 21 | return true; 22 | } 23 | } -------------------------------------------------------------------------------- /09-Priority-Queue(Heap)/自己实现的堆/Custom-Heap/src/IndexMinHeap.java: -------------------------------------------------------------------------------- 1 | public class IndexMinHeap { 2 | } 3 | -------------------------------------------------------------------------------- /09-Priority-Queue(Heap)/自己实现的堆/Custom-Heap/src/Queue.java: -------------------------------------------------------------------------------- 1 | public interface Queue { 2 | 3 | /** 4 | * 队列是否为空 5 | * 6 | * @return 7 | */ 8 | boolean isEmpty(); 9 | 10 | /** 11 | * @return 队列中元素的个数 12 | */ 13 | int size(); 14 | 15 | /** 16 | * 向队列添加一个元素 17 | * 18 | * @param item 19 | */ 20 | void offer(int item); 21 | 22 | 23 | /** 24 | * 将一个元素出队 25 | * 26 | * @return 27 | */ 28 | int poll(); 29 | 30 | /** 31 | * 返回队首元素 32 | * 33 | * @return 34 | */ 35 | int peek(); 36 | 37 | 38 | /** 39 | * 将当前队首元素替换成为 item 40 | * 41 | * @param item 42 | */ 43 | void replace(int item); 44 | } 45 | -------------------------------------------------------------------------------- /09-Priority-Queue(Heap)/自己实现的堆/PriorityQueue/src/Queue.java: -------------------------------------------------------------------------------- 1 | public interface Queue { 2 | 3 | /** 4 | * 队列是否为空 5 | * 6 | * @return 7 | */ 8 | boolean isEmpty(); 9 | 10 | /** 11 | * 返回队列中元素的个数 12 | * 13 | * @return 14 | */ 15 | int size(); 16 | 17 | /** 18 | * 向队列添加一个元素 19 | * 20 | * @param x 21 | */ 22 | void offer(int x); 23 | 24 | /** 25 | * 将一个元素出队 26 | * 27 | * @return 28 | */ 29 | int poll(); 30 | 31 | /** 32 | * 返回队首元素 33 | * 34 | * @return 35 | */ 36 | int peek(); 37 | } 38 | -------------------------------------------------------------------------------- /11-Binary-Search-Tree/1-Basic/0235-lowest-common-ancestor-of-a-binary-search-tree/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { 4 | if (root == null || root == p || root == q) { 5 | return root; 6 | } 7 | 8 | // 只在左边 9 | if (root.val > p.val && root.val > q.val) { 10 | return lowestCommonAncestor(root.left, p, q); 11 | } 12 | 13 | // 只在右边 14 | if (root.val < p.val && root.val < q.val) { 15 | return lowestCommonAncestor(root.right, p, q); 16 | } 17 | return root; 18 | } 19 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/1-Basic/0235-lowest-common-ancestor-of-a-binary-search-tree/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { 4 | if (p.val < root.val && q.val < root.val) { 5 | return lowestCommonAncestor(root.left, p, q); 6 | } else if (p.val > root.val && q.val > root.val) { 7 | return lowestCommonAncestor(root.right, p, q); 8 | } 9 | return root; 10 | } 11 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/1-Basic/0235-lowest-common-ancestor-of-a-binary-search-tree/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/1-Basic/0449-serialize-and-deserialize-bst/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/1-Basic/0450-delete-node-in-a-bst/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | int val; 3 | TreeNode left; 4 | TreeNode right; 5 | 6 | TreeNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/1-Basic/0700-search-in-a-binary-search-tree/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public TreeNode searchBST(TreeNode root, int val) { 4 | if (root == null) { 5 | return null; 6 | } 7 | 8 | if (root.val == val) { 9 | return root; 10 | } else if (val < root.val ) { 11 | return searchBST(root.left, val); 12 | } else { 13 | return searchBST(root.right, val); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/1-Basic/0700-search-in-a-binary-search-tree/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/1-Basic/0701-insert-into-a-binary-search-tree/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | /** 4 | * 记得要把新的子树的根结点返回回去 5 | * 6 | * @param root 7 | * @param val 8 | * @return 9 | */ 10 | public TreeNode insertIntoBST(TreeNode root, int val) { 11 | if (root == null) { 12 | return new TreeNode(val); 13 | } 14 | 15 | if (val < root.val) { 16 | root.left = insertIntoBST(root.left, val); 17 | } else { 18 | root.right = insertIntoBST(root.right, val); 19 | } 20 | return root; 21 | } 22 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/1-Basic/0701-insert-into-a-binary-search-tree/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode() { 8 | } 9 | 10 | TreeNode(int val) { 11 | this.val = val; 12 | } 13 | 14 | TreeNode(int val, TreeNode left, TreeNode right) { 15 | this.val = val; 16 | this.left = left; 17 | this.right = right; 18 | } 19 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/2-Importance/0094-binary-tree-inorder-traversal/src/Solution3.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.List; 3 | 4 | public class Solution3 { 5 | 6 | public List inorderTraversal(TreeNode root) { 7 | List res = new ArrayList<>(); 8 | dfs(root, res); 9 | return res; 10 | } 11 | 12 | private void dfs(TreeNode node, List res) { 13 | if (node == null) { 14 | return; 15 | } 16 | 17 | dfs(node.left, res); 18 | res.add(node.val); 19 | dfs(node.right, res); 20 | } 21 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/2-Importance/0094-binary-tree-inorder-traversal/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/2-Importance/0098-validate-binary-search-tree/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | private long last = Long.MIN_VALUE; 4 | 5 | public boolean isValidBST(TreeNode root) { 6 | if (root == null) { 7 | return true; 8 | } 9 | 10 | if (isValidBST(root.left)) { 11 | if (last < root.val) { 12 | last = root.val; 13 | return isValidBST(root.right); 14 | } 15 | } 16 | return false; 17 | } 18 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/2-Importance/0098-validate-binary-search-tree/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | public boolean isValidBST(TreeNode root) { 4 | if (root == null) { 5 | return true; 6 | } 7 | return dfs(root, null, null); 8 | } 9 | 10 | private boolean dfs(TreeNode node, Integer min, Integer max) { 11 | if (node == null) { 12 | return true; 13 | } 14 | if (min != null && node.val <= min) { 15 | return false; 16 | } 17 | if (max != null && node.val >= max) { 18 | return false; 19 | } 20 | return dfs(node.left, min, node.val) && dfs(node.right, node.val, max); 21 | } 22 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/2-Importance/0098-validate-binary-search-tree/src/Solution5.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayDeque; 2 | import java.util.Deque; 3 | 4 | public class Solution5 { 5 | 6 | public boolean isValidBST(TreeNode root) { 7 | Deque stack = new ArrayDeque<>(); 8 | double inorder = - Integer.MAX_VALUE; 9 | 10 | while (!stack.isEmpty() || root != null) { 11 | while (root != null) { 12 | stack.addLast(root); 13 | root = root.left; 14 | } 15 | root = stack.removeLast(); 16 | if (root.val <= inorder) { 17 | return false; 18 | } 19 | inorder = root.val; 20 | root = root.right; 21 | } 22 | return true; 23 | } 24 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/2-Importance/0098-validate-binary-search-tree/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/2-Importance/0230-kth-smallest-element-in-a-bst/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | private int res; 4 | private int count = 0; 5 | 6 | public int kthSmallest(TreeNode root, int k) { 7 | dfs(root, k); 8 | return res; 9 | } 10 | 11 | private void dfs(TreeNode node, int k) { 12 | // 先写递归终止条件 13 | if (node == null) { 14 | return; 15 | } 16 | 17 | dfs(node.left, k); 18 | 19 | // BST 的中序遍历,就在这里做操作 20 | count++; 21 | if (count == k) { 22 | res = node.val; 23 | // 可加可不加,加上提前终止是更好的做法 24 | return; 25 | } 26 | 27 | dfs(node.right, k); 28 | } 29 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/2-Importance/0230-kth-smallest-element-in-a-bst/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | private int res; 4 | 5 | // 使用中序遍历 6 | 7 | public int kthSmallest(TreeNode root, int k) { 8 | int[] kArr = {k}; 9 | inOrder(root, kArr); 10 | return res; 11 | } 12 | 13 | private void inOrder(TreeNode node, int[] k) { 14 | if (node == null) { 15 | return; 16 | } 17 | inOrder(node.left, k); 18 | k[0]--; 19 | if (k[0] == 0) { 20 | res = node.val; 21 | return; 22 | } 23 | inOrder(node.right, k); 24 | } 25 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/2-Importance/0230-kth-smallest-element-in-a-bst/src/Solution5.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.List; 3 | 4 | public class Solution5 { 5 | 6 | public int kthSmallest(TreeNode root, int k) { 7 | List res = new ArrayList<>(); 8 | dfs(root, res); 9 | return res.get(k - 1); 10 | } 11 | 12 | private void dfs(TreeNode node, List res) { 13 | if (node == null) { 14 | return; 15 | } 16 | dfs(node.left, res); 17 | res.add(node.val); 18 | dfs(node.right, res); 19 | } 20 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/2-Importance/0230-kth-smallest-element-in-a-bst/src/Solution6.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.List; 3 | 4 | public class Solution6 { 5 | 6 | private int k; 7 | 8 | public int kthSmallest(TreeNode root, int k) { 9 | List res = new ArrayList<>(); 10 | this.k = k; 11 | dfs(root, res); 12 | return res.get(k - 1); 13 | } 14 | 15 | private void dfs(TreeNode node, List res) { 16 | if (node == null) { 17 | return; 18 | } 19 | dfs(node.left, res); 20 | res.add(node.val); 21 | if (res.size() == k){ 22 | return; 23 | } 24 | dfs(node.right, res); 25 | } 26 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/2-Importance/0230-kth-smallest-element-in-a-bst/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | int val; 3 | TreeNode left; 4 | TreeNode right; 5 | 6 | TreeNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/3-Advance/0173-binary-search-tree-iterator/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/3-Advance/0538-convert-bst-to-greater-tree/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/3-Advance/0653-two-sum-iv-input-is-a-bst/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/3-Advance/0669-trim-a-binary-search-tree/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 这道题其实还蛮有意思的 4 | 5 | public TreeNode trimBST(TreeNode root, int L, int R) { 6 | if (root == null) { 7 | return null; 8 | } 9 | if (root.val >= L && root.val <= R) { 10 | root.left = trimBST(root.left, L, root.val); 11 | root.right = trimBST(root.right, root.val, R); 12 | return root; 13 | } 14 | if (root.val > R) { 15 | return trimBST(root.left, L, R); 16 | } 17 | return trimBST(root.right, L, R); 18 | } 19 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/3-Advance/0669-trim-a-binary-search-tree/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | // 和 Solution 是一样的,可能更好理解一些吧 4 | 5 | public TreeNode trimBST(TreeNode root, int L, int R) { 6 | if (root == null) { 7 | return null; 8 | } 9 | // 这一步如果不理解的话,可以画图帮助理解 10 | if (root.val < L) { 11 | return trimBST(root.right, L, R); 12 | } 13 | if (root.val > R) { 14 | return trimBST(root.left, L, R); 15 | } 16 | assert root.val >= L && root.val <= R; 17 | // 此时 root 一定会被保留 18 | root.left = trimBST(root.left, L, root.val); 19 | root.right = trimBST(root.right, root.val, R); 20 | return root; 21 | } 22 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/3-Advance/0669-trim-a-binary-search-tree/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/3-Advance/0783-minimum-distance-between-bst-nodes/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/3-Advance/1008-construct-binary-search-tree-from-preorder-traversal/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | // 889. Construct Binary Tree from Preorder and Postorder Traversal 4 | // 1028 就是更难点的题目了 5 | 6 | int i = 0; 7 | 8 | public TreeNode bstFromPreorder(int[] A) { 9 | return bstFromPreorder(A, Integer.MAX_VALUE); 10 | } 11 | 12 | public TreeNode bstFromPreorder(int[] A, int bound) { 13 | if (i == A.length || A[i] > bound) { 14 | return null; 15 | } 16 | 17 | // 后序遍历 18 | TreeNode root = new TreeNode(A[i]); 19 | i++; 20 | root.left = bstFromPreorder(A, root.val); 21 | root.right = bstFromPreorder(A, bound); 22 | return root; 23 | } 24 | } -------------------------------------------------------------------------------- /11-Binary-Search-Tree/3-Advance/1008-construct-binary-search-tree-from-preorder-traversal/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0100-same-tree/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 思路:分治思想、后序遍历 4 | 5 | public boolean isSameTree(TreeNode p, TreeNode q) { 6 | // 先处理最特殊的情况,都为空结点的时候 7 | if (p == null && q == null) { 8 | return true; 9 | } 10 | // 走到这里说明两个结点都同时不为空,那么其中之一为空,或者两个结点的值不相等的时候,返回 false 11 | if (p == null || q == null || p.val != q.val) { 12 | return false; 13 | } 14 | return isSameTree(p.left, q.left) && isSameTree(p.right, q.right); 15 | } 16 | } -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0100-same-tree/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | int val; 3 | TreeNode left; 4 | TreeNode right; 5 | 6 | TreeNode(int x) { 7 | val = x; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0101-symmetric-tree/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | int val; 3 | TreeNode left; 4 | TreeNode right; 5 | 6 | TreeNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0102-binary-tree-level-order-traversal/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | int val; 3 | TreeNode left; 4 | TreeNode right; 5 | 6 | TreeNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0103-binary-tree-zigzag-level-order-traversal/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | int val; 3 | TreeNode left; 4 | TreeNode right; 5 | 6 | TreeNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0104-maximum-depth-of-binary-tree/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 求一棵二叉树的最大深度,后序遍历 4 | 5 | public int maxDepth(TreeNode root) { 6 | if (root == null) { 7 | return 0; 8 | } 9 | 10 | int leftMaxDepth = maxDepth(root.left); 11 | int rightMaxDepth = maxDepth(root.right); 12 | return Math.max(leftMaxDepth, rightMaxDepth) + 1; 13 | } 14 | } -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0104-maximum-depth-of-binary-tree/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | private int res; 4 | 5 | public int maxDepth(TreeNode root) { 6 | maxDepth(root, 1); 7 | return res; 8 | } 9 | 10 | private void maxDepth(TreeNode root, int depth) { 11 | if (root == null) { 12 | return; 13 | } 14 | if (root.left == null && root.right == null) { 15 | res = Math.max(res, depth); 16 | } 17 | maxDepth(root.left, depth + 1); 18 | maxDepth(root.right, depth + 1); 19 | } 20 | } -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0104-maximum-depth-of-binary-tree/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0107-binary-tree-level-order-traversal-ii/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0108-convert-sorted-array-to-binary-search-tree/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0110-balanced-binary-tree/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public boolean isBalanced(TreeNode root) { 4 | if (root == null) { 5 | return true; 6 | } 7 | return dfs(root) != -1; 8 | } 9 | 10 | private int dfs(TreeNode root) { 11 | if (root == null) { 12 | return 0; 13 | } 14 | 15 | // 后序遍历 16 | int left = dfs(root.left); 17 | int right = dfs(root.right); 18 | 19 | if (left == -1 || right == -1 || Math.abs(left - right) > 1) { 20 | return -1; 21 | } 22 | return Math.max(left, right) + 1; 23 | } 24 | } -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0110-balanced-binary-tree/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | int val; 3 | TreeNode left; 4 | TreeNode right; 5 | 6 | TreeNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0111-minimum-depth-of-binary-tree/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int minDepth(TreeNode root) { 4 | if (root == null) { 5 | return 0; 6 | } 7 | // 这一步要特别注意,是一个很容易被忽略的情况 8 | if (root.left == null || root.right == null) { 9 | return Math.max(minDepth(root.left), minDepth(root.right)) + 1; 10 | } 11 | return Math.min(minDepth(root.left), minDepth(root.right)) + 1; 12 | } 13 | } -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0111-minimum-depth-of-binary-tree/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0112-path-sum/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 方法一:后序遍历 4 | 5 | public boolean hasPathSum(TreeNode root, int sum) { 6 | if (root == null) { 7 | return false; 8 | } 9 | if (root.left == null && root.right == null) { 10 | return sum == root.val; 11 | } 12 | boolean left = hasPathSum(root.left, sum - root.val); 13 | boolean right = hasPathSum(root.right, sum - root.val); 14 | return left || right; 15 | } 16 | } -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0112-path-sum/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0114-flatten-binary-tree-to-linked-list/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 能看得出是前序遍历,但是代码难写。 4 | 5 | private TreeNode parent; 6 | 7 | public void flatten(TreeNode root) { 8 | if (root == null) { 9 | return; 10 | } 11 | 12 | flatten(root.right); 13 | flatten(root.left); 14 | 15 | root.right = parent; 16 | root.left = null; 17 | 18 | // 暂存父亲节点 19 | parent = root; 20 | } 21 | } -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0114-flatten-binary-tree-to-linked-list/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | private TreeNode preNode; 4 | 5 | public void flatten(TreeNode root) { 6 | if (root == null) { 7 | return; 8 | } 9 | 10 | if (preNode != null) { 11 | // 让左连接都失效 12 | preNode.left = null; 13 | preNode.right = root; 14 | } 15 | 16 | preNode = root; 17 | 18 | // 这一点比较难想到 19 | TreeNode temp = root.right; 20 | 21 | flatten(root.left); 22 | flatten(temp); 23 | } 24 | } -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0114-flatten-binary-tree-to-linked-list/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0129-sum-root-to-leaf-numbers/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int sumNumbers(TreeNode root) { 4 | if (root == null) { 5 | return 0; 6 | } 7 | return dfs(root, 0); 8 | } 9 | 10 | private int dfs(TreeNode node, int preSum) { 11 | if (node == null) { 12 | return 0; 13 | } 14 | preSum = 10 * preSum + node.val; 15 | if (node.left == null && node.right == null) { 16 | return preSum; 17 | } 18 | return dfs(node.left, preSum) + dfs(node.right, preSum); 19 | } 20 | } -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0129-sum-root-to-leaf-numbers/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0144-binary-tree-preorder-traversal/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.List; 3 | 4 | public class Solution { 5 | 6 | public List preorderTraversal(TreeNode root) { 7 | List res = new ArrayList<>(); 8 | dfs(root,res); 9 | return res; 10 | } 11 | 12 | private void dfs(TreeNode treeNode, List res) { 13 | if (treeNode == null) { 14 | return; 15 | } 16 | res.add(treeNode.val); 17 | dfs(treeNode.left, res); 18 | dfs(treeNode.right, res); 19 | } 20 | } -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0144-binary-tree-preorder-traversal/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0145-binary-tree-postorder-traversal/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.List; 3 | 4 | public class Solution { 5 | 6 | public List postorderTraversal(TreeNode root) { 7 | List res = new ArrayList<>(); 8 | dfs(root, res); 9 | return res; 10 | } 11 | 12 | private void dfs(TreeNode node, List res) { 13 | if (node == null) { 14 | return; 15 | } 16 | dfs(node.left, res); 17 | dfs(node.right, res); 18 | res.add(node.val); 19 | } 20 | } -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0145-binary-tree-postorder-traversal/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | int val; 3 | TreeNode left; 4 | TreeNode right; 5 | 6 | TreeNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0173-binary-search-tree-iterator/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0199-binary-tree-right-side-view/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0257-binary-tree-paths/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0404-sum-of-left-leaves/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 后序遍历 4 | 5 | public int sumOfLeftLeaves(TreeNode root) { 6 | if (root == null) { 7 | return 0; 8 | } 9 | // 表明 root 是叶子结点 10 | if (root.left != null && root.left.left == null && root.left.right == null) { 11 | // 分治算法 12 | return root.left.val + sumOfLeftLeaves(root.right); 13 | } 14 | return sumOfLeftLeaves(root.left) + sumOfLeftLeaves(root.right); 15 | } 16 | } -------------------------------------------------------------------------------- /11-Binary-Tree/1-Basic/0404-sum-of-left-leaves/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Tree/2-Importance/0094-binary-tree-inorder-traversal/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.List; 3 | 4 | public class Solution { 5 | 6 | public List inorderTraversal(TreeNode root) { 7 | List res = new ArrayList<>(); 8 | 9 | dfs(root, res); 10 | return res; 11 | } 12 | 13 | private void dfs(TreeNode node, List res) { 14 | if (node == null) { 15 | return; 16 | } 17 | dfs(node.left, res); 18 | res.add(node.val); 19 | dfs(node.right, res); 20 | } 21 | } -------------------------------------------------------------------------------- /11-Binary-Tree/2-Importance/0094-binary-tree-inorder-traversal/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Tree/2-Importance/0098-validate-binary-search-tree/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | private long last = Long.MIN_VALUE; 4 | 5 | public boolean isValidBST(TreeNode root) { 6 | if (root == null) { 7 | return true; 8 | } 9 | 10 | if (isValidBST(root.left)) { 11 | if (last < root.val) { 12 | last = root.val; 13 | return isValidBST(root.right); 14 | } 15 | } 16 | return false; 17 | } 18 | } -------------------------------------------------------------------------------- /11-Binary-Tree/2-Importance/0098-validate-binary-search-tree/src/Solution4.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayDeque; 2 | import java.util.Deque; 3 | 4 | public class Solution4 { 5 | 6 | public boolean isValidBST(TreeNode root) { 7 | Deque stack = new ArrayDeque<>(); 8 | double inorder = - Double.MAX_VALUE; 9 | 10 | while (!stack.isEmpty() || root != null) { 11 | while (root != null) { 12 | stack.addLast(root); 13 | root = root.left; 14 | } 15 | root = stack.removeLast(); 16 | if (root.val <= inorder) { 17 | return false; 18 | } 19 | inorder = root.val; 20 | root = root.right; 21 | } 22 | return true; 23 | } 24 | } -------------------------------------------------------------------------------- /11-Binary-Tree/2-Importance/0098-validate-binary-search-tree/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Tree/2-Importance/0105-construct-binary-tree-from-preorder-and-inorder-traversal/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | int val; 3 | TreeNode left; 4 | TreeNode right; 5 | 6 | TreeNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /11-Binary-Tree/2-Importance/0106-construct-binary-tree-from-inorder-and-postorder-traversal/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Tree/2-Importance/0226-invert-binary-tree/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 使用前序遍历 4 | 5 | public TreeNode invertTree(TreeNode root) { 6 | if (root == null) { 7 | return null; 8 | } 9 | 10 | // 左子树和右子树交换,即使左右子树都空也不影响正确性 11 | TreeNode temp = root.left; 12 | root.left = root.right; 13 | root.right = temp; 14 | 15 | // 递归翻转左右子树 16 | invertTree(root.left); 17 | invertTree(root.right); 18 | return root; 19 | } 20 | } -------------------------------------------------------------------------------- /11-Binary-Tree/2-Importance/0226-invert-binary-tree/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | // 使用中序遍历 4 | 5 | public TreeNode invertTree(TreeNode root) { 6 | if (root == null) { 7 | return null; 8 | } 9 | 10 | invertTree(root.left); 11 | 12 | TreeNode temp = root.left; 13 | root.left = root.right; 14 | root.right = temp; 15 | 16 | // 注意:因为左右子树已经交换了,因此这里不能写 invertTree(root.right); 17 | // 即:这里的 root.left 就是交换之前的 root.right 18 | invertTree(root.left); 19 | return root; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /11-Binary-Tree/2-Importance/0226-invert-binary-tree/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | // 使用后序遍历 4 | 5 | public TreeNode invertTree(TreeNode root) { 6 | if (root == null) { 7 | return null; 8 | } 9 | 10 | invertTree(root.left); 11 | invertTree(root.right); 12 | 13 | TreeNode temp = root.left; 14 | root.left = root.right; 15 | root.right = temp; 16 | return root; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /11-Binary-Tree/2-Importance/0226-invert-binary-tree/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /11-Binary-Tree/2-Importance/0230-kth-smallest-element-in-a-bst/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.List; 3 | 4 | public class Solution { 5 | 6 | public int kthSmallest(TreeNode root, int k) { 7 | List res = new ArrayList<>(); 8 | dfs(root, res); 9 | return res.get(k - 1); 10 | } 11 | 12 | private void dfs(TreeNode node, List res) { 13 | if (node == null) { 14 | return; 15 | } 16 | dfs(node.left, res); 17 | res.add(node.val); 18 | dfs(node.right, res); 19 | } 20 | } -------------------------------------------------------------------------------- /11-Binary-Tree/2-Importance/0230-kth-smallest-element-in-a-bst/src/Solution2.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.List; 3 | 4 | public class Solution2 { 5 | 6 | private int k; 7 | 8 | public int kthSmallest(TreeNode root, int k) { 9 | List res = new ArrayList<>(); 10 | this.k = k; 11 | dfs(root, res); 12 | return res.get(k - 1); 13 | } 14 | 15 | private void dfs(TreeNode node, List res) { 16 | if (node == null) { 17 | return; 18 | } 19 | dfs(node.left, res); 20 | res.add(node.val); 21 | if (res.size() == k) { 22 | return; 23 | } 24 | dfs(node.right, res); 25 | } 26 | } -------------------------------------------------------------------------------- /11-Binary-Tree/2-Importance/0230-kth-smallest-element-in-a-bst/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | public int kthSmallest(TreeNode root, int k) { 4 | count = k; 5 | dfs(root); 6 | return res; 7 | } 8 | 9 | private int count = 0; 10 | private int res = 0; 11 | 12 | private void dfs(TreeNode node) { 13 | // 先写递归终止条件 14 | if (node == null) { 15 | // 什么都不做 16 | return; 17 | } 18 | 19 | dfs(node.left); 20 | 21 | count--; 22 | if (count == 0) { 23 | this.res = node.val; 24 | // 这里写不写 return 都行,最好加上 25 | return; 26 | } 27 | 28 | dfs(node.right); 29 | } 30 | } -------------------------------------------------------------------------------- /11-Binary-Tree/2-Importance/0230-kth-smallest-element-in-a-bst/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | int val; 3 | TreeNode left; 4 | TreeNode right; 5 | 6 | TreeNode() { 7 | } 8 | 9 | TreeNode(int val) { 10 | this.val = val; 11 | } 12 | 13 | TreeNode(int val, TreeNode left, TreeNode right) { 14 | this.val = val; 15 | this.left = left; 16 | this.right = right; 17 | } 18 | } -------------------------------------------------------------------------------- /11-Binary-Tree/2-Importance/0235-lowest-common-ancestor-of-a-binary-search-tree/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { 4 | if (root == null || root == p || root == q) { 5 | return root; 6 | } 7 | 8 | if (p.val < root.val && q.val < root.val) { 9 | return lowestCommonAncestor(root.left, p, q); 10 | } 11 | 12 | if (p.val > root.val && q.val > root.val) { 13 | return lowestCommonAncestor(root.right, p, q); 14 | } 15 | return root; 16 | } 17 | } -------------------------------------------------------------------------------- /11-Binary-Tree/2-Importance/0235-lowest-common-ancestor-of-a-binary-search-tree/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Tree/2-Importance/0236-lowest-common-ancestor-of-a-binary-tree/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { 4 | if (root == null || root == p || root == q) { 5 | return root; 6 | } 7 | 8 | // 后序遍历 9 | TreeNode left = lowestCommonAncestor(root.left, p, q); 10 | TreeNode right = lowestCommonAncestor(root.right, p, q); 11 | 12 | // 这一句特别重要,如果左边和右边都非空,把当前结点返回回去 13 | if (left != null && right != null) { 14 | return root; 15 | } 16 | 17 | // 下面的这种写法包含了 left 和 right 同时为空的情况 18 | if (left == null) { 19 | return right; 20 | } 21 | return left; 22 | } 23 | } -------------------------------------------------------------------------------- /11-Binary-Tree/2-Importance/0236-lowest-common-ancestor-of-a-binary-tree/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | int val; 3 | TreeNode left; 4 | TreeNode right; 5 | 6 | TreeNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /11-Binary-Tree/3-Advance/0222-count-complete-tree-nodes/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Tree/3-Advance/0437-path-sum-iii/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Tree/3-Advance/0515-find-largest-value-in-each-tree-row/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Tree/3-Advance/0652-find-duplicate-subtrees/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Tree/3-Advance/0951-flip-equivalent-binary-trees/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public boolean flipEquiv(TreeNode root1, TreeNode root2) { 4 | if (root1 == null && root2 == null) { 5 | return true; 6 | } 7 | // 走到这里是因为 root1 和 root2 至少有一样非空 8 | if (root1 == null || root2 == null || root1.val != root2.val) { 9 | return false; 10 | } 11 | return flipEquiv(root1.left, root2.right) && flipEquiv(root1.right, root2.left) || 12 | flipEquiv(root1.left, root2.left) && flipEquiv(root1.right, root2.right); 13 | } 14 | } -------------------------------------------------------------------------------- /11-Binary-Tree/3-Advance/0951-flip-equivalent-binary-trees/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Tree/3-Advance/0993-cousins-in-binary-tree/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Tree/3-Advance/1302-deepest-leaves-sum/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | int res = 0; 4 | int level = 0; 5 | 6 | public int deepestLeavesSum(TreeNode root) { 7 | dfs(root, 0); 8 | return res; 9 | } 10 | 11 | private void dfs(TreeNode cur, int l) { 12 | if (cur == null) { 13 | return; 14 | } 15 | if (cur.left == null && cur.right == null) { 16 | if (l == level) { 17 | res += cur.val; 18 | } else if (l > level) { 19 | res = cur.val; 20 | level = l; 21 | } 22 | } else { 23 | dfs(cur.left, l + 1); 24 | dfs(cur.right, l + 1); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /11-Binary-Tree/3-Advance/1302-deepest-leaves-sum/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /11-Binary-Tree/3-Advance/1305-all-elements-in-two-binary-search-trees/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.Collections; 3 | import java.util.List; 4 | 5 | 6 | public class Solution { 7 | 8 | public List getAllElements(TreeNode root1, TreeNode root2) { 9 | List res = new ArrayList<>(); 10 | dfs(root1, res); 11 | dfs(root2, res); 12 | 13 | Collections.sort(res); 14 | return res; 15 | } 16 | 17 | private void dfs(TreeNode node, List nums) { 18 | if (node == null) { 19 | return; 20 | } 21 | dfs(node.left, nums); 22 | nums.add(node.val); 23 | dfs(node.right, nums); 24 | } 25 | } -------------------------------------------------------------------------------- /11-Binary-Tree/3-Advance/1305-all-elements-in-two-binary-search-trees/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /12-Backtracking-And-DFS/Type-1-Basic/0078-subsets/src/Solution4.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.List; 3 | 4 | public class Solution4 { 5 | 6 | // 方法三:位运算 7 | 8 | public List> subsets(int[] nums) { 9 | int size = nums.length; 10 | int n = 1 << size; 11 | List> res = new ArrayList<>(); 12 | 13 | for (int i = 0; i < n; i++) { 14 | List cur = new ArrayList<>(); 15 | for (int j = 0; j < size; j++) { 16 | if (((i >> j) & 1) == 1) { 17 | cur.add(nums[j]); 18 | } 19 | } 20 | res.add(cur); 21 | } 22 | return res; 23 | } 24 | } -------------------------------------------------------------------------------- /12-Backtracking-And-DFS/Type-1-Basic/0090-subsets-ii/out/production/0090-subsets-ii/META-INF/0090-subsets-ii.kotlin_module: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /12-Backtracking-And-DFS/Type-1-Basic/0113-path-sum-ii/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | int val; 3 | TreeNode left; 4 | TreeNode right; 5 | 6 | TreeNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /12-Backtracking-And-DFS/Type-3-FloodFill/1080-insufficient-nodes-in-root-to-leaf-paths/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /12-Backtracking-And-DFS/其它/0078-subsets/out/production/0078-subsets/META-INF/0078-subsets.kotlin_module: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /12-Backtracking-And-DFS/其它/0107-binary-tree-level-order-traversal-ii/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-1-introduction/0509-fibonacci-number/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 动态规划 4 | // 时间复杂度:O(N) 5 | // 空间复杂度:O(N) 6 | 7 | public int fib(int N) { 8 | if (N < 2) { 9 | return N; 10 | } 11 | int[] dp = new int[N + 1]; 12 | 13 | dp[0] = 0; 14 | dp[1] = 1; 15 | for (int i = 2; i < N + 1; i++) { 16 | dp[i] = dp[i - 1] + dp[i - 2]; 17 | } 18 | return dp[N]; 19 | } 20 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-1-introduction/0509-fibonacci-number/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | // 动态规划:使用滚动变量 4 | // 时间复杂度:O(N) 5 | // 空间复杂度:O(1) 6 | 7 | public int fib(int N) { 8 | if (N < 2) { 9 | return N; 10 | } 11 | int a = 0; 12 | int b = 1; 13 | int c = 0; 14 | for (int i = 2; i < N + 1; i++) { 15 | c = a + b; 16 | a = b; 17 | b = c; 18 | } 19 | return c; 20 | } 21 | // 其它解法:记忆化递归、矩阵乘法 22 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-1-introduction/0509-fibonacci-number/src/Solution3.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | public class Solution3 { 4 | 5 | public int fib(int N) { 6 | if (N < 2) { 7 | return N; 8 | } 9 | 10 | // 0 要占一个位置,所以设置 N + 1 个位置 11 | int[] memo = new int[N + 1]; 12 | // 还未计算过的值用 -1 表示 13 | Arrays.fill(memo, -1); 14 | return fib(N, memo); 15 | } 16 | 17 | public int fib(int n, int[] memo) { 18 | if (n == 0) { 19 | return 0; 20 | } 21 | 22 | if (n == 1) { 23 | return 1; 24 | } 25 | 26 | if (memo[n] == -1) { 27 | memo[n] = fib(n - 1) + fib(n - 2); 28 | } 29 | return memo[n]; 30 | } 31 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-1-introduction/0509-fibonacci-number/src/Solution4.java: -------------------------------------------------------------------------------- 1 | public class Solution4 { 2 | 3 | public int fib(int N) { 4 | if (N < 2) { 5 | return N; 6 | } 7 | return fib(N - 1) + fib(N - 2); 8 | } 9 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-2-Repetitive-Subproblem/0062-unique-paths/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 方法一:记忆化递归 4 | 5 | private int[][] memo; 6 | 7 | public int uniquePaths(int m, int n) { 8 | if (m == 1 && n == 1) { 9 | return 1; 10 | } 11 | memo = new int[m][n]; 12 | memo[0][0] = 1; 13 | return dfs(m - 1, n - 1); 14 | } 15 | 16 | private int dfs(int m, int n) { 17 | // m = 0 和 n = 0 都有特殊含义 18 | if (m < 0 || n < 0) { 19 | return 0; 20 | } 21 | if (memo[m][n] > 0) { 22 | return memo[m][n]; 23 | } 24 | return memo[m][n] = dfs(m - 1, n) + dfs(m, n - 1); 25 | } 26 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-2-Repetitive-Subproblem/0062-unique-paths/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public int uniquePaths(int m, int n) { 4 | int[][] dp = new int[m][n]; 5 | // 先计算第一行和第一列 6 | for (int j = 0; j < n; j++) { 7 | dp[0][j] = 1; 8 | } 9 | for (int i = 1; i < m; i++) { 10 | dp[i][0] = 1; 11 | } 12 | // 再从左到右、从上到下依次计算 13 | for (int i = 1; i < m; i++) { 14 | for (int j = 1; j < n; j++) { 15 | dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; 16 | } 17 | } 18 | return dp[m - 1][n - 1]; 19 | } 20 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-2-Repetitive-Subproblem/0062-unique-paths/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | // 方法三:动态规划(空间优化) 4 | 5 | public int uniquePaths(int m, int n) { 6 | int[] dp = new int[n]; 7 | dp[0] = 1; 8 | for (int i = 0; i < m; i++) { 9 | for (int j = 1; j < n; j++) { 10 | dp[j] += dp[j - 1]; 11 | } 12 | } 13 | return dp[n - 1]; 14 | } 15 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-2-Repetitive-Subproblem/0062-unique-paths/src/Solution5.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | public class Solution5 { 4 | 5 | public int uniquePaths(int m, int n) { 6 | int[][] dp = new int[2][n]; 7 | // 第 1 行全填 1 8 | Arrays.fill(dp[0], 1); 9 | // 第 2 行第 1 个别忘了也填上 1 10 | dp[1][0] = 1; 11 | 12 | for (int i = 1; i < m; i++) { 13 | for (int j = 1; j < n; j++) { 14 | dp[i % 2][j] = dp[(i - 1) % 2][j] + dp[i % 2][j - 1]; 15 | } 16 | } 17 | return dp[(m - 1) % 2][n - 1]; 18 | } 19 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-2-Repetitive-Subproblem/0064-minimum-path-sum/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | public int minPathSum(int[][] grid) { 4 | int rows = grid.length; 5 | int cols = grid[0].length; 6 | 7 | for (int i = 1; i < cols; i++) { 8 | grid[0][i] = grid[0][i] + grid[0][i - 1]; 9 | } 10 | for (int i = 1; i < rows; i++) { 11 | grid[i][0] = grid[i][0] + grid[i - 1][0]; 12 | } 13 | 14 | for (int i = 1; i < rows; i++) { 15 | for (int j = 1; j < cols; j++) { 16 | grid[i][j] = Math.min(grid[i - 1][j], grid[i][j - 1]) + grid[i][j]; 17 | } 18 | } 19 | return grid[rows - 1][cols - 1]; 20 | } 21 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-2-Repetitive-Subproblem/0070-climbing-stairs/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 方法一:动态规划 4 | 5 | public int climbStairs(int n) { 6 | if (n <= 2) { 7 | return n; 8 | } 9 | 10 | // 0 需要占位 11 | int[] dp = new int[n + 1]; 12 | dp[0] = 1; 13 | dp[1] = 1; 14 | for (int i = 2; i <= n; i++) { 15 | dp[i] = dp[i - 1] + dp[i - 2]; 16 | } 17 | return dp[n]; 18 | } 19 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-2-Repetitive-Subproblem/0070-climbing-stairs/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | // 方法一:动态规划 4 | 5 | public int climbStairs(int n) { 6 | if (n <= 2) { 7 | return n; 8 | } 9 | 10 | int[] dp = new int[n + 1]; 11 | // 也可以不管 0 的值 12 | dp[1] = 1; 13 | dp[2] = 2; 14 | for (int i = 3; i <= n; i++) { 15 | dp[i] = dp[i - 1] + dp[i - 2]; 16 | } 17 | return dp[n]; 18 | } 19 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-2-Repetitive-Subproblem/0070-climbing-stairs/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | // 方法三:记忆化递归 4 | 5 | private int[] memo; 6 | 7 | public int climbStairs(int n) { 8 | memo = new int[n + 1]; 9 | return dfs(n); 10 | } 11 | 12 | private int dfs(int n) { 13 | if (memo[n] != 0) { 14 | return memo[n]; 15 | } 16 | if (n == 0) { 17 | return 1; 18 | } 19 | if (n == 1) { 20 | return 1; 21 | } 22 | return memo[n] = dfs(n - 1) + dfs(n - 2); 23 | } 24 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-2-Repetitive-Subproblem/0070-climbing-stairs/src/Solution5.java: -------------------------------------------------------------------------------- 1 | public class Solution5 { 2 | 3 | public int climbStairs(int n) { 4 | if (n == 1) { 5 | return 1; 6 | } 7 | if (n == 2) { 8 | return 2; 9 | } 10 | 11 | int p = 1; 12 | int q = 2; 13 | int res = 1; 14 | for (int i = 3; i <= n; ++i) { 15 | res = p + q; 16 | p = q; 17 | q = res; 18 | } 19 | return res; 20 | } 21 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-2-Repetitive-Subproblem/0096-unique-binary-search-trees/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 方法一:动态规划 4 | 5 | public int numTrees(int n) { 6 | int[] dp = new int[n + 1]; 7 | dp[0] = 1; 8 | dp[1] = 1; 9 | for (int i = 2; i <= n; i++) { 10 | // 这里 j 表示左子树的元素个数,最小是 0 ,最大是 i - 1 11 | // 左边子树 + 右边子树 = i - 1 12 | // i - j - 1 表示的是右边子树元素个数 13 | for (int j = 0; j < i; j++) { 14 | // 使用 * 是因为乘法计数原理 15 | dp[i] += dp[j] * dp[i - j - 1]; 16 | } 17 | } 18 | return dp[n]; 19 | } 20 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-2-Repetitive-Subproblem/0096-unique-binary-search-trees/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | // 方法一:动态规划 4 | 5 | public int numTrees(int n) { 6 | int[] dp = new int[n + 1]; 7 | // 乘法因子的单位是 1 8 | dp[0] = 1; 9 | dp[1] = 1; 10 | for (int i = 2; i < n + 1; i++) { 11 | for (int j = 0; j < i / 2; j++) { 12 | dp[i] += 2 * (dp[j] * dp[i - j - 1]); 13 | } 14 | if ((i % 2) == 1) { 15 | dp[i] += dp[i / 2] * dp[i / 2]; 16 | } 17 | } 18 | return dp[n]; 19 | } 20 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-2-Repetitive-Subproblem/0746-min-cost-climbing-stairs/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public int minCostClimbingStairs(int[] cost) { 4 | int len = cost.length; 5 | int[] dp = new int[len + 1]; 6 | dp[0] = 0; 7 | dp[1] = 0; 8 | for (int i = 2; i <= len; i++) { 9 | dp[i] = Math.min(cost[i - 1] + dp[i - 1], cost[i - 2] + dp[i - 2]); 10 | } 11 | return dp[len]; 12 | } 13 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-2-Repetitive-Subproblem/0746-min-cost-climbing-stairs/src/Solution4.java: -------------------------------------------------------------------------------- 1 | public class Solution4 { 2 | 3 | public int minCostClimbingStairs(int[] cost) { 4 | int len = cost.length; 5 | int[] dp = new int[len + 1]; 6 | 7 | dp[0] = cost[0]; 8 | dp[1] = cost[1]; 9 | 10 | for (int i = 2; i <= len; i++) { 11 | if (i != len) { 12 | dp[i] = cost[i]; 13 | } 14 | dp[i] = Math.min(dp[i - 1], dp[i - 2]); 15 | } 16 | return dp[len]; 17 | } 18 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-2-Repetitive-Subproblem/0746-min-cost-climbing-stairs/src/Solution5.java: -------------------------------------------------------------------------------- 1 | public class Solution5 { 2 | 3 | public int minCostClimbingStairs(int[] cost) { 4 | int len = cost.length; 5 | int[] dp = new int[len + 1]; 6 | 7 | dp[0] = cost[0]; 8 | dp[1] = cost[1]; 9 | 10 | for (int i = 2; i < len; i++) { 11 | dp[i] = Math.min(dp[i - 1], dp[i - 2]) + cost[i]; 12 | } 13 | return Math.min(dp[len - 1], dp[len - 2]); 14 | } 15 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-2-Repetitive-Subproblem/0746-min-cost-climbing-stairs/src/Solution6.java: -------------------------------------------------------------------------------- 1 | public class Solution6 { 2 | 3 | public int minCostClimbingStairs(int[] cost) { 4 | int len = cost.length; 5 | int[] dp = new int[3]; 6 | 7 | dp[0] = cost[0]; 8 | dp[1] = cost[1]; 9 | 10 | for (int i = 2; i < len; i++) { 11 | dp[i % 3] = Math.min(dp[(i - 1) % 3], dp[(i - 2) % 3]) + cost[i]; 12 | } 13 | return Math.min(dp[(len - 1) % 3], dp[(len - 2) % 3]); 14 | } 15 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-3-Optimal-Substructure/0279-perfect-squares/src/Solution2.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | public class Solution2 { 4 | 5 | // 普通的动态规划 6 | 7 | public int numSquares(int n) { 8 | // 0 要占用一个位置 9 | int[] dp = new int[n + 1]; 10 | 11 | // 赋初值,设置成为 4 是数学定理保证 12 | Arrays.fill(dp, 4); 13 | // dp[0] = 0 的合理性:表达式 1 + dp[i - j * j] = 1 ,表示它自己就是一个完全平方式,所以结果是 1 14 | dp[0] = 0; 15 | 16 | // 一个一个求,自底向上 17 | for (int i = 1; i <= n; i++) { 18 | for (int k = 1; k * k <= i; k++) { 19 | dp[i] = Math.min(dp[i], dp[i - k * k] + 1); 20 | } 21 | } 22 | return dp[n]; 23 | } 24 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-3-Optimal-Substructure/0279-perfect-squares/src/Solution3.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | 4 | public class Solution3 { 5 | 6 | // 动态规划 7 | 8 | public int numSquares(int n) { 9 | int[] dp = new int[n + 1]; 10 | Arrays.fill(dp, 4); 11 | dp[0] = 0; 12 | for (int i = 1; i <= n; i++) { 13 | for (int j = 1; i - j * j >= 0; j++) { 14 | dp[i] = Math.min(dp[i], 1 + dp[i - j * j]); 15 | } 16 | } 17 | return dp[n]; 18 | } 19 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-3-Optimal-Substructure/0279-perfect-squares/src/Solution6.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | public class Solution6 { 4 | 5 | // 完全背包 6 | public int numSquares(int n) { 7 | int[] dp = new int[n + 1]; 8 | Arrays.fill(dp, 4); 9 | dp[0] = 0; 10 | // 遍历物品 11 | for (int i = 1; i * i <= n; i++) { 12 | // 遍历背包 13 | for (int j = 1; j <= n; j++) { 14 | if (i * i <= j && dp[j - i * i] != 4) { 15 | dp[j] = Math.min(dp[j - i * i] + 1, dp[j]); 16 | } 17 | } 18 | } 19 | return dp[n]; 20 | } 21 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-3-Optimal-Substructure/0322-coin-change/src/Solution2.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | public class Solution2 { 4 | 5 | // 使用「完全背包」问题的思路 6 | 7 | public int coinChange(int[] coins, int amount) { 8 | int[] dp = new int[amount + 1]; 9 | Arrays.fill(dp, amount + 1); 10 | dp[0] = 0; 11 | // 外层是硬币 12 | for (int coin : coins) { 13 | for (int i = coin; i <= amount; i++) { 14 | dp[i] = Math.min(dp[i], dp[i - coin] + 1); 15 | } 16 | } 17 | 18 | if (dp[amount] == amount + 1) { 19 | dp[amount] = -1; 20 | } 21 | return dp[amount]; 22 | } 23 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-3-Optimal-Substructure/0343-integer-break/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public int integerBreak(int n) { 4 | int[] dp = new int[n + 1]; 5 | // 初始化 6 | dp[1] = 1; 7 | // 递推开始 8 | for (int i = 2; i <= n; i++) { 9 | // 其中一个加法因子至少是 1,最多是 i - 1 10 | for (int j = 1; j <= i - 1; j++) { 11 | dp[i] = Math.max(dp[i], Math.max(j * (i - j), j * dp[i - j])); 12 | } 13 | } 14 | return dp[n]; 15 | } 16 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-3-Optimal-Substructure/0377-combination-sum-iv/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int combinationSum4(int[] nums, int target) { 4 | int[] dp = new int[target + 1]; 5 | dp[0] = 1; 6 | for (int i = 0; i < target; i++) { 7 | for (int num : nums) { 8 | if (i + num <= target) { 9 | dp[i + num] += dp[i]; 10 | } 11 | } 12 | } 13 | return dp[target]; 14 | } 15 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-3-Optimal-Substructure/0377-combination-sum-iv/src/Solution4.java: -------------------------------------------------------------------------------- 1 | public class Solution4 { 2 | 3 | public int combinationSum4(int[] nums, int target) { 4 | int len = nums.length; 5 | if (len == 0) { 6 | return 0; 7 | } 8 | 9 | int[] dp = new int[target + 1]; 10 | dp[0] = 1; 11 | 12 | for (int i = 1; i <= target; i++) { 13 | for (int num : nums) { 14 | if (i - num >= 0) { 15 | dp[i] += dp[i - num]; 16 | } 17 | } 18 | } 19 | return dp[target]; 20 | } 21 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-3-Optimal-Substructure/0377-combination-sum-iv/src/Solution5.java: -------------------------------------------------------------------------------- 1 | public class Solution5 { 2 | 3 | public int combinationSum4(int[] nums, int target) { 4 | int[] dp = new int[target + 1]; 5 | // 这个值被其它状态参考,设置为 1 是合理的 6 | dp[0] = 1; 7 | for (int i = 1; i <= target; i++) { 8 | for (int num : nums) { 9 | if (num <= i) { 10 | dp[i] += dp[i - num]; 11 | } 12 | } 13 | } 14 | return dp[target]; 15 | } 16 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-3-Optimal-Substructure/0377-combination-sum-iv/src/Solution6.java: -------------------------------------------------------------------------------- 1 | public class Solution6 { 2 | 3 | public int combinationSum4(int[] nums, int target) { 4 | int[] dp = new int[target + 1]; 5 | // 这个值被其它状态参考,设置为 1 是合理的 6 | dp[0] = 1; 7 | for (int i = 0; i < target; i++) { 8 | for (int num : nums) { 9 | if (i + num <= target) { 10 | dp[i + num] += dp[i]; 11 | } 12 | } 13 | } 14 | return dp[target]; 15 | } 16 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-3-Optimal-Substructure/0377-combination-sum-iv/src/Solution7.java: -------------------------------------------------------------------------------- 1 | public class Solution7 { 2 | 3 | public int combinationSum4(int[] nums, int target) { 4 | int len = nums.length; 5 | if (len == 0) { 6 | return 0; 7 | } 8 | 9 | int[] dp = new int[target + 1]; 10 | dp[0] = 1; 11 | for (int i = 1; i <= target; i++) { 12 | for (int num : nums) { 13 | if (num <= i) { 14 | dp[i] = dp[i] + dp[i - num]; 15 | } 16 | } 17 | } 18 | return dp[target]; 19 | } 20 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-4-No-Aftereffect/0120-triangle/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.List; 2 | 3 | public class Solution { 4 | 5 | // 从下到上 6 | 7 | public int minimumTotal(List> triangle) { 8 | int len = triangle.size(); 9 | if (len == 0) { 10 | return 0; 11 | } 12 | 13 | int[] dp = new int[len + 1]; 14 | for (int i = len - 1; i >= 0; i--) { 15 | for (int j = 0; j < i + 1; j++) { 16 | dp[j] = Math.min(dp[j], dp[j + 1]) + triangle.get(i).get(j); 17 | } 18 | } 19 | return dp[0]; 20 | } 21 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-4-No-Aftereffect/0120-triangle/src/Solution2.java: -------------------------------------------------------------------------------- 1 | import java.util.List; 2 | 3 | public class Solution2 { 4 | 5 | // 同 Solution 6 | 7 | public int minimumTotal(List> triangle) { 8 | int len = triangle.size(); 9 | if (len == 0) { 10 | return 0; 11 | } 12 | int[] dp = new int[len]; 13 | for (int i = 0; i < len; i++) { 14 | dp[i] = triangle.get(len - 1).get(i); 15 | } 16 | 17 | for (int i = len - 2; i >= 0; i--) { 18 | for (int j = 0; j <= i; j++) { 19 | dp[j] = Math.min(dp[j], dp[j + 1]) + triangle.get(i).get(j); 20 | } 21 | } 22 | return dp[0]; 23 | } 24 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-4-No-Aftereffect/0198-house-robber/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int rob(int[] nums) { 4 | int len = nums.length; 5 | if (len == 0) { 6 | return 0; 7 | } 8 | if (len == 1) { 9 | return nums[0]; 10 | } 11 | 12 | int[][] dp = new int[len][2]; 13 | dp[0][0] = 0; 14 | dp[0][1] = nums[0]; 15 | for (int i = 1; i < len; i++) { 16 | dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1]); 17 | dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] + nums[i]); 18 | } 19 | return Math.max(dp[len - 1][0], dp[len - 1][1]); 20 | } 21 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-4-No-Aftereffect/0198-house-robber/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | // 注意:有下标偏移 4 | 5 | public int rob(int[] nums) { 6 | int len = nums.length; 7 | // 0 表示不偷 8 | // 1 表示偷 9 | // 多加 1 天表示哨兵,相应地要做一些偏移 10 | 11 | // dp[i]:区间 [0, i] 偷取的最大价值 12 | int[][] dp = new int[len + 1][2]; 13 | for (int i = 1; i <= len; i++) { 14 | // 不偷:昨天不偷,昨天偷转换而来 15 | dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1]); 16 | // 偷:只能由昨天不偷转换来 17 | // 注意:这里有下标偏移 18 | dp[i][1] = dp[i - 1][0] + nums[i - 1]; 19 | } 20 | 21 | return Math.max(dp[len][0], dp[len][1]); 22 | } 23 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-4-No-Aftereffect/0198-house-robber/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | // 一维数组 4 | 5 | public int rob(int[] nums) { 6 | int len = nums.length; 7 | if (len == 0) { 8 | return 0; 9 | } 10 | if (len == 1) { 11 | return nums[0]; 12 | } 13 | 14 | // dp[i]:子区间 [0, i] 在不触动警报装置的情况下,能够偷窃到的最高金额 15 | int[] dp = new int[len]; 16 | dp[0] = nums[0]; 17 | dp[1] = Math.max(nums[0], nums[1]); 18 | for (int i = 2; i < len; i++) { 19 | // 分类讨论:在偷 nums[i] 与不偷 nums[i] 中选择一个最大值 20 | dp[i] = Math.max(dp[i - 1], nums[i] + dp[i - 2]); 21 | } 22 | return dp[len - 1]; 23 | } 24 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-4-No-Aftereffect/0198-house-robber/src/Solution4.java: -------------------------------------------------------------------------------- 1 | public class Solution4 { 2 | 3 | public int rob(int[] nums) { 4 | int len = nums.length; 5 | if (len == 0) { 6 | return 0; 7 | } 8 | if (len == 1) { 9 | return nums[0]; 10 | } 11 | 12 | // dp[i]:子区间 [0, i) 在不触动警报装置的情况下,能够偷窃到的最高金额 13 | int[] dp = new int[len + 1]; 14 | dp[0] = 0; 15 | dp[1] = nums[0]; 16 | for (int i = 2; i <= len; i++) { 17 | // 分类讨论:在偷 nums[i] 与不偷 nums[i] 中选择一个最大值 18 | dp[i] = Math.max(dp[i - 1], nums[i - 1] + dp[i - 2]); 19 | } 20 | return dp[len]; 21 | } 22 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-4-No-Aftereffect/Stock-Problems/0121-best-time-to-buy-and-sell-stock/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 方法一:暴力解法 4 | 5 | public int maxProfit(int[] prices) { 6 | int len = prices.length; 7 | if (len < 2) { 8 | return 0; 9 | } 10 | 11 | // 有可能不发生交易,因此结果集的初始值设置为 0 12 | int res = 0; 13 | 14 | // 枚举所有发生一次交易的股价差 15 | for (int i = 0; i < len - 1; i++) { 16 | for (int j = i + 1; j < len; j++) { 17 | res = Math.max(res, prices[j] - prices[i]); 18 | } 19 | } 20 | return res; 21 | } 22 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-4-No-Aftereffect/Stock-Problems/0121-best-time-to-buy-and-sell-stock/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | // 方法二:动态规划(滚动数组) 4 | 5 | public int maxProfit(int[] prices) { 6 | int len = prices.length; 7 | if (len < 2) { 8 | return 0; 9 | } 10 | 11 | int[][] dp = new int[2][2]; 12 | dp[0][0] = 0; 13 | dp[0][1] = -prices[0]; 14 | for (int i = 1; i < len; i++) { 15 | dp[i % 2][0] = Math.max(dp[(i - 1) % 2][0], dp[(i - 1) % 2][1] + prices[i]); 16 | dp[i % 2][1] = Math.max(dp[(i - 1) % 2][1], -prices[i]); 17 | } 18 | return dp[(len - 1) & 1][0]; 19 | } 20 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-4-No-Aftereffect/Stock-Problems/0121-best-time-to-buy-and-sell-stock/src/Solution4.java: -------------------------------------------------------------------------------- 1 | public class Solution4 { 2 | 3 | // 方法二:动态规划(空间优化) 4 | 5 | public int maxProfit(int[] prices) { 6 | int len = prices.length; 7 | if (len < 2) { 8 | return 0; 9 | } 10 | 11 | int[] dp = new int[2]; 12 | dp[0] = 0; 13 | dp[1] = -prices[0]; 14 | for (int i = 1; i < len; i++) { 15 | dp[0] = Math.max(dp[0], dp[1] + prices[i]); 16 | dp[1] = Math.max(dp[1], -prices[i]); 17 | } 18 | return dp[0]; 19 | } 20 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-4-No-Aftereffect/Stock-Problems/0121-best-time-to-buy-and-sell-stock/src/Solution5.java: -------------------------------------------------------------------------------- 1 | public class Solution5 { 2 | 3 | // 方法三:对暴力方法的优化 4 | // 思路:我们只关心之前(不包括今天)看到的最低股价,时间复杂度:O(N) 5 | 6 | public int maxProfit(int[] prices) { 7 | int len = prices.length; 8 | if (len < 2) { 9 | return 0; 10 | } 11 | 12 | int res = 0; 13 | // 表示在当前位置之前的最小值,假设修正法(打擂台法) 14 | int preMinVal = prices[0]; 15 | // 注意:这里从 1 开始 16 | for (int i = 1; i < len; i++) { 17 | res = Math.max(res, prices[i] - preMinVal); 18 | preMinVal = Math.min(preMinVal, prices[i]); 19 | } 20 | return res; 21 | } 22 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-4-No-Aftereffect/Stock-Problems/0122-best-time-to-buy-and-sell-stock-ii/src/Solution5.java: -------------------------------------------------------------------------------- 1 | public class Solution5 { 2 | 3 | // 方法三:贪心算法(由于不限制交易次数,只要今天股价比昨天高,就交易) 4 | 5 | public int maxProfit(int[] prices) { 6 | int len = prices.length; 7 | if (len < 2) { 8 | return 0; 9 | } 10 | 11 | int res = 0; 12 | for (int i = 1; i < len; i++) { 13 | int diff = prices[i] - prices[i - 1]; 14 | if (diff > 0) { 15 | res += diff; 16 | } 17 | } 18 | return res; 19 | } 20 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-4-No-Aftereffect/Stock-Problems/0122-best-time-to-buy-and-sell-stock-ii/src/Solution6.java: -------------------------------------------------------------------------------- 1 | public class Solution6 { 2 | 3 | // 方法三:贪心算法 4 | 5 | public int maxProfit(int[] prices) { 6 | int len = prices.length; 7 | if (len < 2) { 8 | return 0; 9 | } 10 | 11 | int res = 0; 12 | for (int i = 1; i < len; i++) { 13 | res += Math.max(prices[i] - prices[i - 1], 0); 14 | } 15 | return res; 16 | } 17 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-4-No-Aftereffect/Stock-Problems/0714-best-time-to-buy-and-sell-stock-with-transaction-fee/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | // 方法一:动态规划(规定在卖出股票的时候扣除手续费) 4 | 5 | public int maxProfit(int[] prices, int fee) { 6 | int len = prices.length; 7 | if (len < 2) { 8 | return 0; 9 | } 10 | int[][] dp = new int[len][2]; 11 | dp[0][0] = 0; 12 | dp[0][1] = -prices[0]; 13 | for (int i = 1; i < len; i++) { 14 | dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i] - fee); 15 | dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]); 16 | } 17 | return dp[len - 1][0]; 18 | } 19 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-4-No-Aftereffect/Stock-Problems/0714-best-time-to-buy-and-sell-stock-with-transaction-fee/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | public int maxProfit(int[] prices, int fee) { 4 | int len = prices.length; 5 | if (len < 2) { 6 | return 0; 7 | } 8 | 9 | int[] dp = new int[2]; 10 | dp[0] = 0; 11 | dp[1] = -prices[0] - fee; 12 | for (int i = 1; i < len; i++) { 13 | dp[0] = Math.max(dp[0], dp[1] + prices[i]); 14 | dp[1] = Math.max(dp[1], dp[0] - prices[i] - fee); 15 | } 16 | return dp[0]; 17 | } 18 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-4-No-Aftereffect/Stock-Problems/0714-best-time-to-buy-and-sell-stock-with-transaction-fee/src/Solution4.java: -------------------------------------------------------------------------------- 1 | public class Solution4 { 2 | 3 | // 方法一:动态规划(空间优化) 4 | 5 | public int maxProfit(int[] prices, int fee) { 6 | int len = prices.length; 7 | if (len < 2) { 8 | return 0; 9 | } 10 | 11 | int[] dp = new int[2]; 12 | dp[0] = 0; 13 | dp[1] = -prices[0]; 14 | 15 | for (int i = 1; i < len; i++) { 16 | dp[0] = Math.max(dp[0], dp[1] + prices[i] ); 17 | dp[1] = Math.max(dp[1], dp[0] - prices[i]- fee); 18 | } 19 | return dp[0]; 20 | } 21 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-5-LIS/0674-longest-continuous-increasing-subsequence/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | // 方法二:动态规划(空间优化) 4 | 5 | public int findLengthOfLCIS(int[] nums) { 6 | int len = nums.length; 7 | if (len == 0) { 8 | return 0; 9 | } 10 | 11 | int continuousIncreasingLen = 1; 12 | int res = 1; 13 | for (int i = 1; i < len; i++) { 14 | if (nums[i] > nums[i - 1]) { 15 | continuousIncreasingLen += 1; 16 | } else { 17 | continuousIncreasingLen = 1; 18 | } 19 | 20 | res = Math.max(res, continuousIncreasingLen); 21 | } 22 | return res; 23 | } 24 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-5-LIS/0674-longest-continuous-increasing-subsequence/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | public int findLengthOfLCIS(int[] nums) { 4 | int len = nums.length; 5 | int res = 0; 6 | int i = 0; 7 | int j = 0; 8 | // 循环不变量 [i..j) 严格单调递增 9 | while (j < len) { 10 | if (j > 0 && nums[j - 1] >= nums[j]) { 11 | i = j; 12 | } 13 | j++; 14 | res = Math.max(res, j - i); 15 | } 16 | return res; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-5-LIS/0674-longest-continuous-increasing-subsequence/src/Solution4.java: -------------------------------------------------------------------------------- 1 | public class Solution4 { 2 | 3 | public int findLengthOfLCIS(int[] nums) { 4 | int len = nums.length; 5 | int res = 0; 6 | int i = 0; 7 | int j = 0; 8 | // 循环不变量 [i..j] 严格单调递增 9 | while (j < len) { 10 | if (j > 0 && nums[j - 1] >= nums[j]) { 11 | i = j; 12 | } 13 | res = Math.max(res, j - i + 1); 14 | j++; 15 | } 16 | return res; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-5-LIS/最大子段和以及相关问题/0053-maximum-subarray/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | // 方法一:暴力解法(空间优化,可以不看) 4 | 5 | public int maxSubArray(int[] nums) { 6 | int len = nums.length; 7 | int res = Integer.MIN_VALUE; 8 | for (int i = 0; i < len; i++) { 9 | int sum = 0; 10 | for (int j = i; j < len; j++) { 11 | sum += nums[j]; 12 | res = Math.max(res, sum); 13 | } 14 | } 15 | return res; 16 | } 17 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-5-LIS/最大子段和以及相关问题/0053-maximum-subarray/src/Solution5.java: -------------------------------------------------------------------------------- 1 | public class Solution5 { 2 | 3 | // 方法一:动态规划(空间优化) 4 | 5 | public int maxSubArray(int[] nums) { 6 | int len = nums.length; 7 | if (len == 0) { 8 | return 0; 9 | } 10 | // 起名叫 pre 表示的意思是「上一个状态的值」 11 | int pre = nums[0]; 12 | int res = pre; 13 | for (int i = 1; i < len; i++) { 14 | pre = Math.max(nums[i], pre + nums[i]); 15 | res = Math.max(res, pre); 16 | } 17 | return res; 18 | } 19 | } -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-5-LIS/最大子段和以及相关问题/0053-maximum-subarray/src/Solution7.java: -------------------------------------------------------------------------------- 1 | public class Solution7 { 2 | 3 | public int maxSubArray(int[] nums) { 4 | // dp[i] 表示:以 nums[i] 开头的连续子序列的最大和 5 | int len = nums.length; 6 | int[] dp = new int[len]; 7 | dp[len - 1] = nums[len - 1]; 8 | for (int i = len - 2; i >= 0; i--) { 9 | if (dp[i + 1] <= 0) { 10 | dp[i] = nums[i]; 11 | } else { 12 | dp[i] = dp[i + 1] + nums[i]; 13 | } 14 | } 15 | 16 | int res = dp[0]; 17 | for (int i = 1; i < len; i++) { 18 | res = Math.max(dp[i], res); 19 | } 20 | return res; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-5-LIS/最大子段和以及相关问题/0918-maximum-sum-circular-subarray/out/production/0918-maximum-sum-circular-subarray/META-INF/0918-maximum-sum-circular-subarray.kotlin_module: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-6-LCS/0010-regular-expression-matching/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | public boolean isMatch(String s, String p) { 3 | if (p.length() == 0){ 4 | return s.length() == 0; 5 | } 6 | 7 | boolean firstMatch = s.length() >= 1 && (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.'); 8 | 9 | if (p.length() > 1 && p.charAt(1) == '*'){ 10 | if (isMatch(s, p.substring(2))){ 11 | return true; 12 | } 13 | return firstMatch && isMatch(s.substring(1), p); 14 | } 15 | return firstMatch && isMatch(s.substring(1), p.substring(1)); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /13-Dynamic-Programming-1/13-6-LCS/1035-uncrossed-lines/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 方法:动态规划(最长公共子序列) 4 | 5 | public int maxUncrossedLines(int[] A, int[] B) { 6 | int len1 = A.length; 7 | int len2 = B.length; 8 | int[][] dp = new int[len1 + 1][len2 + 1]; 9 | for (int i = 1; i <= len1; i++) { 10 | for (int j = 1; j <= len2; j++) { 11 | if (A[i - 1] == B[j - 1]) { 12 | dp[i][j] = dp[i - 1][j - 1] + 1; 13 | } else { 14 | dp[i][j] = Math.max(dp[i][j - 1], dp[i - 1][j]); 15 | } 16 | } 17 | } 18 | return dp[len1][len2]; 19 | } 20 | } -------------------------------------------------------------------------------- /14-Dynamic-Programming-2/完全背包问题/0518-coin-change-2/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | // 方法二:状态数组多设置一行的写法 4 | 5 | public int change(int amount, int[] coins) { 6 | int len = coins.length; 7 | // 定义:使用区间 [0, i) 里的硬币,恰好可以凑出面值为 j 的方案总数 8 | int[][] dp = new int[len + 1][amount + 1]; 9 | // 初始化 10 | dp[0][0] = 1; 11 | 12 | // 递推开始 13 | for (int i = 1; i <= len; i++) { 14 | for (int j = 0; j <= amount; j++) { 15 | dp[i][j] = dp[i - 1][j]; 16 | if (j - coins[i - 1] >= 0) { 17 | dp[i][j] += dp[i][j - coins[i - 1]]; 18 | } 19 | } 20 | } 21 | return dp[len][amount]; 22 | } 23 | } -------------------------------------------------------------------------------- /14-Dynamic-Programming-2/完全背包问题/0518-coin-change-2/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | // 完全背包空间优化的写法 4 | 5 | public int change(int amount, int[] coins) { 6 | int[] dp = new int[amount + 1]; 7 | // 初始化 8 | dp[0] = 1; 9 | 10 | // 递推开始 11 | int len = coins.length; 12 | for (int i = 1; i <= len; i++) { 13 | for (int j = 0; j <= amount; j++) { 14 | if (j - coins[i - 1] >= 0) { 15 | dp[j] += dp[j - coins[i - 1]]; 16 | } 17 | } 18 | } 19 | return dp[amount]; 20 | } 21 | } -------------------------------------------------------------------------------- /14-Dynamic-Programming-2/完全背包问题/0518-coin-change-2/src/Solution5.java: -------------------------------------------------------------------------------- 1 | import java.io.IOException; 2 | 3 | public class Solution5 { 4 | 5 | public static void main(String[] args) throws IOException { 6 | System.out.println("-12 \t\t:" + Integer.toBinaryString(-12)); 7 | System.out.println("-12 >>> 2 \t:" + Integer.toBinaryString((-12) >>> 2)); 8 | System.out.println(-12 >>> 2); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /14-Dynamic-Programming-2/完全背包问题/0518-coin-change-2/src/Solution9.java: -------------------------------------------------------------------------------- 1 | public class Solution9 { 2 | 3 | public int change(int amount, int[] coins) { 4 | int len = coins.length; 5 | if (len == 0) { 6 | if (amount == 0) { 7 | return 1; 8 | } 9 | return 0; 10 | } 11 | 12 | int[] dp = new int[amount + 1]; 13 | dp[0] = 1; 14 | 15 | for (int i = coins[0]; i <= amount; i += coins[0]) { 16 | dp[i] = 1; 17 | } 18 | 19 | for (int i = 1; i < len; i++) { 20 | for (int j = coins[i]; j <= amount; j += coins[i]) { 21 | dp[j + coins[i]] += dp[j]; 22 | 23 | } 24 | } 25 | return dp[amount]; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /14-Dynamic-Programming-2/完全背包问题/14-3 完全包问题/0-1、完全背包问题选讲.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liweiwei1419/LeetCode-Solutions-in-Good-Style/acc8661338cc7c1ae067915fb16079a9e3e66847/14-Dynamic-Programming-2/完全背包问题/14-3 完全包问题/0-1、完全背包问题选讲.pdf -------------------------------------------------------------------------------- /14-Dynamic-Programming-2/完全背包问题/14-3 完全包问题/0-1、完全背包问题选讲.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liweiwei1419/LeetCode-Solutions-in-Good-Style/acc8661338cc7c1ae067915fb16079a9e3e66847/14-Dynamic-Programming-2/完全背包问题/14-3 完全包问题/0-1、完全背包问题选讲.pptx -------------------------------------------------------------------------------- /15-Greedy-Algorithm/0012-integer-to-roman/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public String intToRoman(int num) { 4 | int[] nums = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; 5 | String[] romans = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}; 6 | 7 | StringBuilder stringBuilder = new StringBuilder(); 8 | int index = 0; 9 | while (num > 0) { 10 | int times = num / nums[index]; 11 | while (times > 0) { 12 | stringBuilder.append(romans[index]); 13 | times--; 14 | } 15 | num = num % nums[index]; 16 | index++; 17 | } 18 | return stringBuilder.toString(); 19 | } 20 | } -------------------------------------------------------------------------------- /15-Greedy-Algorithm/0012-integer-to-roman/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | // 一位一位打表做 4 | 5 | public String intToRoman(int num) { 6 | // 个位 7 | String[] one = new String[]{"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"}; 8 | // 十位 9 | String[] two = new String[]{"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"}; 10 | // 百位 11 | String[] three = new String[]{"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"}; 12 | // 千位 13 | String[] four = new String[]{"", "M", "MM", "MMM"}; 14 | return four[num / 1000] + three[(num / 100) % 10] + two[(num / 10) % 10] + one[num % 10]; 15 | } 16 | } -------------------------------------------------------------------------------- /15-Greedy-Algorithm/0045-jump-game-ii/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | // 代码超时 4 | 5 | public int jump(int[] nums) { 6 | int len = nums.length; 7 | int p = len - 1; 8 | int res = 0; 9 | while (p > 0) { 10 | for (int j = 0; j < p; j++) { 11 | if (j + nums[j] >= p) { 12 | res++; 13 | p = j; 14 | break; 15 | } 16 | } 17 | } 18 | return res; 19 | } 20 | } -------------------------------------------------------------------------------- /15-Greedy-Algorithm/0045-jump-game-ii/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | // 方法:贪心算法:类似层序遍历,脑子里要形成一个动画 4 | 5 | public int jump(int[] nums) { 6 | int len = nums.length; 7 | if (len < 2){ 8 | return 0; 9 | } 10 | 11 | // 当前区间的结束下标 12 | int currentEnd = 0; 13 | // [0, i) 里能达到的最远下标 14 | int maxReached = 0; 15 | int steps = 0; 16 | for (int i = 0; i < len - 1; i++) { 17 | maxReached = Math.max(maxReached, i + nums[i]); 18 | if (i == currentEnd) { 19 | currentEnd = maxReached; 20 | steps++; 21 | } 22 | 23 | } 24 | return steps; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /15-Greedy-Algorithm/0045-jump-game-ii/src/Solution6.java: -------------------------------------------------------------------------------- 1 | public class Solution6 { 2 | } 3 | -------------------------------------------------------------------------------- /15-Greedy-Algorithm/0055-jump-game/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public boolean canJump(int[] nums) { 4 | int len = nums.length; 5 | int maxReach = 0; 6 | for (int i = 0; i < len; i++) { 7 | if (maxReach < i) { 8 | return false; 9 | } 10 | maxReach = Math.max(maxReach, i + nums[i]); 11 | } 12 | return true; 13 | } 14 | } -------------------------------------------------------------------------------- /15-Greedy-Algorithm/0134-gas-station/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int canCompleteCircuit(int[] gas, int[] cost) { 4 | int diffSum = 0; 5 | int minDiffSum = Integer.MAX_VALUE; 6 | int start = 0; 7 | 8 | int len = gas.length; 9 | for (int i = 0; i < len; i++) { 10 | diffSum += gas[i] - cost[i]; 11 | 12 | if (diffSum < minDiffSum) { 13 | minDiffSum = diffSum; 14 | start = i; 15 | } 16 | } 17 | 18 | if (diffSum < 0) { 19 | return -1; 20 | } 21 | return (start + 1) % len; 22 | } 23 | } -------------------------------------------------------------------------------- /15-Greedy-Algorithm/0134-gas-station/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | // 贪心算法 4 | 5 | public int canCompleteCircuit(int[] gas, int[] cost) { 6 | // 从下标 0 开始的「累计剩余油量」 7 | int rest = 0; 8 | // 从 start + 1 开始的「累计剩余油量」 9 | int run = 0; 10 | // 输出结果 11 | int start = 0; 12 | 13 | int len = gas.length; 14 | for (int i = 0; i < len; i++) { 15 | run += (gas[i] - cost[i]); 16 | rest += (gas[i] - cost[i]); 17 | if (run < 0) { 18 | start = i + 1; 19 | run = 0; 20 | } 21 | } 22 | 23 | if (rest < 0) { 24 | return -1; 25 | } 26 | return start; 27 | } 28 | } -------------------------------------------------------------------------------- /15-Greedy-Algorithm/0392-is-subsequence/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 贪心算法 4 | 5 | public boolean isSubsequence(String s, String t) { 6 | int i = 0; 7 | int j = 0; 8 | int sLen = s.length(); 9 | int tLen = t.length(); 10 | while (i < sLen && j < tLen) { 11 | if (s.charAt(i) == t.charAt(j)) { 12 | i++; 13 | } 14 | j++; 15 | } 16 | return i == sLen; 17 | 18 | } 19 | } -------------------------------------------------------------------------------- /15-Greedy-Algorithm/0392-is-subsequence/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public boolean isSubsequence(String s, String t) { 4 | int sLen = s.length(); 5 | int tLen = t.length(); 6 | int i = 0; 7 | int j = 0; 8 | while (i < sLen && j < tLen) { 9 | if (s.charAt(i) == t.charAt(j)) { 10 | i++; 11 | } 12 | j++; 13 | } 14 | return i == sLen; 15 | } 16 | } -------------------------------------------------------------------------------- /15-Greedy-Algorithm/0392-is-subsequence/src/Solution4.java: -------------------------------------------------------------------------------- 1 | public class Solution4 { 2 | 3 | public boolean isSubsequence(String s, String t) { 4 | int slen = s.length(); 5 | int tlen = t.length(); 6 | int sl = 0; 7 | int tl = 0; 8 | while (sl < slen && tl < tlen) { 9 | while (tl < tlen && s.charAt(sl) != t.charAt(tl)) { 10 | tl++; 11 | } 12 | if (tl == tlen) { 13 | break; 14 | } 15 | sl++; 16 | tl++; 17 | } 18 | return sl == slen; 19 | } 20 | } -------------------------------------------------------------------------------- /15-Greedy-Algorithm/0435-non-overlapping-intervals/src/Solution2.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.Comparator; 3 | 4 | public class Solution2 { 5 | 6 | // 贪心算法:区间按照结尾端点升序排序 7 | 8 | public int eraseOverlapIntervals(int[][] intervals) { 9 | int len = intervals.length; 10 | if (len < 2) { 11 | return 0; 12 | } 13 | 14 | // 区间按照结尾端点升序排序 15 | Arrays.sort(intervals, Comparator.comparingInt(a -> a[1])); 16 | 17 | int res = 1; 18 | int end = intervals[0][1]; 19 | for (int i = 1; i < len; i++) { 20 | if (intervals[i][0] >= end) { 21 | res += 1; 22 | end = intervals[i][1]; 23 | } 24 | } 25 | return len - res; 26 | } 27 | } -------------------------------------------------------------------------------- /15-Greedy-Algorithm/0452-minimum-number-of-arrows-to-burst-balloons/src/Solution2.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.Comparator; 3 | 4 | public class Solution2 { 5 | 6 | public int findMinArrowShots(int[][] points) { 7 | int len = points.length; 8 | if (len < 2) { 9 | return len; 10 | } 11 | 12 | Arrays.sort(points, Comparator.comparingInt(o -> o[1])); 13 | int end = points[0][1]; 14 | int res = 1; 15 | for (int i = 1; i < len; i++) { 16 | if (points[i][0] > end) { 17 | end = points[i][1]; 18 | res++; 19 | } 20 | } 21 | return res; 22 | } 23 | } -------------------------------------------------------------------------------- /15-Greedy-Algorithm/0455-assign-cookies/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | public class Solution { 4 | 5 | public int findContentChildren(int[] g, int[] s) { 6 | int gLen = g.length; 7 | int sLen = s.length; 8 | if (sLen == 0) { 9 | return 0; 10 | } 11 | 12 | Arrays.sort(g); 13 | Arrays.sort(s); 14 | 15 | int gIndex = 0; 16 | int sIndex = 0; 17 | while (gIndex < gLen && sIndex < sLen) { 18 | // 用最小的饼干去满足贪心程度最低的小朋友 19 | if (g[gIndex] <= s[sIndex]) { 20 | gIndex++; 21 | sIndex++; 22 | } else { 23 | sIndex++; 24 | } 25 | } 26 | return gIndex; 27 | } 28 | } -------------------------------------------------------------------------------- /15-Greedy-Algorithm/0561-array-partition-i/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | public class Solution { 4 | 5 | public int arrayPairSum(int[] nums) { 6 | int len = nums.length; 7 | Arrays.sort(nums); 8 | int res = 0; 9 | for (int i = 0; i < len; i += 2) { 10 | res += nums[i]; 11 | } 12 | return res; 13 | } 14 | } -------------------------------------------------------------------------------- /15-Greedy-Algorithm/贪心算法/0057-insert-interval/src/Interval.java: -------------------------------------------------------------------------------- 1 | public class Interval { 2 | 3 | int start; 4 | int end; 5 | 6 | Interval() { 7 | start = 0; 8 | end = 0; 9 | } 10 | 11 | Interval(int s, int e) { 12 | start = s; 13 | end = e; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /15-Greedy-Algorithm/贪心算法/0406-queue-reconstruction-by-height(不是贪心算法)/src/Solution3.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.Arrays; 3 | import java.util.List; 4 | 5 | public class Solution3 { 6 | 7 | public int[][] reconstructQueue(int[][] people) { 8 | Arrays.sort(people, (person1, person2) -> { 9 | if (person1[0] != person2[0]) { 10 | return person2[0] - person1[0]; 11 | } else { 12 | return person1[1] - person2[1]; 13 | } 14 | }); 15 | 16 | List res = new ArrayList<>(); 17 | for (int[] person : people) { 18 | res.add(person[1], person); 19 | } 20 | return res.toArray(new int[res.size()][]); 21 | } 22 | } -------------------------------------------------------------------------------- /17-Hash-Table/1-Basic/0001-two-sum/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 方法一:暴力解法 4 | 5 | public int[] twoSum(int[] nums, int target) { 6 | int len = nums.length; 7 | for (int i = 0; i < len - 1; i++) { 8 | for (int j = i + 1; j < len; j++) { 9 | if (nums[i] + nums[j] == target) { 10 | return new int[]{i, j}; 11 | } 12 | } 13 | } 14 | throw new IllegalArgumentException("No two sum solution"); 15 | } 16 | } -------------------------------------------------------------------------------- /17-Hash-Table/1-Basic/0001-two-sum/src/Solution2.java: -------------------------------------------------------------------------------- 1 | import java.util.HashMap; 2 | import java.util.Map; 3 | 4 | public class Solution2 { 5 | 6 | // 方法二:哈希表 7 | 8 | public int[] twoSum(int[] nums, int target) { 9 | int len = nums.length; 10 | Map hashMap = new HashMap<>(len - 1); 11 | hashMap.put(nums[0], 0); 12 | for (int i = 1; i < len; i++) { 13 | int another = target - nums[i]; 14 | if (hashMap.containsKey(another)) { 15 | return new int[]{i, hashMap.get(another)}; 16 | } 17 | hashMap.put(nums[i], i); 18 | } 19 | throw new IllegalArgumentException("No two sum solution"); 20 | } 21 | } -------------------------------------------------------------------------------- /17-Hash-Table/1-Basic/0001-two-sum/src/Solution3.java: -------------------------------------------------------------------------------- 1 | import java.util.HashMap; 2 | import java.util.Map; 3 | import java.util.TreeSet; 4 | 5 | public class Solution3 { 6 | 7 | public int[] twoSum(int[] nums, int target) { 8 | int len = nums.length; 9 | Map hashMap = new HashMap<>(len - 1); 10 | for (int i = 0; i < len; i++) { 11 | if (hashMap.containsKey(target - nums[i])) { 12 | return new int[]{i, hashMap.get(target - nums[i])}; 13 | } 14 | hashMap.put(nums[i], i); 15 | } 16 | return new int[0]; 17 | } 18 | } -------------------------------------------------------------------------------- /17-Hash-Table/2-Advance/0187-repeated-dna-sequences/src/Solution2.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.HashSet; 3 | import java.util.List; 4 | 5 | public class Solution2 { 6 | 7 | public List findRepeatedDnaSequences(String s) { 8 | HashSet seen = new HashSet<>(); 9 | HashSet repeated = new HashSet<>(); 10 | 11 | int len = s.length(); 12 | for (int i = 0; i + 9 < len; i++) { 13 | String segment = s.substring(i, i + 10); 14 | if (!seen.add(segment)) { 15 | repeated.add(segment); 16 | } 17 | } 18 | return new ArrayList<>(repeated); 19 | } 20 | } -------------------------------------------------------------------------------- /17-Hash-Table/2-Advance/0217-contains-duplicate/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.HashSet; 2 | import java.util.Set; 3 | 4 | public class Solution { 5 | 6 | public boolean containsDuplicate(int[] nums) { 7 | Set set = new HashSet<>(); 8 | for (int num : nums) { 9 | if (set.contains(num)) { 10 | return true; 11 | } else { 12 | set.add(num); 13 | } 14 | } 15 | return false; 16 | } 17 | } -------------------------------------------------------------------------------- /17-Hash-Table/2-Advance/0217-contains-duplicate/src/Solution2.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | public class Solution2 { 4 | 5 | // 排序,逐个检查 6 | 7 | public boolean containsDuplicate(int[] nums) { 8 | int len = nums.length; 9 | // 特判 10 | if (len < 2) { 11 | return false; 12 | } 13 | 14 | // 原地排序,这一步是关键 15 | Arrays.sort(nums); 16 | for (int i = 0; i < len - 1; i++) { 17 | if (nums[i] == nums[i + 1]) { 18 | return true; 19 | } 20 | } 21 | return false; 22 | } 23 | } -------------------------------------------------------------------------------- /17-Hash-Table/2-Advance/0217-contains-duplicate/src/Solution3.java: -------------------------------------------------------------------------------- 1 | import java.util.HashSet; 2 | import java.util.Set; 3 | 4 | public class Solution3 { 5 | 6 | public boolean containsDuplicate1(int[] nums) { 7 | Set set = new HashSet<>(); 8 | for (int num : nums) { 9 | boolean success = set.add(num); 10 | if (!success) { 11 | // 如果没有添加成功,表示有重复元素,直接返回就可以了 12 | return true; 13 | } 14 | } 15 | return false; 16 | } 17 | } -------------------------------------------------------------------------------- /17-Hash-Table/2-Advance/0217-contains-duplicate/src/Solution4.java: -------------------------------------------------------------------------------- 1 | import java.util.HashSet; 2 | import java.util.Set; 3 | 4 | public class Solution4 { 5 | 6 | public boolean containsDuplicate(int[] nums) { 7 | Set hashSet = new HashSet<>(); 8 | for (int num : nums) { 9 | if (hashSet.contains(num)) { 10 | return true; 11 | } 12 | hashSet.add(num); 13 | } 14 | return false; 15 | } 16 | } -------------------------------------------------------------------------------- /17-Hash-Table/2-Advance/0387-first-unique-character-in-a-string/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int firstUniqChar(String s) { 4 | int len = s.length(); 5 | if (len == 0) { 6 | return -1; 7 | } 8 | if (len == 1) { 9 | return 0; 10 | } 11 | 12 | int[] map = new int[26]; 13 | for (int i = 0; i < len; i++) { 14 | int index = s.charAt(i) - 'a'; 15 | map[index]++; 16 | } 17 | 18 | for (int i = 0; i < len; i++) { 19 | int index = s.charAt(i) - 'a'; 20 | if (map[index] == 1) { 21 | return i; 22 | } 23 | } 24 | return -1; 25 | } 26 | } -------------------------------------------------------------------------------- /17-Hash-Table/2-Advance/0387-first-unique-character-in-a-string/src/Solution2.java: -------------------------------------------------------------------------------- 1 | import java.util.HashMap; 2 | import java.util.Map; 3 | 4 | public class Solution2 { 5 | 6 | public int firstUniqChar(String s) { 7 | int len = s.length(); 8 | 9 | // 计数 10 | Map map = new HashMap<>(); 11 | for (int i = 0; i < len; i++) { 12 | map.put(s.charAt(i), map.getOrDefault(s.charAt(i), 0) + 1); 13 | } 14 | 15 | for (int i = 0; i < len; i++) { 16 | if (map.get(s.charAt(i)) == 1) { 17 | return i; 18 | } 19 | } 20 | return -1; 21 | } 22 | } -------------------------------------------------------------------------------- /17-Hash-Table/2-Advance/1207-unique-number-of-occurrences/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.HashMap; 2 | import java.util.HashSet; 3 | import java.util.Map; 4 | import java.util.Set; 5 | 6 | public class Solution { 7 | 8 | public boolean uniqueOccurrences(int[] arr) { 9 | Map freq = new HashMap<>(); 10 | for (int num : arr) { 11 | freq.put(num, freq.getOrDefault(num, 0) + 1); 12 | } 13 | 14 | Set hashSet = new HashSet<>(); 15 | for (int count : freq.values()) { 16 | if (hashSet.contains(count)) { 17 | return false; 18 | } 19 | hashSet.add(count); 20 | } 21 | 22 | return true; 23 | } 24 | } -------------------------------------------------------------------------------- /17-Hash-Table/待分类/0220-contains-duplicate-iii/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | // 暴力解法(超时) 4 | 5 | public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) { 6 | int len = nums.length; 7 | if (len == 0 || k <= 0 || t < 0) { 8 | return false; 9 | } 10 | 11 | for (int i = 0; i < len; i++) { 12 | for (int j = i + 1; j < len; j++) { 13 | // 注意:nums[j] - nums[i] 的结果可能会整型溢出,因此运算之前需要转换成 long 类型 14 | if (Math.abs(j - i) <= k && Math.abs((long) nums[j] - (long) nums[i]) <= t) { 15 | return true; 16 | } 17 | } 18 | } 19 | return false; 20 | } 21 | } -------------------------------------------------------------------------------- /17-Hash-Table/待分类/0220-contains-duplicate-iii/src/Solution4.java: -------------------------------------------------------------------------------- 1 | import java.util.TreeSet; 2 | 3 | public class Solution4 { 4 | 5 | public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) { 6 | int n = nums.length; 7 | TreeSet set = new TreeSet<>(); 8 | for (int i = 0; i < n; i++) { 9 | Long ceiling = set.ceiling((long) nums[i] - (long) t); 10 | if (ceiling != null && ceiling <= (long) nums[i] + (long) t) { 11 | return true; 12 | } 13 | set.add((long) nums[i]); 14 | if (i >= k) { 15 | set.remove((long) nums[i - k]); 16 | } 17 | } 18 | return false; 19 | } 20 | } -------------------------------------------------------------------------------- /17-Hash-Table/待分类/0220-contains-duplicate-iii/src/TreeSetDemo.java: -------------------------------------------------------------------------------- 1 | import java.util.TreeSet; 2 | 3 | 4 | /** 5 | * TreeSet 的特殊 API 6 | */ 7 | public class TreeSetDemo { 8 | 9 | // floor 表示地板,即小于等于输入值的最大元素 10 | // ceiling 表示天花板,即大于等于输入值的最元素 11 | 12 | // 例如:1,3,7,12 13 | // 输入是 8 14 | // floor(8) = 7 15 | // ceiling(8) = 12 16 | 17 | 18 | public static void main(String[] args) { 19 | TreeSet set = new TreeSet<>(); 20 | set.add(1); 21 | set.add(3); 22 | set.add(7); 23 | set.add(12); 24 | System.out.println("8 的地板是:" + set.floor(8)); 25 | System.out.println("8 的天花板是:" + set.ceiling(8)); 26 | } 27 | } -------------------------------------------------------------------------------- /17-Hash-Table/待分类/0389-find-the-difference/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 只包含小写数字,干脆全部转成 0-25 的数字就好了 4 | // 根据题意,t 比 s 多 1 个字符,干脆初始值就取 t 的第 1 个字符 5 | 6 | public char findTheDifference(String s, String t) { 7 | int sLen = s.length(); 8 | int tLen = t.length(); 9 | 10 | char[] sCharArray = s.toCharArray(); 11 | char[] tCharArray = t.toCharArray(); 12 | 13 | 14 | int res = tCharArray[0] - 'a'; 15 | for (int i = 0; i < sLen; i++) { 16 | res ^= (sCharArray[i] - 'a'); 17 | } 18 | for (int i = 1; i < tLen; i++) { 19 | res ^= (tCharArray[i] - 'a'); 20 | } 21 | return (char) (res + 'a'); 22 | } 23 | } -------------------------------------------------------------------------------- /17-Hash-Table/待分类/0771-jewels-and-stones/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int numJewelsInStones(String J, String S) { 4 | boolean[] hashMap = new boolean[256]; 5 | for (char c : J.toCharArray()) { 6 | hashMap[c] = true; 7 | } 8 | 9 | int cnt = 0; 10 | for (char s : S.toCharArray()) { 11 | if (hashMap[s]) { 12 | cnt++; 13 | } 14 | } 15 | return cnt; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /18-prefix-sum/0523-continuous-subarray-sum/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public boolean checkSubarraySum(int[] nums, int k) { 4 | int len = nums.length; 5 | for (int left = 0; left < len - 1; left++) { 6 | // 大小至少为 2 7 | for (int right = left + 1; right < len; right++) { 8 | int sum = 0; 9 | for (int i = left; i <= right; i++) { 10 | sum += nums[i]; 11 | } 12 | if (sum == k || (k != 0 && sum % k == 0)) { 13 | return true; 14 | } 15 | } 16 | } 17 | return false; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /18-prefix-sum/0560-subarray-sum-equals-k/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 暴力解法:枚举左右边界(超时) 4 | // 时间复杂度:O(N^3) 5 | 6 | public int subarraySum(int[] nums, int k) { 7 | int len = nums.length; 8 | int count = 0; 9 | for (int left = 0; left < len; left++) { 10 | for (int right = left; right < len; right++) { 11 | 12 | int sum = 0; 13 | for (int i = left; i <= right; i++) { 14 | sum += nums[i]; 15 | } 16 | if (sum == k) { 17 | count++; 18 | } 19 | } 20 | } 21 | return count; 22 | } 23 | } -------------------------------------------------------------------------------- /18-prefix-sum/0560-subarray-sum-equals-k/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | // 暴力解法:固定了起点,可以通过 4 | // 时间复杂度:O(N^2) 5 | 6 | public int subarraySum(int[] nums, int k) { 7 | int count = 0; 8 | int len = nums.length; 9 | for (int left = 0; left < len; left++) { 10 | int sum = 0; 11 | // 区间里可能会有一些互相抵销的元素 12 | for (int right = left; right < len; right++) { 13 | sum += nums[right]; 14 | if (sum == k) { 15 | count++; 16 | } 17 | } 18 | } 19 | return count; 20 | } 21 | } -------------------------------------------------------------------------------- /18-prefix-sum/0974-subarray-sums-divisible-by-k/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 超时 4 | 5 | public int subarraysDivByK(int[] A, int K) { 6 | int len = A.length; 7 | int count = 0; 8 | for (int i = 0; i < len; i++) { 9 | for (int j = i; j < len; j++) { 10 | int sum = sum(A, i, j); 11 | if ((sum % K) == 0) { 12 | count++; 13 | } 14 | } 15 | } 16 | return count; 17 | } 18 | 19 | private int sum(int[] A, int left, int right) { 20 | int sum = 0; 21 | for (int i = left; i <= right; i++) { 22 | sum += A[i]; 23 | 24 | } 25 | return sum; 26 | } 27 | } -------------------------------------------------------------------------------- /18-prefix-sum/0974-subarray-sums-divisible-by-k/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | // 哈希表 4 | 5 | public int subarraysDivByK(int[] A, int K) { 6 | // 前缀和出现的次数 7 | // key: i 之前的前缀和,value:出现的次数 8 | int[] preSumCount = new int[K]; 9 | preSumCount[0] = 1; 10 | 11 | int preSum = 0; 12 | int res = 0; 13 | for (int value : A) { 14 | preSum += value; 15 | 16 | // (preSum % K + K) % K 这句话要解释清楚 17 | int remainder = (preSum % K + K) % K; 18 | int count = preSumCount[remainder]; 19 | res += count; 20 | 21 | preSumCount[remainder]++; 22 | } 23 | return res; 24 | } 25 | } -------------------------------------------------------------------------------- /18-prefix-sum/1248-count-number-of-nice-subarrays/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 方法一:前缀和 4 | 5 | public int numberOfSubarrays(int[] nums, int k) { 6 | int len = nums.length; 7 | // preSum[i] 前缀和为 i 出现的次数 8 | int[] preSum = new int[len + 1]; 9 | // 表示前缀和为 0 的个数为 1,1 是乘法单位元 10 | preSum[0] = 1; 11 | 12 | // 目前为止看到的奇数的个数 13 | int odd = 0; 14 | int res = 0; 15 | for (int num : nums) { 16 | odd += num & 1; 17 | if (odd >= k) { 18 | // 注意:有一个单位的偏移 19 | res += preSum[odd - k]; 20 | } 21 | preSum[odd]++; 22 | } 23 | return res; 24 | } 25 | } -------------------------------------------------------------------------------- /18-prefix-sum/1248-count-number-of-nice-subarrays/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public int numberOfSubarrays(int[] nums, int k) { 4 | int len = nums.length; 5 | int[] odd = new int[len + 2]; 6 | int ans = 0, cnt = 0; 7 | for (int i = 0; i < len; ++i) { 8 | if ((nums[i] & 1) != 0) { 9 | cnt++; 10 | odd[cnt] = i; 11 | } 12 | } 13 | odd[0] = -1; 14 | cnt++; 15 | odd[cnt] = len; 16 | for (int i = 1; i + k <= cnt; ++i) { 17 | ans += (odd[i] - odd[i - 1]) * (odd[i + k] - odd[i + k - 1]); 18 | } 19 | return ans; 20 | } 21 | } -------------------------------------------------------------------------------- /19-Breadth-First-Search/0133-clone-graph/src/Node.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.List; 3 | 4 | public class Node { 5 | 6 | public int val; 7 | public List neighbors; 8 | 9 | public Node() { 10 | val = 0; 11 | neighbors = new ArrayList(); 12 | } 13 | 14 | public Node(int _val) { 15 | val = _val; 16 | neighbors = new ArrayList(); 17 | } 18 | 19 | public Node(int _val, ArrayList _neighbors) { 20 | val = _val; 21 | neighbors = _neighbors; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /19-Breadth-First-Search/0515-find-largest-value-in-each-tree-row/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | int val; 3 | TreeNode left; 4 | TreeNode right; 5 | 6 | TreeNode(int x) { 7 | val = x; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /19-Breadth-First-Search/0637-average-of-levels-in-binary-tree/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } -------------------------------------------------------------------------------- /22-divide-and-conquer/0095-unique-binary-search-trees-ii/src/TreeNode.java: -------------------------------------------------------------------------------- 1 | public class TreeNode { 2 | int val; 3 | TreeNode left; 4 | TreeNode right; 5 | 6 | TreeNode(int x) { 7 | val = x; 8 | } 9 | } -------------------------------------------------------------------------------- /28-string/1-Basic/0008-string-to-integer-atoi/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public int myAtoi(String str) { 4 | if (str == null || str.length() == 0) { 5 | return 0; 6 | } 7 | str = str.trim(); 8 | int help = 0; 9 | if (str.charAt(0) != '-' || str.charAt(0) < '1' || str.charAt(0) > '9') { 10 | return 0; 11 | } 12 | for (int i = 1; i < str.length(); i++) { 13 | if (str.charAt(i) < '1' || str.charAt(i) > '9') { 14 | help = i; 15 | break; 16 | } 17 | } 18 | str = str.substring(0, help); 19 | return Integer.parseInt(str); 20 | } 21 | } -------------------------------------------------------------------------------- /28-string/1-Basic/0028-implement-strstr/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public int strStr(String haystack, String needle) { 4 | int hlen = haystack.length(); 5 | int nlen = needle.length(); 6 | if (nlen == 0) { 7 | return 0; 8 | } 9 | for (int i = 0; i <= hlen - nlen; i++) { 10 | if (needle.equals(haystack.substring(i, i + nlen))) { 11 | return i; 12 | } 13 | } 14 | return -1; 15 | } 16 | } -------------------------------------------------------------------------------- /28-string/1-Basic/0028-implement-strstr/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | // 调用 API 4 | 5 | public int strStr(String haystack, String needle) { 6 | int hlen = haystack.length(); 7 | int nlen = needle.length(); 8 | if (hlen == 0) { 9 | return -1; 10 | } 11 | if (nlen == 0) { 12 | return 0; 13 | } 14 | return haystack.indexOf(needle); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /28-string/1-Basic/0058-length-of-last-word/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int lengthOfLastWord(String s) { 4 | int len = s.length(); 5 | // 特别注意 "a " 这种特殊的测试用例 6 | // 特别注意 "b a ",因此,要使用 while 7 | while (len > 0 && s.charAt(len - 1) == ' ') { 8 | len--; 9 | } 10 | if (len == 0) { 11 | return 0; 12 | } 13 | 14 | int begin = -1; 15 | int index = 0; 16 | while (index < len) { 17 | char curChar = s.charAt(index); 18 | if (curChar == ' ') { 19 | begin = index; 20 | } 21 | index++; 22 | } 23 | return len - 1 - begin; 24 | } 25 | } -------------------------------------------------------------------------------- /28-string/1-Basic/0058-length-of-last-word/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public int lengthOfLastWord(String s) { 4 | int len = s.length(); 5 | while (len > 0 && s.charAt(len - 1) == ' ') { 6 | len--; 7 | } 8 | if (len == 0) { 9 | return 0; 10 | } 11 | int res = 0; 12 | while (len > 0 && s.charAt(len - 1) != ' ') { 13 | res++; 14 | len--; 15 | } 16 | return res; 17 | } 18 | } -------------------------------------------------------------------------------- /28-string/1-Basic/0387-first-unique-character-in-a-string/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 把数组当做哈希表用 4 | 5 | public int firstUniqChar(String s) { 6 | 7 | int[] hashMap = new int[26]; 8 | char[] charArray = s.toCharArray(); 9 | 10 | for (char c : charArray) { 11 | hashMap[c - 'a']++; 12 | } 13 | 14 | int len = s.length(); 15 | for (int i = 0; i < len; i++) { 16 | if (hashMap[charArray[i] - 'a'] == 1) { 17 | return i; 18 | } 19 | } 20 | return -1; 21 | } 22 | } -------------------------------------------------------------------------------- /28-string/1-Basic/0459-repeated-substring-pattern/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | public boolean repeatedSubstringPattern3(String s) { 4 | // 掐头去尾只要包含就可以了 5 | return ((s + s).substring(1, 2 * s.length() - 1).contains(s)); 6 | } 7 | } -------------------------------------------------------------------------------- /28-string/1-Basic/0521-longest-uncommon-subsequence-i/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 任何字符串本身都是一个子序列,空字符串是任何字符串的子序列。 4 | // 只需要判断两字符串是否相等,如果相等就返回 -1 ,不相等就返回较长的字符串长度。算是有一些坑的问题了,这道问题踩的人比较多。 5 | 6 | public int findLUSlength(String a, String b) { 7 | if (a != null && a.equals(b)) { 8 | return -1; 9 | } 10 | return Math.max(a.length(), b.length()); 11 | } 12 | } -------------------------------------------------------------------------------- /28-string/1-Basic/0657-robot-return-to-origin/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public boolean judgeCircle(String moves) { 4 | int x = 0; 5 | int y = 0; 6 | 7 | char[] charArray = moves.toCharArray(); 8 | for (char move : charArray) { 9 | if (move == 'U') { 10 | y--; 11 | } else if (move == 'D') { 12 | y++; 13 | } else if (move == 'L') { 14 | x--; 15 | } else if (move == 'R') { 16 | x++; 17 | } 18 | } 19 | return x == 0 && y == 0; 20 | } 21 | } --------------------------------------------------------------------------------