├── .gitignore ├── README.md ├── array ├── 0026-remove-duplicates-from-sorted-array │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0027-remove-element │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0057-insert-interval │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0066-plus-one │ └── src │ │ └── Solution.java ├── 0074-search-a-2d-matrix │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0075-sort-colors │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── 0075-sort-colors2 │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── 0080-remove-duplicates-from-sorted-array-ii │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0088-merge-sorted-array │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0169-majority-element │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 0189-rotate-array │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0215-kth-largest-element-in-an-array │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0215-kth-largest-element-in-an-array2 │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ ├── Solution6.java │ │ ├── Solution7.java │ │ ├── Solution8.java │ │ └── Solution9.java ├── 0229-majority-element-ii │ └── src │ │ └── Solution.java ├── 0283-move-zeroes │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0414-third-maximum-number │ └── src │ │ └── Solution.java ├── 0451-sort-characters-by-frequency │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0566-reshape-the-matrix │ └── src │ │ └── Solution.java ├── 0661-image-smoother │ └── src │ │ └── Solution.java ├── 0717-1-bit-and-2-bit-characters │ └── src │ │ └── Solution.java ├── 0792-number-of-matching-subsequences │ └── src │ │ ├── Main.java │ │ ├── Solution.java │ │ └── Solution2.java ├── 0840-magic-squares-in-grid(数组) │ └── src │ │ └── Solution.java ├── 0867-transpose-matrix(数组) │ └── src │ │ └── Solution.java ├── 0912-sort-an-array │ └── src │ │ ├── Shell.java │ │ ├── Solution.java │ │ ├── Solution10.java │ │ ├── Solution11.java │ │ ├── Solution12.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ ├── Solution6.java │ │ ├── Solution7.java │ │ ├── Solution8.java │ │ └── Solution9.java ├── 0989-add-to-array-form-of-integer │ └── src │ │ └── Solution.java └── 1010-pairs-of-songs-with-total-durations-divisible-by-60(数组) │ └── src │ └── Solution.java ├── backtracking ├── 0017-letter-combinations-of-a-phone-number │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ └── Solution6.java ├── 0022-generate-parentheses │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 0036-valid-sudoku │ └── src │ │ └── Solution.java ├── 0037-sudoku-solver │ └── src │ │ └── Solution.java ├── 0039-combination-sum │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 0039-combination-sum2 │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ └── Solution6.java ├── 0040-combination-sum-ii │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0040-combination-sum-ii2 │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0046-permutations │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ ├── Solution6.java │ │ └── Solution7.java ├── 0046-permutations2 │ └── src │ │ └── Solution.java ├── 0047-permutations-ii │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0051-n-queens │ └── src │ │ ├── Solution.java │ │ ├── Solution10.java │ │ ├── Solution11.java │ │ ├── Solution12.java │ │ ├── Solution13.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution5.java │ │ ├── Solution6.java │ │ ├── Solution7.java │ │ ├── Solution8.java │ │ └── Solution9.java ├── 0060-permutation-sequence │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── 0077-combinations │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 0078-subsets │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ ├── Solution6.java │ │ ├── Solution7.java │ │ └── Solution8.java ├── 0078-subsets2 │ └── src │ │ └── Solution.java ├── 0079-word-search │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0090-subsets-ii │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0090-subsets-ii2 │ └── src │ │ └── Solution.java ├── 0093-restore-ip-addresses │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── 0112-path-sum │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 0126-word-ladder-ii │ └── src │ │ ├── Main.java │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0127-word-ladder │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0130-surrounded-regions │ └── src │ │ └── Solution.java ├── 0131-palindrome-partitioning │ └── src │ │ ├── Main.java │ │ ├── Solution.java │ │ └── Solution2.java ├── 0139-word-break │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0140-word-break-ii │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0200-number-of-islands │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0200-number-of-islands2 │ └── src │ │ └── Solution.java ├── 0212-word-search-ii │ └── src │ │ └── Solution.java ├── 0216-combination-sum-iii │ └── src │ │ └── Solution.java ├── 0401-binary-watch │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0784-letter-case-permutation │ └── src │ │ └── Solution.java └── 0784-letter-case-permutation2 │ └── src │ ├── Solution.java │ ├── Solution2.java │ ├── Solution3.java │ └── Solution4.java ├── binary-indexed-tree └── 0307-range-sum-query-mutable(树状数组、线段树) │ └── src │ ├── NumArray.java │ ├── NumArray2.java │ ├── NumArray3.java │ └── NumArray4.java ├── binary-search-tree ├── 0094-binary-tree-inorder-traversal │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0098-validate-binary-search-tree │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 0102-binary-tree-level-order-traversal │ └── src │ │ └── Solution.java ├── 0107-binary-tree-level-order-traversal-ii │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0173-binary-search-tree-iterator │ └── src │ │ └── BSTIterator.java ├── 0230-kth-smallest-element-in-a-bst │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 0235-lowest-common-ancestor-of-a-binary-search-tree │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0538-convert-bst-to-greater-tree │ └── src │ │ └── Solution.java ├── 0653-two-sum-iv-input-is-a-bst │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0669-trim-a-binary-search-tree │ └── src │ │ ├── Solution.java │ │ └── Solution2.java └── 0783-minimum-distance-between-bst-nodes │ └── src │ ├── Solution.java │ └── Solution2.java ├── binary-search ├── 0004-median-of-two-sorted-arrays │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 0033-search-in-rotated-sorted-array │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── 0034-find-first-and-last-position-of-element-in-sorted-array │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0035-search-insert-position │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0035-search-insert-position2 │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── 0035-search-insert-position3 │ └── 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 │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ └── Solution6.java ├── 0154-find-minimum-in-rotated-sorted-array-ii │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0162-find-peak-element │ └── src │ │ └── Solution.java ├── 0240-search-a-2d-matrix-ii │ └── src │ │ ├── Main.java │ │ ├── Main2.java │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ ├── Solution6.java │ │ ├── Solution7.java │ │ ├── Solution8.java │ │ └── Solution9.java ├── 0274-h-index │ └── src │ │ └── Solution.java ├── 0275-h-index-ii │ └── src │ │ └── Solution.java ├── 0278-first-bad-version │ └── src │ │ └── Solution.java ├── 0278-first-bad-version2 │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0287-find-the-duplicate-number │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 0354-russian-doll-envelopes │ └── src │ │ └── Solution.java ├── 0374-guess-number-higher-or-lower │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0410-split-array-largest-sum │ └── src │ │ └── Solution.java ├── 0611-valid-triangle-number │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0658-find-k-closest-elements │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0658-find-k-closest-elements2 │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0704-binary-search │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 0704-binary-search2 │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0911-online-election │ └── src │ │ └── TopVotedCandidate.java └── 1095-find-in-mountain-array(二分查找) │ └── src │ └── Solution.java ├── bit-manipulation ├── 0029-divide-two-integers │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── 0052-n-queens-ii │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0136-single-number │ └── src │ │ └── Solution.java ├── 0137-single-number-ii │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0190-reverse-bits │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 0191-number-of-1-bits │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ ├── Solution6.java │ │ ├── Solution7.java │ │ └── Solution8.java ├── 0201-bitwise-and-of-numbers-range │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0204-count-primes │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0231-power-of-two │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── 0260-single-number-iii │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0326-power-of-three │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0338-counting-bits │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0342-power-of-four │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 0371-sum-of-two-integers(位运算) │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0389-find-the-difference(位运算、哈希表) │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0405-convert-a-number-to-hexadecimal(位运算) │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0421-maximum-xor-of-two-numbers-in-an-array │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 0442-find-all-duplicates-in-an-array │ └── src │ │ └── Solution.java ├── 0461-hamming-distance(位运算) │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0476-number-complement(位运算) │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0477-total-hamming-distance(位运算) │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0693-binary-number-with-alternating-bits │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java └── 0762-prime-number-of-set-bits-in-binary-representation │ └── src │ ├── Solution.java │ ├── Solution2.java │ ├── Solution3.java │ └── Solution4.java ├── breadth-first-search ├── 0207-course-schedule │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ └── Solution6.java ├── 0210-course-schedule-ii │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.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 ├── 0542-01-matrix │ └── src │ │ └── Solution.java └── 0690-employee-importance │ └── src │ ├── Solution.java │ └── Solution2.java ├── bucket-sort ├── 0041-first-missing-positive │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0268-missing-number │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0438-find-all-anagrams-in-a-string │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.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 └── 0448-find-all-numbers-disappeared-in-an-array2 │ └── src │ ├── Solution.java │ └── Solution2.java ├── dynamic-programming ├── 0005-longest-palindromic-substring │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── 0032-longest-valid-parentheses │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0053-maximum-subarray │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── 0053-maximum-subarray2 │ └── src │ │ └── Solution.java ├── 0062-unique-paths │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── 0063-unique-paths-ii2 │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0064-minimum-path-sum │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0070-climbing-stairs │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 0072-edit-distance │ └── src │ │ └── Solution.java ├── 0091-decode-ways │ └── src │ │ └── Solution.java ├── 0091-decode-ways2 │ └── src │ │ └── Solution.java ├── 0095-unique-binary-search-trees-ii │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution4.java ├── 0096-unique-binary-search-trees │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0115-distinct-subsequences │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0120-triangle │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0152-maximum-product-subarray │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0198-house-robber │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── 0213-house-robber-ii │ └── src │ │ └── Solution.java ├── 0264-ugly-number-ii │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0279-perfect-squares │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── 0300-longest-increasing-subsequence │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 0303-range-sum-query-immutable(动态规划) │ └── src │ │ ├── NumArray.java │ │ └── NumArray2.java ├── 0337-house-robber-iii │ └── src │ │ └── Solution.java ├── 0343-integer-break │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0343-integer-break2 │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ └── Solution6.java ├── 0376-wiggle-subsequence │ ├── 376.md │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0377-combination-sum-iv │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0416-partition-equal-subset-sum │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0474-ones-and-zeroes(动态规划) │ └── src │ │ └── Solution.java ├── 0509-fibonacci-number │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0518-coin-change-2 │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java └── 0746-min-cost-climbing-stairs │ └── src │ ├── Solution.java │ └── Solution2.java ├── greedy ├── 0012-integer-to-roman │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0055-jump-game │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── 0056-merge-intervals │ └── src │ │ └── Solution.java ├── 0392-is-subsequence(贪心算法、动态规划、二分查找) │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0402-remove-k-digits(栈、贪心算法) │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.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 │ │ └── Solution3.java └── 0455-assign-cookies │ └── src │ ├── Solution.java │ └── Solution2.java ├── hash-table ├── 0001-two-sum │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.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 ├── 0217-contains-duplicate │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0219-contains-duplicate-ii │ └── src │ │ └── Solution.java ├── 0220-contains-duplicate-iii │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── TreeSetDemo.java ├── 0242-valid-anagram │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.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 ├── 0352-data-stream-as-disjoint-intervals │ └── src │ │ └── SummaryRanges.java ├── 0387-first-unique-character-in-a-string(哈希表、字符串) │ └── src │ │ ├── Main.java │ │ ├── Solution.java │ │ └── Student.java ├── 0447-number-of-boomerangs(哈希表) │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0454-4sum-ii │ └── src │ │ └── Solution.java ├── 0560-subarray-sum-equals-k │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 0706-design-hashmap │ └── src │ │ └── MyHashMap.java └── 0720-longest-word-in-dictionary │ └── src │ ├── Solution.java │ └── Solution2.java ├── heap ├── 0295-find-median-from-data-stream │ └── src │ │ └── MedianFinder.java ├── 0313-super-ugly-number(堆、数学) │ └── src │ │ └── Solution.java └── 0347-top-k-frequent-elements │ └── src │ ├── Solution.java │ └── Solution2.java ├── linked-list ├── 0002-add-two-numbers │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0019-remove-nth-node-from-end-of-list │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0021-merge-two-sorted-lists │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0023-merge-k-sorted-lists │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── 0024-swap-nodes-in-pairs │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.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 │ │ └── Solution3.java ├── 0083-remove-duplicates-from-sorted-list │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0086-partition-list │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 0092-reverse-linked-list-ii │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.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 │ │ └── LRUCache2.java ├── 0147-insertion-sort-list │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0148-sort-list │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0160-intersection-of-two-linked-lists │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0203-remove-linked-list-elements │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.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 │ │ └── Solution2.java ├── 0328-odd-even-linked-list │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── 0445-add-two-numbers-ii │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0460-lfu-cache │ ├── README.md │ └── src │ │ ├── LFUCache.java │ │ ├── LFUCache2.java │ │ ├── LFUCache3.java │ │ └── Main.java └── 0876-middle-of-the-linked-list │ └── src │ └── Solution.java ├── math ├── 0007-reverse-integer │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── 0009-palindrome-number │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0168-excel-sheet-column-title │ └── src │ │ └── Solution.java ├── 0171-excel-sheet-column-number │ └── src │ │ └── Solution.java ├── 0263-ugly-number │ └── src │ │ ├── Main.java │ │ ├── Solution.java │ │ └── Solution2.java ├── 0268-missing-number │ └── src │ │ └── Solution.java ├── 0292-nim-game │ └── src │ │ └── Solution.java ├── 0367-valid-perfect-square(数学、二分查找) │ └── src │ │ └── Solution.java ├── 0397-integer-replacement │ ├── README.md │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ └── Solution6.java ├── 0400-nth-digit(数学) │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0507-perfect-number │ └── src │ │ └── Solution.java ├── 0633-sum-of-square-numbers │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0836-rectangle-overlap(数学) │ └── src │ │ └── Solution.java └── 0868-binary-gap(数学) │ └── src │ ├── Solution.java │ ├── Solution2.java │ └── Solution3.java ├── recursion ├── 0010-regular-expression-matching │ └── src │ │ ├── Solution.java │ │ └── Solution2.java └── 0038-count-and-say │ └── src │ ├── Solution.java │ ├── Solution2.java │ ├── Solution3.java │ └── Solution4.java ├── sliding-window ├── .idea │ ├── description.html │ ├── inspectionProfiles │ │ └── Project_Default.xml │ ├── markdown-navigator │ │ └── profiles_settings.xml │ ├── misc.xml │ ├── modules.xml │ ├── project-template.xml │ └── workspace.xml ├── 0003-longest-substring-without-repeating-characters │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution8.java ├── 0076-minimum-window-substring │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ └── Solution6.java ├── 0209-minimum-size-subarray-sum │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 0239-sliding-window-maximum │ └── src │ │ ├── Solution.java │ │ ├── Solution10.java │ │ ├── Solution11.java │ │ ├── Solution12.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ ├── Solution6.java │ │ ├── Solution7.java │ │ ├── Solution8.java │ │ └── Solution9.java ├── 0424-longest-repeating-character-replacement │ └── src │ │ └── Solution.java ├── 0438-find-all-anagrams-in-a-string │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0480-sliding-window-median │ └── src │ │ └── Solution.java ├── 0567-permutation-in-string │ └── src │ │ └── Solution.java ├── 0978-longest-turbulent-subarray │ └── src │ │ └── Solution.java └── 0992-subarrays-with-k-different-integers │ └── src │ ├── Solution.java │ └── Solution2.java ├── stack ├── 0020-valid-parentheses │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 0071-simplify-path │ └── src │ │ └── Solution.java ├── 0084-largest-rectangle-in-histogram │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0150-evaluate-reverse-polish-notation │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 0155-min-stack │ └── src │ │ ├── MinStack.java │ │ └── MinStack2.java ├── 0155-min-stack2 │ └── src │ │ ├── Main.java │ │ ├── Main2.java │ │ ├── MinStack.java │ │ ├── MinStack2.java │ │ └── MinStack2Debug.java ├── 0225-implement-stack-using-queues │ └── src │ │ └── MyStack.java ├── 0232-implement-queue-using-stacks │ └── src │ │ └── MyQueue.java ├── 0284-peeking-iterator │ └── src │ │ └── PeekingIterator.java ├── 0316-remove-duplicate-letters │ └── src │ │ ├── Solution.java │ │ └── Solution2.java └── 0341-flatten-nested-list-iterator │ └── src │ ├── NestedIterator.java │ ├── NestedIterator2.java │ └── NestedIterator3.java ├── string ├── 0006-zigzag-conversion │ └── src │ │ └── Solution.java ├── 0008-string-to-integer-atoi │ └── src │ │ └── Solution.java ├── 0010-regular-expression-matching │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 0013-roman-to-integer │ └── src │ │ └── Solution.java ├── 0014-longest-common-prefix │ └── src │ │ └── Solution.java ├── 0028-implement-strstr │ └── src │ │ ├── Solution.java │ │ └── Solution2.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 ├── 0125-valid-palindrome │ └── src │ │ └── Solution.java ├── 0165-compare-version-numbers │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0344-reverse-string │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0345-reverse-vowels-of-a-string │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0415-add-strings │ └── src │ │ └── Solution.java ├── 0443-string-compression(字符串) │ ├── README.md │ └── 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 ├── 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 ├── 0859-buddy-strings(字符串) │ └── src │ │ ├── Solution.java │ │ └── Solution2.java └── 1081-smallest-subsequence-of-distinct-characters(字符串) │ └── src │ ├── Solution.java │ └── Solution2.java ├── tree ├── 0100-same-tree │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0101-symmetric-tree │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── 0103-binary-tree-zigzag-level-order-traversal │ └── src │ │ └── Solution.java ├── 0104-maximum-depth-of-binary-tree │ └── src │ │ └── Solution.java ├── 0105-construct-binary-tree-from-preorder-and-inorder-traversal │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0106-construct-binary-tree-from-inorder-and-postorder-traversal │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ └── Solution5.java ├── 0107-binary-tree-level-order-traversal-ii │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0108-convert-sorted-array-to-binary-search-tree │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 0109-convert-sorted-list-to-binary-search-tree │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0110-balanced-binary-tree │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0111-minimum-depth-of-binary-tree │ └── src │ │ └── Solution.java ├── 0112-path-sum │ └── src │ │ └── Solution.java ├── 0113-path-sum-ii │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0129-sum-root-to-leaf-numbers │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0144-binary-tree-preorder-traversal │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 0145-binary-tree-postorder-traversal │ └── src │ │ └── Solution.java ├── 0199-binary-tree-right-side-view │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0222-count-complete-tree-nodes │ └── src │ │ └── Solution.java ├── 0226-invert-binary-tree │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ └── Solution4.java ├── 0236-lowest-common-ancestor-of-a-binary-tree │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0257-binary-tree-paths │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0297-serialize-and-deserialize-binary-tree(树、设计) │ └── src │ │ └── Codec.java ├── 0404-sum-of-left-leaves(树) │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0437-path-sum-iii(树) │ └── src │ │ └── Solution.java ├── 0450-delete-node-in-a-bst │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0652-find-duplicate-subtrees │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java └── 0687-longest-univalue-path │ └── src │ └── Solution.java ├── 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 ├── 0336-palindrome-pairs │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0648-replace-words │ └── src │ │ ├── Solution.java │ │ └── Solution2.java └── 0677-map-sum-pairs │ └── src │ ├── MapSum.java │ └── MapSum2.java ├── two-pointers ├── 0011-container-with-most-water │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0015-3sum │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ └── Solution3.java ├── 0016-3sum-closest │ └── src │ │ └── Solution.java ├── 0018-4sum │ └── src │ │ └── Solution.java ├── 0026-remove-duplicates-from-sorted-array │ └── src │ │ ├── Solution.java │ │ └── Solution2.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 ├── 0167-two-sum-ii-input-array-is-sorted │ └── src │ │ └── Solution.java ├── 0167-two-sum-ii-input-array-is-sorted2 │ └── src │ │ ├── Solution.java │ │ └── Solution2.java ├── 0334-increasing-triplet-subsequence │ └── src │ │ └── Solution.java └── 0713-subarray-product-less-than-k │ └── src │ ├── Solution.java │ └── Solution2.java ├── union-find └── 0547-friend-circles │ └── src │ └── Solution.java ├── 分治 └── 0315-count-of-smaller-numbers-after-self │ └── src │ ├── Solution.java │ ├── Solution2.java │ ├── Solution3.java │ ├── Solution4.java │ ├── Solution5.java │ ├── Solution6.java │ └── Solution7.java ├── 深度优先遍历 └── 1080-insufficient-nodes-in-root-to-leaf-paths(深度优先遍历) │ └── src │ ├── Solution.java │ └── Solution2.java ├── 股票问题 ├── 0121-best-time-to-buy-and-sell-stock │ └── src │ │ ├── Solution.java │ │ ├── Solution2.java │ │ ├── Solution3.java │ │ ├── Solution4.java │ │ ├── Solution5.java │ │ ├── Solution6.java │ │ ├── Solution7.java │ │ └── Solution8.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 │ ├── Solution10.java │ ├── Solution2.java │ ├── Solution4.java │ ├── Solution6.java │ ├── Solution7.java │ ├── Solution8.java │ └── Solution9.java └── 阿里巴巴Java开发手册(华山版).pdf /.gitignore: -------------------------------------------------------------------------------- 1 | */.idea/ 2 | */*/.idea/ 3 | */*/out/ 4 | *.iml 5 | origin/ 6 | 未分类/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 我的 LeetCode 题解(Java 实现) 2 | 3 | 我在做 LeetCode 问题的时候,同时给一些问题做了题解,下面是网址: 4 | 5 | https://liweiwei1419.github.io/leetcode-solution/ -------------------------------------------------------------------------------- /array/0026-remove-duplicates-from-sorted-array/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | 4 | public class Solution { 5 | 6 | public int removeDuplicates(int[] nums) { 7 | int len = nums.length; 8 | if (len < 2) { 9 | return len; 10 | } 11 | // 循环不变量:[0, j)是移除重复元素以后的数组 12 | int j = 1; 13 | for (int i = 1; i < len; i++) { 14 | if (nums[i] != nums[j - 1]) { 15 | // 注意顺序:先更新值,再递增脚标 16 | nums[j] = nums[i]; 17 | j++; 18 | } 19 | } 20 | return j; 21 | } 22 | 23 | public static void main(String[] args) { 24 | int[] nums = {1, 1, 2, 2, 2, 3, 3, 4, 4, 4}; 25 | Solution solution = new Solution(); 26 | int ret = solution.removeDuplicates(nums); 27 | System.out.println(ret); 28 | System.out.println(Arrays.toString(nums)); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /array/0026-remove-duplicates-from-sorted-array/src/Solution2.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | 4 | public class Solution2 { 5 | 6 | public int removeDuplicates(int[] nums) { 7 | int len = nums.length; 8 | if (len < 2) { 9 | return len; 10 | } 11 | // 循环不变量:[0, j] 是移除重复元素以后的数组 12 | int j = 0; 13 | for (int i = 1; i < len; i++) { 14 | if (nums[i] != nums[j]) { 15 | j++; 16 | nums[j] = nums[i]; 17 | } 18 | } 19 | return j + 1; 20 | } 21 | 22 | public static void main(String[] args) { 23 | int[] nums = {1, 1, 2, 2, 2, 3, 3, 4, 4, 4}; 24 | Solution2 solution = new Solution2(); 25 | int ret = solution.removeDuplicates(nums); 26 | System.out.println(ret); 27 | System.out.println(Arrays.toString(nums)); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /array/0027-remove-element/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public int removeElement(int[] nums, int val) { 4 | int len = nums.length; 5 | if (len == 0) { 6 | return 0; 7 | } 8 | int next = 0; 9 | for (int i = 0; i < len; i++) { 10 | if (nums[i] != val) { 11 | nums[next] = nums[i]; 12 | next++; 13 | } 14 | } 15 | return next; 16 | } 17 | 18 | public static void main(String[] args) { 19 | Solution solution = new Solution(); 20 | int result = solution.removeElement(new int[]{3, 2, 2, 3}, 2); 21 | System.out.println(result); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /array/0074-search-a-2d-matrix/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | public boolean searchMatrix(int[][] matrix, int target) { 4 | if (matrix == null || matrix.length == 0) { 5 | return false; 6 | } 7 | int row = matrix.length; 8 | int col = matrix[0].length; 9 | int begin = 0, end = row * col - 1; 10 | while (begin <= end) { 11 | int mid = (end - begin) / 2 + begin; 12 | int value = matrix[mid / col][mid % col]; 13 | if (value == target) { 14 | return true; 15 | } else if (value < target) { 16 | begin = mid + 1; 17 | } else { 18 | end = mid - 1; 19 | } 20 | } 21 | return false; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /array/0075-sort-colors/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | public void sortColors(int[] nums) { 4 | int[] counter = new int[3]; 5 | for (int num : nums) { 6 | counter[num] += 1; 7 | } 8 | int index = 0; 9 | for (int i = 0; i < 3; i++) { 10 | for (int j = 0; j < counter[i]; j++) { 11 | nums[index] = i; 12 | index += 1; 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /array/0075-sort-colors/src/Solution4.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/11/23 11:11 下午 4 | */ 5 | public class Solution4 { 6 | 7 | // 计数排序(不规范的代码示例) 8 | 9 | public void sortColors(int[] nums) { 10 | int[] cnt = new int[3]; 11 | for (int num:nums) { 12 | cnt[num]++; 13 | } 14 | int k = 0; 15 | for (int i = 0; i < 3; i++) { 16 | while (cnt[i]-- > 0) nums[k++] = i; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /array/0075-sort-colors/src/Solution5.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/11/23 11:11 下午 4 | */ 5 | public class Solution5 { 6 | 7 | // 计数排序(不规范的代码示例) 8 | 9 | public void sortColors(int[] nums) { 10 | int[] cnt = new int[3]; 11 | for (int num : nums) { 12 | cnt[num]++; 13 | } 14 | int k = 0; 15 | for (int i = 0; i < 3; i++) { 16 | int count = cnt[i]; 17 | for (int j = 0; j < count; j++) { 18 | nums[k] = i; 19 | k++; 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /array/0075-sort-colors2/src/Solution.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/12 11:38 上午 4 | */ 5 | public class Solution { 6 | 7 | // 非标准的计数排序 8 | 9 | public void sortColors(int[] nums) { 10 | int len = nums.length; 11 | if (len < 2) { 12 | return; 13 | } 14 | int[] count = new int[3]; 15 | for (int num : nums) { 16 | count[num]++; 17 | } 18 | int next = 0; 19 | for (int i = 0; i < 3; i++) { 20 | for (int j = 0; j < count[i]; j++) { 21 | nums[next] = i; 22 | next++; 23 | } 24 | } 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /array/0075-sort-colors2/src/Solution4.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | /** 4 | * @author liweiwei1419 5 | * @date 2019/10/12 12:51 下午 6 | */ 7 | public class Solution4 { 8 | 9 | public void sortColors(int[] nums) { 10 | Arrays.sort(nums); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /array/0080-remove-duplicates-from-sorted-array-ii/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/22 5:48 上午 4 | */ 5 | public class Solution2 { 6 | 7 | public int removeDuplicates(int[] nums) { 8 | int len = nums.length; 9 | if (len < 3) { 10 | return len; 11 | } 12 | 13 | // 循环不变量:[0, j) 是最终返回的数组 14 | // 初始化的时候,前 2 位有效 15 | // [0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4] 16 | // j 17 | // i 18 | // j 指向下一个要填写的元素 19 | int j = 2; 20 | for (int i = 2; i < len; i++) { 21 | if (nums[i] != nums[j - 2]) { 22 | nums[j] = nums[i]; 23 | j++; 24 | } 25 | } 26 | return j; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /array/0169-majority-element/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | 4 | public class Solution { 5 | 6 | /** 7 | * 排个序,在测试用例一定存在符合题目要求的数的时候,是可以这么用的 8 | * 9 | * @param nums 10 | * @return 11 | */ 12 | public int majorityElement(int[] nums) { 13 | int len = nums.length; 14 | Arrays.sort(nums); 15 | return nums[len / 2]; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /array/0169-majority-element/src/Solution3.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/6/29 下午4:50 4 | */ 5 | public class Solution3 { 6 | // 1,1,1,3,2 7 | public int majorityElement(int[] nums) { 8 | int len = nums.length; 9 | if (len == 1) { 10 | return nums[0]; 11 | } 12 | int count = 1; 13 | int res = nums[0]; 14 | for (int i = 1; i < len; i++) { 15 | if (nums[i] == res) { 16 | count++; 17 | } else { 18 | // 此时 nums[i] != res 19 | count--; 20 | if (count == 0) { 21 | res = nums[i]; 22 | // 这一步很关键 23 | count = 1; 24 | } 25 | } 26 | } 27 | return res; 28 | } 29 | } -------------------------------------------------------------------------------- /array/0169-majority-element/src/Solution4.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/11/2 9:13 上午 4 | */ 5 | public class Solution4 { 6 | 7 | // 已知:你可以假设数组是非空的,并且给定的数组总是存在众数。 8 | // 摩尔投票法,有点像玩消消乐一样 9 | 10 | public int majorityElement(int[] nums) { 11 | int res = 0; 12 | int count = 0; 13 | int len = nums.length; 14 | for (int i = 0; i < len; i++) { 15 | if (count == 0) { 16 | res = nums[i]; 17 | } 18 | if (res == nums[i]) { 19 | count++; 20 | } else { 21 | count--; 22 | } 23 | } 24 | return res; 25 | } 26 | } -------------------------------------------------------------------------------- /array/0215-kth-largest-element-in-an-array2/src/Solution4.java: -------------------------------------------------------------------------------- 1 | import java.util.PriorityQueue; 2 | 3 | /** 4 | * @author liwei 5 | * @date 18/7/2 下午7:45 6 | */ 7 | public class Solution4 { 8 | 9 | public int findKthLargest(int[] nums, int k) { 10 | int len = nums.length; 11 | // 最小堆 12 | PriorityQueue priorityQueue = new PriorityQueue<>(k + 1, (a, b) -> (a - b)); 13 | for (int i = 0; i < k; i++) { 14 | priorityQueue.add(nums[i]); 15 | } 16 | for (int i = k; i < len; i++) { 17 | priorityQueue.add(nums[i]); 18 | priorityQueue.poll(); 19 | } 20 | return priorityQueue.peek(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /array/0215-kth-largest-element-in-an-array2/src/Solution5.java: -------------------------------------------------------------------------------- 1 | import java.util.PriorityQueue; 2 | 3 | /** 4 | * @author liwei 5 | * @date 2019/8/10 10:57 AM 6 | */ 7 | public class Solution5 { 8 | public int findKthLargest(int[] nums, int k) { 9 | int len = nums.length; 10 | // 最小堆 11 | PriorityQueue priorityQueue = new PriorityQueue<>(k + 1, (a, b) -> (a - b)); 12 | for (int num : nums) { 13 | priorityQueue.add(num); 14 | if (priorityQueue.size() == k + 1) { 15 | priorityQueue.poll(); 16 | } 17 | } 18 | return priorityQueue.peek(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /array/0215-kth-largest-element-in-an-array2/src/Solution7.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | /** 4 | * @author liwei 5 | * @date 2019/8/10 1:47 PM 6 | */ 7 | public class Solution7 { 8 | 9 | public int findKthLargest(int[] nums, int k) { 10 | int len = nums.length; 11 | Arrays.sort(nums); 12 | return nums[len - k]; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /array/0283-move-zeroes/src/Solution.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/13 2:24 上午 4 | */ 5 | public class Solution { 6 | 7 | // 循环不变式:[0, i) 非零 8 | 9 | public void moveZeroes(int[] nums) { 10 | int len = nums.length; 11 | if (len < 2) { 12 | return; 13 | } 14 | 15 | int next = 0; 16 | for (int i = 0; i < len; i++) { 17 | if (nums[i] != 0) { 18 | nums[next] = nums[i]; 19 | next++; 20 | } 21 | } 22 | 23 | for (int i = next; i < len; i++) { 24 | nums[next] = 0; 25 | next++; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /array/0283-move-zeroes/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/13 2:25 上午 4 | */ 5 | public class Solution2 { 6 | 7 | // 循环不变式: 8 | // [0, notZero) 非零 9 | // [Zero, i) == 0 10 | // i == len 11 | 12 | public void moveZeroes(int[] nums) { 13 | int len = nums.length; 14 | if (len < 2) { 15 | return; 16 | } 17 | 18 | int notZero = 0; 19 | for (int i = 0; i < len; i++) { 20 | if (nums[i] != 0) { 21 | swap(nums, notZero, i); 22 | notZero++; 23 | } 24 | } 25 | } 26 | 27 | private void swap(int[] nums, int index1, int index2) { 28 | int temp = nums[index1]; 29 | nums[index1] = nums[index2]; 30 | nums[index2] = temp; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /array/0283-move-zeroes/src/Solution3.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/13 2:25 上午 4 | */ 5 | public class Solution3 { 6 | 7 | // 循环不变式: 8 | // [0, notZero] 非零 9 | // (Zero, i) == 0 10 | // i == len 11 | 12 | public void moveZeroes(int[] nums) { 13 | int len = nums.length; 14 | if (len < 2) { 15 | return; 16 | } 17 | int notZero = -1; 18 | for (int i = 0; i < len; i++) { 19 | if (nums[i] != 0) { 20 | notZero++; 21 | swap(nums, notZero, i); 22 | } 23 | } 24 | } 25 | 26 | private void swap(int[] nums, int index1, int index2) { 27 | int temp = nums[index1]; 28 | nums[index1] = nums[index2]; 29 | nums[index2] = temp; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /array/0912-sort-an-array/src/Shell.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/11/23 3:03 上午 4 | */ 5 | public class Shell { 6 | 7 | // 打表 8 | public static void main(String[] args) { 9 | int h = 1; 10 | while (h < 1000000000) { 11 | h = 3 * h + 1; 12 | System.out.println(h); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /array/0912-sort-an-array/src/Solution12.java: -------------------------------------------------------------------------------- 1 | import java.util.List; 2 | 3 | /** 4 | * @author liweiwei1419 5 | * @date 2019/11/23 2:54 上午 6 | */ 7 | public class Solution12 { 8 | 9 | // 堆排序 10 | 11 | public List sortArray(int[] nums) { 12 | return null; 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /array/0912-sort-an-array/src/Solution6.java: -------------------------------------------------------------------------------- 1 | import java.util.List; 2 | 3 | /** 4 | * @author liweiwei1419 5 | * @date 2019/11/22 12:09 上午 6 | */ 7 | public class Solution6 { 8 | 9 | // 快速排序 10 | 11 | public List sortArray(int[] nums) { 12 | return null; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /backtracking/0036-valid-sudoku/src/Solution.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/11/29 11:00 上午 4 | */ 5 | public class Solution { 6 | } 7 | -------------------------------------------------------------------------------- /backtracking/0078-subsets2/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.List; 3 | import java.util.Stack; 4 | 5 | /** 6 | * @author liweiwei1419 7 | * @date 2019/10/11 1:00 下午 8 | */ 9 | public class Solution { 10 | public List> subsets(int[] nums) { 11 | List> res = new ArrayList<>(); 12 | int len = nums.length; 13 | dfs(nums, 0, len, new Stack<>(), res); 14 | return res; 15 | } 16 | 17 | private void dfs(int[] nums, int start, int len, Stack stack, List> res) { 18 | res.add(new ArrayList<>(stack)); 19 | for (int i = start; i < len; i++) { 20 | stack.add(nums[i]); 21 | dfs(nums,i + 1,len,stack,res); 22 | stack.pop(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /backtracking/0112-path-sum/src/Solution.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @author liweiwei1419 4 | * @date 2019/10/12 6:42 下午 5 | */ 6 | 7 | class TreeNode { 8 | int val; 9 | TreeNode left; 10 | TreeNode right; 11 | 12 | TreeNode(int x) { 13 | val = x; 14 | } 15 | } 16 | 17 | public class Solution { 18 | 19 | public boolean hasPathSum(TreeNode root, int sum) { 20 | if (root == null) { 21 | return false; 22 | } 23 | if (root.left == null && root.right == null) { 24 | return sum == root.val; 25 | } 26 | 27 | boolean left = hasPathSum(root.left, sum - root.val); 28 | boolean right = hasPathSum(root.right, sum - root.val); 29 | return left || right; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /backtracking/0112-path-sum/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public boolean hasPathSum(TreeNode root, int sum) { 4 | if (root == null) { 5 | return false; 6 | } 7 | // 是叶子节点,这就是递归到底的情况了 8 | if (root.left == null && root.right == null) { 9 | return root.val == sum; 10 | } 11 | if (hasPathSum(root.left, sum - root.val)) { 12 | return true; 13 | } 14 | if (hasPathSum(root.right, sum - root.val)) { 15 | return true; 16 | } 17 | return false; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /backtracking/0112-path-sum/src/Solution3.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/7/3 下午9:30 4 | */ 5 | public class Solution3 { 6 | 7 | // 给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。 8 | 9 | public boolean hasPathSum(TreeNode root, int sum) { 10 | if (root == null) { 11 | return false; 12 | } 13 | assert root != null; 14 | // 如果没有左子树和右子树,就说明是根结点了 15 | if (root.left == null && root.right == null) { 16 | return root.val == sum; 17 | } 18 | boolean hasPathSum = false; 19 | if (root.left != null) { 20 | hasPathSum = hasPathSum || hasPathSum(root.left, sum - root.val); 21 | } 22 | if (root.right != null) { 23 | hasPathSum = hasPathSum || hasPathSum(root.right, sum - root.val); 24 | } 25 | return hasPathSum; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /backtracking/0112-path-sum/src/Solution4.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 既然标记为简单的问题,应该直觉想到的就是问题的解,且没有陷阱 3 | * https://leetcode-cn.com/problems/path-sum/description/ 4 | */ 5 | 6 | public class Solution4 { 7 | 8 | public boolean hasPathSum(TreeNode root, int sum) { 9 | if (root == null) { 10 | return false; 11 | } 12 | if (root.left == null && root.right == null) { 13 | return sum == root.val; 14 | } 15 | // root 不为空,并且左边和右边至少有一个有值 16 | return hasPathSum(root.left, sum - root.val) 17 | || hasPathSum(root.right, sum - root.val); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /backtracking/0126-word-ladder-ii/src/Main.java: -------------------------------------------------------------------------------- 1 | import java.util.HashSet; 2 | import java.util.Set; 3 | 4 | public class Main { 5 | 6 | public static void main(String[] args) { 7 | Set set1 = new HashSet<>(); 8 | set1.add("abc"); 9 | set1.add("aaa"); 10 | 11 | Set set2 = new HashSet<>(); 12 | set2.add("aaa"); 13 | 14 | set1.remove(set2); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /backtracking/0131-palindrome-partitioning/src/Main.java: -------------------------------------------------------------------------------- 1 | public class Main { 2 | 3 | public static void main(String[] args) { 4 | String s = "a.a..b............................"; 5 | int l = s.split("\\.").length; 6 | System.out.println(l); 7 | for (String ss:s.split("\\.")) { 8 | System.out.println(ss); 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /binary-search-tree/0098-validate-binary-search-tree/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | private boolean dfs(TreeNode node, int val, boolean ifLeft) { 4 | if (node == null) { 5 | return true; 6 | } 7 | if (ifLeft) { 8 | return node.val < val && dfs(node.left, val, ifLeft) && dfs(node.right, val, ifLeft); 9 | } else { 10 | return node.val > val && dfs(node.left, val, ifLeft) && dfs(node.right, val, ifLeft); 11 | 12 | } 13 | } 14 | 15 | /** 16 | * 按照 BST 的定义 17 | * @param root 18 | * @return 19 | */ 20 | public boolean isValidBST(TreeNode root) { 21 | if (root == null) { 22 | return true; 23 | } 24 | return dfs(root.left, root.val, true) && 25 | dfs(root.right, root.val, false) && 26 | isValidBST(root.left) && isValidBST(root.right); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /binary-search-tree/0098-validate-binary-search-tree/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | private boolean helper(TreeNode node, Integer min, Integer max) { 4 | if (node == null) { 5 | return true; 6 | } 7 | if (min != null && node.val <= min) { 8 | return false; 9 | } 10 | if (max != null && node.val >= max) { 11 | return false; 12 | } 13 | return helper(node.left, min, node.val) && helper(node.right, node.val, max); 14 | } 15 | 16 | /** 17 | * 18 | * @param root 19 | * @return 20 | */ 21 | public boolean isValidBST(TreeNode root) { 22 | if (root == null) { 23 | return true; 24 | } 25 | return helper(root, null, null); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /binary-search-tree/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 | } 30 | -------------------------------------------------------------------------------- /binary-search-tree/0230-kth-smallest-element-in-a-bst/src/Solution3.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/7/2 上午11:25 4 | */ 5 | public class Solution3 { 6 | 7 | private int res; 8 | 9 | // 使用中序遍历 10 | 11 | public int kthSmallest(TreeNode root, int k) { 12 | int[] kArr = {k}; 13 | inOrder(root, kArr); 14 | return res; 15 | } 16 | 17 | private void inOrder(TreeNode node, int[] k) { 18 | if (node == null) { 19 | return; 20 | } 21 | inOrder(node.left, k); 22 | k[0]--; 23 | if (k[0] == 0) { 24 | res = node.val; 25 | return; 26 | } 27 | inOrder(node.right, k); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /binary-search-tree/0235-lowest-common-ancestor-of-a-binary-search-tree/src/Solution.java: -------------------------------------------------------------------------------- 1 | class TreeNode { 2 | int val; 3 | TreeNode left; 4 | TreeNode right; 5 | 6 | TreeNode(int x) { 7 | val = x; 8 | } 9 | } 10 | 11 | public class Solution { 12 | 13 | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { 14 | if (root.val > p.val && root.val > q.val) { 15 | return lowestCommonAncestor(root.left, p, q); 16 | } 17 | if (root.val < p.val && root.val < q.val) { 18 | return lowestCommonAncestor(root.right, p, q); 19 | } 20 | return root; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /binary-search-tree/0235-lowest-common-ancestor-of-a-binary-search-tree/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 2019/8/29 4:04 PM 4 | */ 5 | public class Solution2 { 6 | 7 | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { 8 | // 其实这一步判断可以不用 9 | if (root == null || root == p || root == q) { 10 | return root; 11 | } 12 | if (p.val < root.val && q.val < root.val) { 13 | return lowestCommonAncestor(root.left, p, q); 14 | } else if (p.val > root.val && q.val > root.val) { 15 | return lowestCommonAncestor(root.right, p, q); 16 | } 17 | return root; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /binary-search-tree/0669-trim-a-binary-search-tree/src/Solution.java: -------------------------------------------------------------------------------- 1 | class TreeNode { 2 | int val; 3 | TreeNode left; 4 | TreeNode right; 5 | 6 | TreeNode(int x) { 7 | val = x; 8 | } 9 | } 10 | 11 | public class Solution { 12 | 13 | // 这道题其实还蛮有意思的 14 | 15 | public TreeNode trimBST(TreeNode root, int L, int R) { 16 | if (root == null) { 17 | return null; 18 | } 19 | if (root.val >= L && root.val <= R) { 20 | root.left = trimBST(root.left, L, root.val); 21 | root.right = trimBST(root.right, root.val, R); 22 | return root; 23 | } 24 | if (root.val > R) { 25 | return trimBST(root.left, L, R); 26 | } 27 | assert root.val < L; 28 | return trimBST(root.right, L, R); 29 | } 30 | } -------------------------------------------------------------------------------- /binary-search-tree/0669-trim-a-binary-search-tree/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 和 Solution 是一样的,可能更好理解一些吧 3 | */ 4 | public class Solution2 { 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 | } -------------------------------------------------------------------------------- /binary-search-tree/0783-minimum-distance-between-bst-nodes/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public int minDiffInBST(TreeNode root) { 4 | // 设置为 Integer 是为了检测出没有赋值的情况 5 | Integer[] preVal = new Integer[1]; 6 | int[] ret = new int[]{Integer.MAX_VALUE}; 7 | inOrder(root,preVal,ret); 8 | return ret[0]; 9 | } 10 | 11 | private void inOrder(TreeNode node, Integer[] preVal, int[] ret) { 12 | if (node == null) { 13 | return; 14 | } 15 | inOrder(node.left, preVal, ret); 16 | if (preVal[0] != null) { 17 | int diff = node.val - preVal[0]; 18 | ret[0] = Math.min(ret[0], diff); 19 | } 20 | // 注意,在这个位置更新之前的值 21 | preVal[0] = node.val; 22 | inOrder(node.right, preVal, ret); 23 | } 24 | } -------------------------------------------------------------------------------- /binary-search/0033-search-in-rotated-sorted-array/src/Solution4.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/11/28 9:47 上午 4 | */ 5 | public class Solution4 { 6 | 7 | public int search(int[] nums, int target) { 8 | int len = nums.length; 9 | for (int i = 0; i < len; i++) { 10 | if (nums[i] == target) { 11 | return i; 12 | } 13 | } 14 | return -1; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /binary-search/0035-search-insert-position/src/Solution.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/9/19 7:40 下午 4 | */ 5 | public class Solution { 6 | 7 | /** 8 | * 二分查找:反面思考 9 | * 10 | * @param nums 11 | * @param target 12 | * @return 13 | */ 14 | public int searchInsert(int[] nums, int target) { 15 | int len = nums.length; 16 | if (target > nums[len - 1]) { 17 | return len; 18 | } 19 | int left = 0; 20 | int right = len - 1; 21 | while (left < right) { 22 | int mid = (left + right) >>> 1; 23 | if (nums[mid] < target) { 24 | // 如果看到的这个数小于 target,那么它以及它之前的数都不是我们要找的 25 | left = mid + 1; 26 | } else { 27 | right = mid; 28 | } 29 | } 30 | return left; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /binary-search/0035-search-insert-position/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/9/19 7:40 下午 4 | */ 5 | public class Solution2 { 6 | 7 | /** 8 | * 二分查找:正面思考 9 | * 10 | * @param nums 11 | * @param target 12 | * @return 13 | */ 14 | public int searchInsert(int[] nums, int target) { 15 | int len = nums.length; 16 | if (target > nums[len - 1]) { 17 | return len; 18 | } 19 | int left = 0; 20 | int right = len - 1; 21 | while (left < right) { 22 | int mid = (left + right ) >>> 1; 23 | if (nums[mid] >= target) { 24 | // 个人的经验是这种思路比较容易出错,但不一定, 25 | // 我比较习惯于从反面思考,例如:要我找第 1 个大于等于 target 的数,我的思考就是小于 target 的数一定不是我想要的 26 | right = mid; 27 | } else { 28 | left = mid + 1; 29 | } 30 | } 31 | return left; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /binary-search/0035-search-insert-position/src/Solution3.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/9/19 8:08 下午 4 | */ 5 | public class Solution3 { 6 | 7 | /** 8 | * 不做特判,把特判归入二分查找的区间 9 | * 10 | * @param nums 11 | * @param target 12 | * @return 13 | */ 14 | public int searchInsert(int[] nums, int target) { 15 | int len = nums.length; 16 | int left = 0; 17 | // 因为有可能数组的最后一个元素的位置的下一个是我们要找的,故右边界是 len 18 | int right = len; 19 | while (left < right) { 20 | int mid = (left + right) >>> 1; 21 | if (nums[mid] < target) { 22 | left = mid + 1; 23 | } else { 24 | right = mid; 25 | } 26 | } 27 | return left; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /binary-search/0035-search-insert-position2/src/Solution4.java: -------------------------------------------------------------------------------- 1 | public class Solution4 { 2 | 3 | public int searchInsert(int[] nums, int target) { 4 | int len = nums.length; 5 | 6 | if (len == 0) { 7 | return 0; 8 | } 9 | 10 | int left = 0; 11 | int right = len; 12 | 13 | while (left < right) { 14 | // int mid = left + (right - left) / 2; 15 | int mid = (left + right) >>> 1; 16 | 17 | if (nums[mid] < target) { 18 | left = mid + 1; 19 | } else { 20 | right = mid; 21 | } 22 | } 23 | return left; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /binary-search/0035-search-insert-position2/src/Solution5.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 配图用 3 | * 4 | * @author liwei 5 | * @date 2019/6/27 10:58 AM 6 | */ 7 | public class Solution5 { 8 | 9 | public int searchInsert(int[] nums, int target) { 10 | int len = nums.length; 11 | if (nums[len - 1] < target) { 12 | return len; 13 | } 14 | 15 | int left = 0; 16 | int right = len - 1; 17 | 18 | while (left <= right) { 19 | int mid = (left + right) / 2; 20 | 21 | if (nums[mid] == target) { 22 | return mid; 23 | } else if (nums[mid] < target) { 24 | left = mid + 1; 25 | } else { 26 | right = mid - 1; 27 | } 28 | } 29 | return left; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /binary-search/0035-search-insert-position3/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/9 3:43 下午 4 | */ 5 | public class Solution2 { 6 | public int searchInsert(int[] nums, int target) { 7 | int len = nums.length; 8 | if (len == 0) { 9 | return -1; 10 | } 11 | // 在 [left, right] 里查找第 1 个大于等于 target 的元素 12 | int left = 0; 13 | int right = len; 14 | while (left < right) { 15 | // 在区间只剩下一个元素的时候(left == right),退出循环 16 | // 最后这元素我们不是不看,而是留到循环以后来看 17 | int mid = left + (right - left) / 2; 18 | if (nums[mid] < target) { 19 | // 接下来在 [mid + 1, right] 查找 20 | left = mid + 1; 21 | } else { 22 | // nums[mid] >= target, 23 | // 接下来在 [left, mid] 查找 24 | right = mid; 25 | } 26 | } 27 | return left; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /binary-search/0069-sqrtx/src/Solution.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 二分查找 3 | */ 4 | public class Solution { 5 | 6 | // 时间复杂度:O(log N),这里 N = x 7 | // 空间复杂度:O(1) 8 | 9 | public int mySqrt(int x) { 10 | long left = 0; 11 | long right = x; 12 | while (left < right) { 13 | long mid = (left + right + 1) / 2; 14 | if (mid > x / mid) { 15 | right = mid - 1; 16 | } else { 17 | left = mid; 18 | } 19 | } 20 | return (int) left; 21 | } 22 | 23 | public static void main(String[] args) { 24 | System.out.println(Integer.MAX_VALUE); 25 | } 26 | } -------------------------------------------------------------------------------- /binary-search/0069-sqrtx/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/9/19 7:03 下午 4 | */ 5 | public class Solution2 { 6 | 7 | /** 8 | * 方法二:牛顿法 9 | * 10 | * @param x 11 | * @return 12 | */ 13 | public int mySqrt(int x) { 14 | double cur = 1; 15 | while (true) { 16 | double pre = cur; 17 | cur = (x / cur + cur) / 2; 18 | if (Math.abs(pre - cur) < 1e-6) { 19 | break; 20 | } 21 | } 22 | return (int) cur; 23 | } 24 | 25 | public static void main(String[] args) { 26 | Solution2 solution2 = new Solution2(); 27 | int x = 8; 28 | int res = solution2.mySqrt(8); 29 | System.out.println(res); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /binary-search/0069-sqrtx/src/Solution3.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 二分查找 3 | */ 4 | public class Solution3 { 5 | 6 | // 时间复杂度:O(log N),这里 N = x 7 | // 空间复杂度:O(1) 8 | 9 | public int mySqrt(int x) { 10 | int left = 0; 11 | int right = x; 12 | while (left < right) { 13 | int mid = (left + right + 1) >>> 1; 14 | // 用除法避免类型转换 15 | if (mid > x / mid) { 16 | right = mid - 1; 17 | } else { 18 | left = mid; 19 | } 20 | } 21 | return left; 22 | } 23 | } -------------------------------------------------------------------------------- /binary-search/0074-search-a-2d-matrix/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | public boolean searchMatrix(int[][] matrix, int target) { 3 | int rows = matrix.length; 4 | // 特判 5 | if (rows == 0) { 6 | return false; 7 | } 8 | int cols = matrix[0].length; 9 | if (cols == 0) { 10 | return false; 11 | } 12 | 13 | int left = 0; 14 | // 最后一格的索引是矩阵元素个数 - 1 15 | int right = rows * cols - 1; 16 | while (left < right) { 17 | int mid = (left + right) >>> 1; 18 | if (matrix[mid / cols][mid % cols] < target) { 19 | left = mid + 1; 20 | } else { 21 | right = mid; 22 | } 23 | } 24 | return matrix[left / cols][left % cols] == target; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /binary-search/0153-find-minimum-in-rotated-sorted-array/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 典型的例子: 4 | // [4, 5, 6, 1, 2] 5 | // [1, 2, 3, 4, 5] 6 | // 只能使用中间数和右边界比较 7 | 8 | public int findMin(int[] nums) { 9 | int len = nums.length; 10 | // 特判 11 | if (len == 0) { 12 | return -1; 13 | } 14 | 15 | int left = 0; 16 | int right = len - 1; 17 | while (left < right) { 18 | int mid = (left + right) >>> 1; 19 | if (nums[mid] > nums[right]) { 20 | // 中间数一定不是"旋转排序数组的最小值" 21 | left = mid + 1; 22 | } else { 23 | right = mid; 24 | } 25 | } 26 | // 非空数组一定存在最小值,故无需后处理 27 | return nums[left]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /binary-search/0153-find-minimum-in-rotated-sorted-array/src/Solution3.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/9/24 10:55 下午 4 | */ 5 | public class Solution3 { 6 | 7 | public int findMin(int[] nums) { 8 | int len = nums.length; 9 | if (len == 0) { 10 | throw new IllegalArgumentException("数组为空,不存在最小值"); 11 | } 12 | int left = 0; 13 | int right = len - 1; 14 | while (left < right) { 15 | int mid = (left + right) >>> 1; 16 | if (nums[mid] < nums[right]) { 17 | // 右边是顺序数组 18 | // 6 7 1 2 3 19 | right = mid; 20 | } else { 21 | // 左边是顺序数组 22 | // 5 6 7 8 9 1 2 23 | left = mid + 1; 24 | } 25 | } 26 | return nums[left]; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /binary-search/0153-find-minimum-in-rotated-sorted-array/src/Solution5.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/9/24 10:58 下午 4 | */ 5 | public class Solution5 { 6 | 7 | // 分治法 8 | 9 | public int findMin(int[] nums) { 10 | int len = nums.length; 11 | if (len == 0) { 12 | throw new IllegalArgumentException("给出的数组为空,没有最小值"); 13 | } 14 | return findMin(nums, 0, len - 1); 15 | } 16 | 17 | public int findMin(int[] nums, int left, int right) { 18 | // 分治的方法,首先先要处理要递归终止的条件 19 | if (left + 1 >= right) { 20 | return Math.min(nums[left], nums[right]); 21 | } 22 | if (nums[left] < nums[right]) { 23 | return nums[left]; 24 | } 25 | 26 | int mid = (left + right) >>> 1; 27 | return Math.min(findMin(nums, left, mid), findMin(nums, mid + 1, right)); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /binary-search/0153-find-minimum-in-rotated-sorted-array/src/Solution6.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/9/24 10:53 下午 4 | */ 5 | public class Solution6 { 6 | 7 | // 暴力法 8 | 9 | public int findMin(int[] nums) { 10 | int len = nums.length; 11 | if (len == 0) { 12 | throw new IllegalArgumentException("数组为空"); 13 | } 14 | int minimum = nums[0]; 15 | for (int i = 1; i < len; i++) { 16 | minimum = Math.min(minimum, nums[i]); 17 | } 18 | return minimum; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /binary-search/0154-find-minimum-in-rotated-sorted-array-ii/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | public int findMin(int[] nums) { 4 | int len = nums.length; 5 | if (len == 0) { 6 | throw new IllegalArgumentException("数组为空,最小值不存在"); 7 | } 8 | return findMin(nums, 0, len - 1); 9 | } 10 | 11 | private int findMin(int[] nums, int left, int right) { 12 | if (left + 1 >= right) { 13 | return Math.min(nums[left], nums[right]); 14 | } 15 | if (nums[left] < nums[right]) { 16 | return nums[left]; 17 | } 18 | int mid = (left + right) >>> 1; 19 | return Math.min(findMin(nums, left, mid - 1), findMin(nums, mid, right)); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /binary-search/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) >>> 1; 11 | // 正好看到的是右边元素, 12 | // 分支排除了左边界,并且使用左中位数 13 | // 可以保证逻辑是完备的 14 | if (nums[mid] < nums[mid + 1]) { 15 | left = mid + 1; 16 | } else { 17 | right = mid; 18 | } 19 | } 20 | // 峰值元素一定存在,因此无需后处理 21 | return left; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /binary-search/0240-search-a-2d-matrix-ii/src/Main.java: -------------------------------------------------------------------------------- 1 | public class Main { 2 | 3 | // 二分法测试代码 4 | private static int binarySearch(int[] nums, int target) { 5 | int left = 0; 6 | int right = nums.length - 1; 7 | // 这里一定是等于号 8 | while (left < right) { 9 | int mid = left + (right - left) / 2; 10 | if (nums[mid] == target) { 11 | return mid; 12 | } else if (nums[mid] < target) { 13 | left = mid + 1; 14 | } else { 15 | right = mid - 1; 16 | } 17 | } 18 | return right; 19 | } 20 | 21 | public static void main(String[] args) { 22 | int[] nums = {1, 2, 3, 5, 8, 12, 13, 15}; 23 | int target = 14; 24 | // 我要返回的是 6 25 | 26 | int index = binarySearch(nums, target); 27 | System.out.println(nums[index]); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /binary-search/0240-search-a-2d-matrix-ii/src/Solution6.java: -------------------------------------------------------------------------------- 1 | public class Solution6 { 2 | 3 | public boolean searchMatrix(int[][] matrix, int target) { 4 | int row = matrix.length; 5 | if (row == 0) { 6 | return false; 7 | } 8 | int col = matrix[0].length; 9 | // 从左下角开始搜索 10 | int x = row - 1; 11 | int y = 0; 12 | // 每次考虑向右边走 13 | while (y < col) { 14 | // 向右边走之前,尽量向上走 15 | while (x >= 0 && matrix[x][y] > target) { 16 | x--; 17 | } 18 | // 走不动了,再向右边走 19 | if (x >= 0 && matrix[x][y] == target) { 20 | return true; 21 | } 22 | y++; 23 | } 24 | return false; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /binary-search/0240-search-a-2d-matrix-ii/src/Solution7.java: -------------------------------------------------------------------------------- 1 | public class Solution7 { 2 | 3 | public boolean searchMatrix(int[][] matrix, int target) { 4 | int row = matrix.length; 5 | if (row == 0) { 6 | return false; 7 | } 8 | int col = matrix[0].length; 9 | // 从右上角开始搜索 10 | int x = 0; 11 | int y = col - 1; 12 | // 每次考虑向下走 13 | while (x < row) { 14 | // 向下走之前,尽量向左边走 15 | while (y >= 0 && matrix[x][y] > target) { 16 | y--; 17 | } 18 | if (y >= 0 && matrix[x][y] == target) { 19 | return true; 20 | } 21 | x++; 22 | } 23 | return false; 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /binary-search/0240-search-a-2d-matrix-ii/src/Solution8.java: -------------------------------------------------------------------------------- 1 | public class Solution8 { 2 | 3 | public boolean searchMatrix(int[][] matrix, int target) { 4 | int row = matrix.length; 5 | if (row == 0) { 6 | return false; 7 | } 8 | int col = matrix[0].length; 9 | // 从右上角开始搜索 10 | int x = 0; 11 | int y = col - 1; 12 | // 每次考虑向左边走 13 | while (y >= 0) { 14 | // 向左边走之前,尽量向下走 15 | while (x < row && matrix[x][y] < target) { 16 | x++; 17 | } 18 | if (x < row && matrix[x][y] == target) { 19 | return true; 20 | } 21 | y--; 22 | } 23 | return false; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /binary-search/0274-h-index/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | public class Solution { 4 | 5 | public int hIndex(int[] citations) { 6 | int len = citations.length; 7 | if (len == 0) { 8 | return 0; 9 | } 10 | Arrays.sort(citations); 11 | if (citations[len - 1] == 0) { 12 | return 0; 13 | } 14 | 15 | int left = 0; 16 | int right = len - 1; 17 | while (left < right) { 18 | int mid = (left + right) >>> 1; 19 | if (citations[mid] < len - mid) { 20 | left = mid + 1; 21 | } else { 22 | right = mid; 23 | } 24 | 25 | } 26 | return len - left; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /binary-search/0278-first-bad-version/src/Solution.java: -------------------------------------------------------------------------------- 1 | /* The isBadVersion API is defined in the parent class VersionControl. 2 | boolean isBadVersion(int version); */ 3 | 4 | class VersionControl { 5 | boolean isBadVersion(int version) { 6 | // 为了本地编译通过,硬编码 7 | if (version < 13) { 8 | return false; 9 | } 10 | return true; 11 | } 12 | } 13 | 14 | public class Solution extends VersionControl { 15 | public int firstBadVersion(int n) { 16 | int left = 1; 17 | int right = n; 18 | while (left < right) { 19 | int mid = (left + right) >>> 1; 20 | if (!isBadVersion(mid)) { 21 | left = mid + 1; 22 | } else { 23 | right = mid; 24 | } 25 | } 26 | return left; 27 | } 28 | } -------------------------------------------------------------------------------- /binary-search/0278-first-bad-version2/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 | } 22 | -------------------------------------------------------------------------------- /binary-search/0278-first-bad-version2/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 | } -------------------------------------------------------------------------------- /binary-search/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 | if (index1 == index2) { 21 | return; 22 | } 23 | int temp = nums[index1]; 24 | nums[index1] = nums[index2]; 25 | nums[index2] = temp; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /binary-search/0287-find-the-duplicate-number/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | // 二分法:选左中位数 4 | 5 | public int findDuplicate(int[] nums) { 6 | int len = nums.length; 7 | int left = 1; 8 | int right = len - 1; 9 | while (left < right) { 10 | int mid = (left + right) >>> 1; 11 | int counter = 0; 12 | for (int num : nums) { 13 | if (num <= mid) { 14 | counter += 1; 15 | } 16 | } 17 | if (counter > mid) { 18 | right = mid; 19 | } else { 20 | left = mid + 1; 21 | } 22 | } 23 | return left; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /binary-search/0287-find-the-duplicate-number/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | // 二分法:选右中位数 4 | 5 | public int findDuplicate(int[] nums) { 6 | int len = nums.length; 7 | int left = 1; 8 | int right = len - 1; 9 | while (left < right) { 10 | int mid = (left + right + 1) >>> 1; 11 | int counter = 0; 12 | for (int num : nums) { 13 | if (num < mid) { 14 | counter += 1; 15 | } 16 | } 17 | if (counter >= mid) { 18 | // 如果小于 4 的个数等于 4 或者更多 19 | // 那么重复的数一定位于 1、2、3 20 | right = mid - 1; 21 | } else { 22 | left = mid; 23 | } 24 | } 25 | return left; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /binary-search/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 | 9 | while (left < right) { 10 | int mid = (left + right + 1) >>> 1; 11 | 12 | int count = 0; 13 | for (int num : nums) { 14 | if (num < mid) { 15 | count++; 16 | } 17 | } 18 | // 容易出错,需要仔细分析 19 | if (count < mid) { 20 | left = mid; 21 | } else { 22 | right = mid - 1; 23 | } 24 | } 25 | return left; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /binary-search/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 | 20 | public static void main(String[] args) { 21 | Solution2 solution2 = new Solution2(); 22 | int n = 10; 23 | int guessNumber = solution2.guessNumber(n); 24 | System.out.println(guessNumber); 25 | } 26 | } 27 | 28 | 29 | -------------------------------------------------------------------------------- /binary-search/0374-guess-number-higher-or-lower/src/Solution3.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/9/24 4:15 下午 4 | */ 5 | public class Solution3 extends GuessGame { 6 | 7 | public int guessNumber(int n) { 8 | int left = 1; 9 | int right = n; 10 | while (left < right) { 11 | // int mid = left + (right - left + 1) / 2; 12 | int mid = (left + right + 1) >>> 1; 13 | int guessNum = guess(mid); 14 | if (guessNum == -1) { 15 | // 目标数字小, mid 大 16 | right = mid - 1; 17 | } else { 18 | left = mid; 19 | } 20 | } 21 | // 最后剩下的数一定是所求,无需后处理 22 | return left; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /binary-search/0704-binary-search/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 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 | // 在 [left, right] 区间里查找 target 11 | int left = 0; 12 | int right = len - 1; 13 | while (left <= right) { 14 | 15 | int mid = (left + right) >>> 1; 16 | 17 | if (nums[mid] == target) { 18 | return mid; 19 | } else if (nums[mid] > target) { 20 | // 下一轮搜索区间:[left, mid - 1] 21 | right = mid - 1; 22 | } else { 23 | // 此时:nums[mid] < target 24 | // 下一轮搜索区间:[mid + 1, right] 25 | left = mid + 1; 26 | } 27 | } 28 | return -1; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /binary-search/0704-binary-search/src/Solution3.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 2019/7/11 11:45 PM 4 | */ 5 | public class Solution3 { 6 | 7 | // 把等于元素放在最后判断的二分查找算法 8 | 9 | public int search(int[] nums, int target) { 10 | int len = nums.length; 11 | int left = 0; 12 | int right = len - 1; 13 | while (left < right) { 14 | 15 | int mid = (left + right) >>> 1; 16 | 17 | if (nums[mid] < target) { 18 | // 下一轮搜索区间是:[mid + 1, right] 19 | left = mid + 1; 20 | } else { 21 | // 此时 nums[mid] >= target, 22 | // mid 的右边一定不存在 target,下一轮搜索区间是:[left, mid] 23 | right = mid; 24 | } 25 | } 26 | // 不要忘了单独做判断 27 | if (nums[left] == target) { 28 | return left; 29 | } 30 | return -1; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /binary-search/0704-binary-search2/src/Solution.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liweiwei1419/Learning-Algorithms-by-LeetCode/633cdfc78b70f0aaa2dd4ac8c1b6a9043d2c0149/binary-search/0704-binary-search2/src/Solution.java -------------------------------------------------------------------------------- /binary-search/0704-binary-search2/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/9 2:23 下午 4 | */ 5 | public class Solution2 { 6 | 7 | 8 | } 9 | -------------------------------------------------------------------------------- /bit-manipulation/0136-single-number/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int singleNumber(int[] nums) { 4 | int res = 0; 5 | for (int i = 0; i < nums.length; i++) { 6 | res ^= nums[i]; 7 | } 8 | return res; 9 | } 10 | 11 | public int singleNumber2(int[] nums) { 12 | int len = nums.length; 13 | if (len == 0) { 14 | throw new RuntimeException("数组元素为空,没有只出现一次的数字"); 15 | } 16 | int res = nums[0]; 17 | for (int i = 1; i < len; i++) { 18 | res ^= nums[i]; 19 | } 20 | return res; 21 | } 22 | 23 | public static void main(String[] args) { 24 | int[] nums = {2, 2, 1}; 25 | Solution solution = new Solution(); 26 | int singleNumber = solution.singleNumber(nums); 27 | System.out.println(singleNumber); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /bit-manipulation/0137-single-number-ii/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int singleNumber(int[] nums) { 4 | int res = 0; 5 | int mask = 1; 6 | for (int i = 0; i < 32; i++) { 7 | int count = 0; 8 | for (int num : nums) { 9 | if ((mask & num) != 0) { 10 | count++; 11 | } 12 | } 13 | if (count % 3 != 0) { 14 | res |= mask; 15 | } 16 | mask <<= 1; 17 | } 18 | return res; 19 | } 20 | 21 | public static void main(String[] args) { 22 | Solution solution = new Solution(); 23 | int[] nums = {1, 1, 1, 2, 2, 2, 3, 3, 3, 5}; 24 | // int[] nums = {-2, -2, 1, 1, -3, 1, -3, -3, -4, -2}; 25 | int singleNumber = solution.singleNumber(nums); 26 | System.out.println(singleNumber); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /bit-manipulation/0137-single-number-ii/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public int singleNumber(int[] nums) { 4 | int res = 0; 5 | int mask = 1; 6 | for (int i = 0; i < 32; i++) { 7 | mask = 1 << i; 8 | int count = 0; 9 | for (int num : nums) { 10 | if ((num & mask) != 0) { 11 | count++; 12 | } 13 | } 14 | if (count % 3 != 0) { 15 | res |= mask; 16 | } 17 | } 18 | return res; 19 | } 20 | 21 | public static void main(String[] args) { 22 | Solution2 solution2 = new Solution2(); 23 | int[] nums = {1, 1, 1, 2, 2, 2, 3, 3, 3, 5}; 24 | // int[] nums = {-2, -2, 1, 1, -3, 1, -3, -3, -4, -2}; 25 | int singleNumber = solution2.singleNumber(nums); 26 | System.out.println(singleNumber); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /bit-manipulation/0137-single-number-ii/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | public int singleNumber(int[] nums) { 4 | int res = 0; 5 | int mask = 1; 6 | for (int i = 0; i < 32; i++) { 7 | int count = 0; 8 | for (int num : nums) { 9 | if ((num & mask) != 0) { 10 | count++; 11 | } 12 | } 13 | if (count % 3 == 1) { 14 | res |= mask; 15 | } 16 | mask <<= 1; 17 | } 18 | return res; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /bit-manipulation/0190-reverse-bits/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | // you need treat n as an unsigned value 3 | 4 | public int reverseBits(int n) { 5 | // 0 其实不用特殊考虑 6 | if (n == 0) { 7 | return 0; 8 | } 9 | int res = 0; 10 | // 这里不能使用 while(n!=0) ,因为我们要考虑到最高位补 0 的情况 11 | for (int i = 0; i < 32; i++) { 12 | // 先左移,让出位置来 13 | res <<= 1; 14 | // 当前考虑的这个数位是 0 还是 1 15 | res += n & 1; 16 | n >>= 1; 17 | } 18 | return res; 19 | } 20 | 21 | public static void main(String[] args) { 22 | Solution2 solution2 = new Solution2(); 23 | int n = 43261596; 24 | int reverseBits = solution2.reverseBits(n); 25 | System.out.println(reverseBits); 26 | } 27 | } -------------------------------------------------------------------------------- /bit-manipulation/0190-reverse-bits/src/Solution3.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/7/1 下午7:47 4 | */ 5 | public class Solution3 { 6 | 7 | public int reverseBits(int n) { 8 | int res = 0; 9 | for (int i = 0; i < 32; i++) { 10 | res <<= 1; 11 | res += n & 1; 12 | n >>= 1; 13 | } 14 | return res; 15 | } 16 | 17 | public static void main(String[] args) { 18 | // 输入: 43261596 19 | // 输出: 964176192 20 | System.out.println(43261596); 21 | Solution3 solution3 = new Solution3(); 22 | int reverseBits = solution3.reverseBits(43261596); 23 | System.out.println(reverseBits); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /bit-manipulation/0190-reverse-bits/src/Solution4.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/15 7:05 下午 4 | */ 5 | public class Solution4 { 6 | 7 | // you need treat n as an unsigned value 8 | public int reverseBits2(int n) { 9 | int res = 0; 10 | 11 | for (int i = 0; i < 32; i++) { 12 | res <<= 1; 13 | res += n & 1; 14 | n >>= 1; 15 | } 16 | 17 | return res; 18 | } 19 | 20 | public int reverseBits(int n) { 21 | int res = 0; 22 | // 注意:外层循环是 32,里面那个是 31 23 | for (int i = 0; i < 32; i++) { 24 | if (((n >> i) & 1) != 0) { 25 | res |= (1 << (31 - i)); 26 | } 27 | } 28 | return res; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /bit-manipulation/0191-number-of-1-bits/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // you need to treat n as an unsigned value 4 | public int hammingWeight(int n) { 5 | char[] binaryArr = Integer.toBinaryString(n).toCharArray(); 6 | int count = 0; 7 | for (char b : binaryArr) { 8 | if (b == '1') { 9 | count++; 10 | } 11 | } 12 | return count; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /bit-manipulation/0191-number-of-1-bits/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | // you need to treat n as an unsigned value 4 | public int hammingWeight(int n) { 5 | return Integer.bitCount(n); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /bit-manipulation/0191-number-of-1-bits/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | // you need to treat n as an unsigned value 4 | public int hammingWeight(int n) { 5 | int count = 0; 6 | if (n < 0) { 7 | n = n & 0x7fffffff; 8 | count++; 9 | } 10 | while (n != 0) { 11 | if ((n & 1) == 1) { 12 | count++; 13 | } 14 | n = n >> 1; 15 | } 16 | return count; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /bit-manipulation/0191-number-of-1-bits/src/Solution4.java: -------------------------------------------------------------------------------- 1 | public class Solution4 { 2 | 3 | // you need to treat n as an unsigned value 4 | public int hammingWeight(int n) { 5 | int count = 0; 6 | while (n != 0) { 7 | n = n & (n-1); 8 | count++; 9 | } 10 | return count; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /bit-manipulation/0191-number-of-1-bits/src/Solution5.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/7/1 下午7:31 4 | */ 5 | public class Solution5 { 6 | 7 | public int hammingWeight(int n) { 8 | int mask = 1; 9 | int count = 0; 10 | for (int i = 0; i < 32; i++) { 11 | if ((n & mask) != 0) { 12 | count++; 13 | } 14 | mask <<= 1; 15 | } 16 | return count; 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /bit-manipulation/0191-number-of-1-bits/src/Solution6.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/7/1 下午7:38 4 | */ 5 | public class Solution6 { 6 | 7 | public int hammingWeight(int n) { 8 | int mask = 1; 9 | int count = 0; 10 | while (n != 0) { 11 | count += (n & mask); 12 | n >>>= 1; 13 | } 14 | return count; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /bit-manipulation/0191-number-of-1-bits/src/Solution8.java: -------------------------------------------------------------------------------- 1 | public class Solution8 { 2 | public int hammingWeight(int n) { 3 | int mask = 1; 4 | int count = 0; 5 | for (int i = 0; i < 32; i++) { 6 | if ((n & mask) != 0) { 7 | count++; 8 | } 9 | mask <<= 1; 10 | } 11 | return count; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /bit-manipulation/0201-bitwise-and-of-numbers-range/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | public int rangeBitwiseAnd(int m, int n) { 3 | int count = 0; 4 | while (m != n) { 5 | m >>= 1; 6 | n >>= 1; 7 | count++; 8 | } 9 | return m << count; 10 | } 11 | } -------------------------------------------------------------------------------- /bit-manipulation/0201-bitwise-and-of-numbers-range/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | /** 4 | * 利用了 n &= (n - 1) 一下能消死一大片 5 | * 6 | * @param m 7 | * @param n 8 | * @return 9 | */ 10 | public int rangeBitwiseAnd(int m, int n) { 11 | while (n > m) { 12 | n &= (n - 1); 13 | } 14 | return n; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /bit-manipulation/0231-power-of-two/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public boolean isPowerOfTwo(int n) { 4 | return n > 0 && (n & (n - 1)) == 0; 5 | } 6 | 7 | public static void main(String[] args) { 8 | Solution solution = new Solution(); 9 | boolean powerOfTwo = solution.isPowerOfTwo(4); 10 | System.out.println(powerOfTwo); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /bit-manipulation/0231-power-of-two/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/6/30 下午9:50 4 | */ 5 | public class Solution2 { 6 | 7 | public boolean isPowerOfTwo(int n) { 8 | if (n <= 0) { 9 | return false; 10 | } 11 | while (n % 2 == 0) { 12 | n /= 2; 13 | } 14 | return n == 1; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /bit-manipulation/0231-power-of-two/src/Solution3.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/6/30 下午9:52 4 | */ 5 | public class Solution3 { 6 | 7 | public boolean isPowerOfTwo(int n) { 8 | return n > 0 && Integer.toString(n, 2).matches("^10*$"); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /bit-manipulation/0231-power-of-two/src/Solution5.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/6/30 下午10:01 4 | */ 5 | public class Solution5 { 6 | 7 | public boolean isPowerOfTwo(int n) { 8 | // 1073741824 是小于 Integer.MAX_VALUE 中 2 的方幂的最大者 9 | // 该方法对于判定质数的方幂同样有效 10 | return n > 0 && 1073741824 % n == 0; 11 | } 12 | 13 | public static void main(String[] args) { 14 | Solution5 solution5 = new Solution5(); 15 | boolean solution5PowerOfTwo = solution5.isPowerOfTwo(1); 16 | System.out.println(solution5PowerOfTwo); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /bit-manipulation/0260-single-number-iii/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int[] singleNumber(int[] nums) { 4 | int axorb = 0; 5 | for (int num : nums) { 6 | axorb ^= num; 7 | } 8 | 9 | // n & (n - 1) 将从右边到左边的第 1 个 1 变成 0 10 | // n & (~(n - 1)) 只保留从右边到左边的第 1 个 1(本题使用技巧) 11 | int flag = axorb & (~(axorb - 1)); 12 | int[] res = new int[2]; 13 | for (int num : nums) { 14 | if ((num & flag) == 0) { 15 | res[0] ^= num; 16 | } else { 17 | res[1] ^= num; 18 | } 19 | } 20 | return res; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /bit-manipulation/0326-power-of-three/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.HashSet; 3 | import java.util.List; 4 | 5 | public class Solution { 6 | 7 | // 打表法 8 | public boolean isPowerOfThree(int n) { 9 | int[] nums = new int[]{1, 3, 9, 27, 81, 243, 729, 2187, 6561, 19683, 59049, 177147, 531441, 1594323, 4782969, 14348907, 43046721, 129140163, 387420489, 1162261467}; 10 | HashSet set = new HashSet<>(); 11 | for (int num : nums) { 12 | set.add(num); 13 | } 14 | return set.contains(n); 15 | } 16 | 17 | public static void main(String[] args) { 18 | List res = new ArrayList<>(); 19 | int n = 1; 20 | System.out.println(Integer.MAX_VALUE); 21 | while (n > 0 && n < 2147483647) { 22 | res.add(n); 23 | n = n * 3; 24 | } 25 | System.out.println(res); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /bit-manipulation/0326-power-of-three/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | /** 4 | * 因为 3 是质数,用 3 的方幂的最大值去整除这个待检测的数即可 5 | * 6 | * @param n 7 | * @return 8 | */ 9 | public boolean isPowerOfThree(int n) { 10 | return n > 0 && 1162261467 % n == 0; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /bit-manipulation/0326-power-of-three/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | /** 4 | * 转换成一个 3 进制的数,它的字符串表示一定是以 1 开头,后面全部是 0 5 | * 6 | * @param n 7 | * @return 8 | */ 9 | public boolean isPowerOfThree(int n) { 10 | return n > 0 && Integer.toString(n, 3).matches("^10*$"); 11 | } 12 | 13 | public static void main(String[] args) { 14 | int num = 27; 15 | System.out.println(Integer.toString(num, 3)); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /bit-manipulation/0338-counting-bits/src/Solution.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public int[] countBits(int num) { 3 | int[] res = new int[num + 1]; 4 | for (int i = 0; i <= num; i++) { 5 | res[i] = Integer.bitCount(i); 6 | } 7 | return res; 8 | } 9 | } -------------------------------------------------------------------------------- /bit-manipulation/0338-counting-bits/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public int[] countBits(int num) { 4 | int[] ret = new int[num + 1]; 5 | for (int i = 0; i <= num; i++) { 6 | ret[i] = bitCount(i); 7 | } 8 | return ret; 9 | } 10 | 11 | private int bitCount(int num) { 12 | int count = 0; 13 | while (num != 0) { 14 | num = num & (num - 1); 15 | count++; 16 | } 17 | return count; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /bit-manipulation/0338-counting-bits/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | public int[] countBits(int num) { 4 | int[] dp = new int[num + 1]; 5 | dp[0] = 0; 6 | for (int i = 1; i <= num; i++) { 7 | // 特判,很重要,只有 1 个的话,就直接是 1 8 | if ((i & (i - 1)) == 0) { 9 | dp[i] = 1; 10 | continue; 11 | } 12 | dp[i] = dp[i - 1] + 1; 13 | } 14 | return dp; 15 | } 16 | 17 | public static void main(String[] args) { 18 | for (int i = 0; i < 16; i++) { 19 | System.out.println(String.format("%04d", Integer.parseInt(Integer.toBinaryString(i)))); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /bit-manipulation/0342-power-of-four/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public boolean isPowerOfFour(int num) { 4 | if (num <= 0) { 5 | return false; 6 | } 7 | String binaryString = Integer.toBinaryString(num); 8 | int len = binaryString.length(); 9 | // 二进制的长度是奇数,即后面 0 的个数是偶数 10 | return len % 2 == 1 && (num & 1 << (len - 1)) == num; 11 | } 12 | 13 | public static void main(String[] args) { 14 | Solution solution = new Solution(); 15 | boolean powerOfFour = solution.isPowerOfFour(-2147483648); 16 | System.out.println(powerOfFour); 17 | } 18 | } -------------------------------------------------------------------------------- /bit-manipulation/0342-power-of-four/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/6/30 下午4:54 4 | */ 5 | public class Solution2 { 6 | 7 | public boolean isPowerOfFour(int num) { 8 | return num > 0 && (num & (num - 1)) == 0 && (num - 1) % 3 == 0; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /bit-manipulation/0342-power-of-four/src/Solution3.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/6/30 下午6:16 4 | */ 5 | public class Solution3 { 6 | 7 | /** 8 | * 转换成四进制数 9 | * @param num 10 | * @return 11 | */ 12 | public boolean isPowerOfFour(int num) { 13 | return num > 0 && Integer.toString(num,4).matches("^10*$"); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /bit-manipulation/0342-power-of-four/src/Solution4.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/6/30 下午7:33 4 | */ 5 | public class Solution4 { 6 | 7 | public boolean isPowerOfFour(int num) { 8 | if (num <= 0) { 9 | return false; 10 | } 11 | while (num % 4 == 0) { 12 | num /= 4; 13 | } 14 | return num == 1; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /bit-manipulation/0371-sum-of-two-integers(位运算)/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int getSum(int a, int b) { 4 | int sum; 5 | while (true) { 6 | sum = a ^ b; 7 | int carry = a & b; 8 | if (carry == 0) { 9 | break; 10 | } 11 | a = sum; 12 | b = carry << 1; 13 | } 14 | return sum; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /bit-manipulation/0371-sum-of-two-integers(位运算)/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public int getSum(int a, int b) { 4 | int sum; 5 | int carry; 6 | do { 7 | sum = a ^ b; 8 | carry = a & b; 9 | 10 | a = sum; 11 | b = carry << 1; 12 | } while (carry != 0); 13 | return sum; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /bit-manipulation/0371-sum-of-two-integers(位运算)/src/Solution3.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 练习 3 | * 4 | * @author liwei 5 | * @date 18/7/1 下午5:49 6 | */ 7 | public class Solution3 { 8 | 9 | public int getSum(int a, int b) { 10 | int sum = 0; 11 | int carry = 0; 12 | while (true) { 13 | sum = a ^ b; 14 | // 括号不能丢 15 | carry = (a & b) << 1; 16 | if (carry == 0) { 17 | break; 18 | } 19 | a = sum; 20 | b = carry; 21 | } 22 | return sum; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /bit-manipulation/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 | int res = t.charAt(0) - 'a'; 10 | for (int i = 0; i < slen; i++) { 11 | res ^= (s.charAt(i) - 'a'); 12 | } 13 | for (int i = 1; i < tlen; i++) { 14 | res ^= (t.charAt(i) - 'a'); 15 | } 16 | return (char) (res + 'a'); 17 | } 18 | 19 | public static void main(String[] args) { 20 | String s = "abcd"; 21 | String t = "abcde"; 22 | Solution solution = new Solution(); 23 | char theDifference = solution.findTheDifference(s, t); 24 | System.out.println(theDifference); 25 | } 26 | } -------------------------------------------------------------------------------- /bit-manipulation/0389-find-the-difference(位运算、哈希表)/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | // 在编写注释的过程中发现,其实 char 就是整型数字,因此根本不用做转换 4 | 5 | public char findTheDifference(String s, String t) { 6 | int slen = s.length(); 7 | int tlen = t.length(); 8 | int res = t.charAt(0); 9 | for (int i = 0; i < slen; i++) { 10 | res ^= (s.charAt(i)); 11 | } 12 | for (int i = 1; i < tlen; i++) { 13 | res ^= (t.charAt(i)); 14 | } 15 | return (char) (res); 16 | } 17 | 18 | public static void main(String[] args) { 19 | String s = "abcd"; 20 | String t = "abcde"; 21 | Solution2 solution = new Solution2(); 22 | char theDifference = solution.findTheDifference(s, t); 23 | System.out.println(theDifference); 24 | } 25 | } -------------------------------------------------------------------------------- /bit-manipulation/0461-hamming-distance(位运算)/src/Solution.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/7/1 下午4:03 4 | */ 5 | public class Solution { 6 | 7 | public int hammingDistance(int x, int y) { 8 | int a = x ^ y; 9 | int count = 0; 10 | while (a != 0) { 11 | a = a & (a - 1); 12 | count++; 13 | } 14 | return count; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /bit-manipulation/0461-hamming-distance(位运算)/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | public int hammingDistance(int x, int y) { 3 | int a = x ^ y; 4 | // 接下来统计 a 这个数二进制中 1 的个数 5 | int count = 0; 6 | while (a != 0) { 7 | a = a & (a - 1); 8 | count++; 9 | } 10 | return count; 11 | } 12 | } -------------------------------------------------------------------------------- /bit-manipulation/0477-total-hamming-distance(位运算)/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/7/1 上午11:59 4 | */ 5 | public class Solution2 { 6 | 7 | public int totalHammingDistance(int[] nums) { 8 | int len = nums.length; 9 | int mask = 1; 10 | int res = 0; 11 | for (int i = 0; i < 32; i++) { 12 | // 0 的个数 13 | int zeros = 0; 14 | for (int num : nums) { 15 | if ((num & mask) == 0) { 16 | zeros++; 17 | } 18 | } 19 | res += ((len - zeros) * zeros); 20 | mask <<= 1; 21 | } 22 | return res; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /bit-manipulation/0693-binary-number-with-alternating-bits/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/6/29 下午8:43 4 | */ 5 | public class Solution2 { 6 | 7 | public boolean hasAlternatingBits(int n) { 8 | String nStr = Integer.toBinaryString(n); 9 | int len = nStr.length(); 10 | for (int i = 0; i < len - 1; i++) { 11 | if (nStr.charAt(i) == nStr.charAt(i + 1)) { 12 | return false; 13 | } 14 | } 15 | return true; 16 | } 17 | 18 | public static void main(String[] args) { 19 | Solution2 solution2 = new Solution2(); 20 | int n = 5; 21 | solution2.hasAlternatingBits(n); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /bit-manipulation/0693-binary-number-with-alternating-bits/src/Solution3.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/6/29 下午9:05 4 | */ 5 | public class Solution3 { 6 | 7 | public boolean hasAlternatingBits(int n) { 8 | String nStr = Integer.toBinaryString(n); 9 | // 因为是正数,所以一定以 1 开头 10 | return nStr.matches("(10)*1?"); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /bit-manipulation/0762-prime-number-of-set-bits-in-binary-representation/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 4 | // 1、找到所有介于 L 和 R 之间的数的二进制表示; 5 | // 2、判断每个二进制数表示中 1 的个数是否为质数; 6 | // 3、求为质数的个数。 7 | 8 | public int countPrimeSetBits(int L, int R) { 9 | // int 类型的二进制表示 1 的个数最多是 32 10 | // 所以 32 以内的质数个数完全可以打表列举出来 11 | boolean[] isPrime = new boolean[32]; 12 | int[] primes = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31}; 13 | 14 | // 质数的个数作为索引,是不是质数体现在索引对应的值 15 | for (int prime : primes) { 16 | isPrime[prime] = true; 17 | } 18 | int res = 0; 19 | for (int i = L; i <= R; i++) { 20 | if (isPrime[Integer.bitCount(i)]) { 21 | res++; 22 | } 23 | } 24 | return res; 25 | } 26 | } 27 | 28 | 29 | -------------------------------------------------------------------------------- /bit-manipulation/0762-prime-number-of-set-bits-in-binary-representation/src/Solution4.java: -------------------------------------------------------------------------------- 1 | public class Solution4 { 2 | 3 | public int countPrimeSetBits(int L, int R) { 4 | boolean[] primes = new boolean[32]; 5 | int[] primeNums = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31}; 6 | for (int prime : primeNums) { 7 | primes[prime] = true; 8 | } 9 | int res = 0; 10 | for (int i = L; i <= R; i++) { 11 | int bitCount = 0; 12 | int num = i; 13 | while (num != 0) { 14 | num = num & (num - 1); 15 | bitCount++; 16 | } 17 | if (primes[bitCount]) { 18 | res++; 19 | } 20 | } 21 | return res; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /bucket-sort/0041-first-missing-positive/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public int firstMissingPositive(int[] nums) { 4 | int len = nums.length; 5 | for (int i = 0; i < len; i++) { 6 | while (nums[i] > 0 && nums[i] <= len && nums[nums[i] - 1] != nums[i]) { 7 | swap(nums, nums[i] - 1, i); 8 | } 9 | } 10 | for (int i = 0; i < len; i++) { 11 | if (nums[i] - 1 != i) { 12 | return i + 1; 13 | } 14 | } 15 | return len + 1; 16 | } 17 | 18 | private void swap(int[] nums, int index1, int index2) { 19 | if (index1 == index2) { 20 | return; 21 | } 22 | nums[index1] = nums[index1] ^ nums[index2]; 23 | nums[index2] = nums[index1] ^ nums[index2]; 24 | nums[index1] = nums[index1] ^ nums[index2]; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /bucket-sort/0268-missing-number/src/Solution.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/4 3:47 下午 4 | */ 5 | public class Solution { 6 | 7 | public int missingNumber(int[] nums) { 8 | int len = nums.length; 9 | 10 | int sum = 0; 11 | for (int i = 1; i <= len; i++) { 12 | sum += i; 13 | } 14 | 15 | for (int i = 0; i < len; i++) { 16 | sum -= nums[i]; 17 | } 18 | return sum; 19 | } 20 | 21 | public static void main(String[] args) { 22 | int[] nums = {9, 6, 4, 2, 3, 5, 7, 0, 1}; 23 | 24 | Solution solution = new Solution(); 25 | int res = solution.missingNumber(nums); 26 | System.out.println(res); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /bucket-sort/0268-missing-number/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/4 3:49 下午 4 | */ 5 | public class Solution2 { 6 | 7 | public int missingNumber(int[] nums) { 8 | int len = nums.length; 9 | int res = 0; 10 | 11 | for (int i = 0; i < len; i++) { 12 | res ^= nums[i]; 13 | } 14 | 15 | for (int i = 1; i <= len; i++) { 16 | res ^= i; 17 | } 18 | 19 | return res; 20 | } 21 | 22 | public static void main(String[] args) { 23 | int[] nums = {9, 6, 4, 2, 3, 5, 7, 0, 1}; 24 | 25 | Solution2 solution2 = new Solution2(); 26 | int res = solution2.missingNumber(nums); 27 | System.out.println(res); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /bucket-sort/0448-find-all-numbers-disappeared-in-an-array/src/Solution4.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.List; 3 | 4 | public class Solution4 { 5 | 6 | public List findDisappearedNumbers(int[] nums) { 7 | List res = new ArrayList<>(); 8 | int len = nums.length; 9 | if (len == 0) { 10 | return res; 11 | } 12 | int[] postion = new int[len + 1]; 13 | for (int num : nums) { 14 | if (postion[num] == 0) { 15 | postion[num] = num; 16 | } 17 | } 18 | for (int i = 1; i < len + 1; i++) { 19 | if (postion[i] == 0) { 20 | res.add(i); 21 | } 22 | } 23 | return res; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /dynamic-programming/0053-maximum-subarray/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | /** 4 | * 和 Solution 一样,空间复杂度更小 5 | * 时间复杂度:O(n) 6 | * 空间复杂度:O(1) 7 | */ 8 | public int maxSubArray(int[] nums) { 9 | int len = nums.length; 10 | if (len == 0) { 11 | return 0; 12 | } 13 | // 起名叫 pre 表示的意思是“上一个状态”的值 14 | int pre = nums[0]; 15 | int res = pre; 16 | for (int i = 1; i < len; i++) { 17 | pre = Math.max(nums[i], pre + nums[i]); 18 | res = Math.max(res, pre); 19 | } 20 | return res; 21 | } 22 | 23 | public static void main(String[] args) { 24 | int[] nums = {-2, 1, -3, 4, -1, 2, 1, -5, 4}; 25 | Solution2 solution = new Solution2(); 26 | int maxSubArray = solution.maxSubArray(nums); 27 | System.out.println(maxSubArray); 28 | } 29 | } -------------------------------------------------------------------------------- /dynamic-programming/0053-maximum-subarray2/src/Solution.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/10 9:29 下午 4 | */ 5 | public class Solution { 6 | 7 | public int maxSubArray(int[] nums) { 8 | int len = nums.length; 9 | int res = Integer.MIN_VALUE; 10 | for (int i = 0; i < len; i++) { 11 | int sum = 0; 12 | for (int j = i; j < len; j++) { 13 | sum += nums[j]; 14 | res = Math.max(res, sum); 15 | } 16 | } 17 | return res; 18 | } 19 | 20 | public static void main(String[] args) { 21 | int[] nums = {-2, 1, -3, 4, -1, 2, 1, -5, 4}; 22 | Solution solution = new Solution(); 23 | int res = solution.maxSubArray(nums); 24 | System.out.println(res); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /dynamic-programming/0062-unique-paths/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | // i,j 的值来源:上面和前面的值之和 4 | 5 | public int uniquePaths(int m, int n) { 6 | if (m < 0 || n < 0) { 7 | return 0; 8 | } 9 | int[] dp = new int[n]; 10 | dp[0] = 1; 11 | for (int i = 0; i < m; i++) { 12 | for (int j = 1; j < n; j++) { 13 | dp[j] += dp[j - 1]; 14 | } 15 | } 16 | return dp[n - 1]; 17 | } 18 | 19 | public static void main(String[] args) { 20 | Solution3 solution = new Solution3(); 21 | int m = 7; 22 | int n = 3; 23 | int uniquePaths = solution.uniquePaths(m, n); 24 | System.out.println(uniquePaths); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /dynamic-programming/0070-climbing-stairs/src/Solution.java: -------------------------------------------------------------------------------- 1 | // https://leetcode-cn.com/problems/climbing-stairs/description/ 2 | 3 | public class Solution { 4 | 5 | private int[] cache; 6 | 7 | private int calcways(int n) { 8 | if (cache[n] != 0) { 9 | return cache[n]; 10 | } 11 | if (n == 0) { 12 | return 1; 13 | } 14 | if (n == 1) { 15 | return 1; 16 | } 17 | cache[n] = calcways(n - 1) + calcways(n - 2); 18 | return cache[n]; 19 | } 20 | 21 | public int climbStairs(int n) { 22 | cache = new int[n + 1]; 23 | return calcways(n); 24 | } 25 | 26 | public static void main(String[] args) { 27 | // write your code here 28 | Solution solution = new Solution(); 29 | int climbStairs = solution.climbStairs(2); 30 | System.out.println(climbStairs); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /dynamic-programming/0070-climbing-stairs/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public int climbStairs(int n) { 4 | int[] dp = new int[n + 1]; 5 | dp[0] = 1; 6 | dp[1] = 1; 7 | for (int i = 2; i <= n; i++) { 8 | dp[i] = dp[i - 1] + dp[i - 2]; 9 | } 10 | return dp[n]; 11 | } 12 | 13 | public static void main(String[] args) { 14 | Solution2 solution = new Solution2(); 15 | int climbStairs = solution.climbStairs(2); 16 | System.out.println(climbStairs); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /dynamic-programming/0070-climbing-stairs/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | private int[] memory; 4 | 5 | public int climbStairs(int n) { 6 | if (n <= 0) { 7 | return 1; 8 | } 9 | memory = new int[n + 1]; 10 | for (int i = 0; i < n + 1; i++) { 11 | memory[i] = -1; 12 | } 13 | int res = climbinng(n); 14 | return res; 15 | } 16 | 17 | private int climbinng(int n) { 18 | if (n == 1) { 19 | return 1; 20 | } 21 | if (n == 2) { 22 | // 方法1:一个台阶,一个台阶;方法2:一次上两个台阶 23 | return 2; 24 | } 25 | // 接下来就是看图说话了(乘法计数原理) 26 | if (memory[n] == -1) { 27 | memory[n] = climbinng(n - 1) * 1 + climbinng(n - 2) * 1; 28 | } 29 | return memory[n]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /dynamic-programming/0070-climbing-stairs/src/Solution4.java: -------------------------------------------------------------------------------- 1 | public class Solution4 { 2 | 3 | public int climbStairs(int n) { 4 | if (n <= 0) { 5 | return 1; 6 | } 7 | if (n == 1) { 8 | return 1; 9 | } 10 | int[] memory = new int[n + 1]; 11 | memory[0] = 1; 12 | memory[1] = 1; 13 | for (int i = 2; i < n + 1; i++) { 14 | memory[i] = -1; 15 | } 16 | for (int i = 2; i < n + 1; i++) { 17 | memory[i] = memory[i - 1] + memory[i - 2]; 18 | } 19 | return memory[n]; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /dynamic-programming/0096-unique-binary-search-trees/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int numTrees(int n) { 4 | int[] dp = new int[n + 1]; 5 | // 想清楚这两个值很关键 6 | dp[0] = 1; 7 | dp[1] = 1; 8 | for (int i = 2; i <= n; i++) { 9 | // 这里 j 表示左子树的元素个数,最小是 0 ,最大是 i - 1 10 | // 左边子树 + 右边子树 = i - 1 11 | // i - j - 1 表示的是右边子树元素个数 12 | for (int j = 0; j < i; j++) { 13 | // 使用 * 是因为乘法计数原理 14 | dp[i] += dp[j] * dp[i - j - 1]; 15 | } 16 | } 17 | return dp[n]; 18 | } 19 | 20 | public static void main(String[] args) { 21 | Solution solution = new Solution(); 22 | int n = 3; 23 | int numTrees = solution.numTrees(n); 24 | System.out.println(numTrees); 25 | } 26 | } -------------------------------------------------------------------------------- /dynamic-programming/0096-unique-binary-search-trees/src/Solution3.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 2019/9/1 6:56 PM 4 | */ 5 | public class Solution3 { 6 | 7 | public int numTrees(int n) { 8 | int[] dp = new int[n + 1]; 9 | // 乘法因子的单位是 1 10 | dp[0] = 1; 11 | dp[1] = 1; 12 | 13 | for (int i = 2; i < n + 1; i++) { 14 | for (int j = 0; j < i / 2; j++) { 15 | dp[i] += 2 * (dp[j] * dp[i - j - 1]); 16 | } 17 | if ((i & 1) == 1) { 18 | dp[i] += dp[i / 2] * dp[i / 2]; 19 | } 20 | } 21 | return dp[n]; 22 | } 23 | 24 | public static void main(String[] args) { 25 | Solution3 solution3 = new Solution3(); 26 | int n = 3; 27 | int numTrees = solution3.numTrees(n); 28 | System.out.println(numTrees); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /dynamic-programming/0120-triangle/src/Solution2.java: -------------------------------------------------------------------------------- 1 | import java.util.List; 2 | 3 | /** 4 | * @author liweiwei1419 5 | * @date 2019/10/22 5:33 上午 6 | */ 7 | public class Solution2 { 8 | 9 | public int minimumTotal(List> triangle) { 10 | int len = triangle.size(); 11 | if (len == 0) { 12 | return 0; 13 | } 14 | 15 | int[] dp = new int[len]; 16 | for (int i = 0; i < len; i++) { 17 | dp[i] = triangle.get(len - 1).get(i); 18 | } 19 | 20 | for (int i = len - 2; i >= 0; i--) { 21 | for (int j = 0; j <= i; j++) { 22 | dp[j] = Math.min(dp[j], dp[j + 1]) + triangle.get(i).get(j); 23 | } 24 | } 25 | return dp[0]; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /dynamic-programming/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 | 11 | int[] dp = new int[len]; 12 | for (int i = 0; i < len; i++) { 13 | dp[i] = -1; 14 | } 15 | 16 | // 从后向前写 17 | for (int i = len - 1; i >= 0; i--) { 18 | for (int j = i; j < len; j++) { 19 | dp[i] = Math.max(dp[i], nums[j] + (j + 2 >= len ? 0 : dp[j + 2])); 20 | } 21 | } 22 | return dp[0]; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /dynamic-programming/0198-house-robber/src/Solution4.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 没有记忆化搜索的递归,提交到 LeetCode 上不能通过 3 | * Submission Result: Time Limit Exceeded 4 | * Created by liwei on 17/10/3. 5 | */ 6 | public class Solution4 { 7 | 8 | public int rob(int[] nums) { 9 | // 针对特殊情况应该首先考虑到 10 | if (nums == null || nums.length == 0) { 11 | return 0; 12 | } 13 | return getRob(nums, 0); 14 | } 15 | 16 | // 状态的定义:[i,...,n-1] 这个些个房屋中能够偷取的宝物总和的最大值 17 | // 有最大,一般就有一个遍历的过程 18 | private int getRob(int[] nums, int start) { 19 | // 递归终止条件 20 | if (start >= nums.length) { 21 | return 0; 22 | } 23 | int max = -1; 24 | int len = nums.length; 25 | // i 应该从 start 这个位置开始! 26 | for (int i = start; i < len; i++) { 27 | max = Math.max(max, nums[i] + getRob(nums, i + 2)); 28 | } 29 | return max; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /dynamic-programming/0264-ugly-number-ii/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public int nthUglyNumber(int n) { 4 | int[] dp = new int[n]; 5 | int index2 = 0; 6 | int index3 = 0; 7 | int index5 = 0; 8 | dp[0] = 1; 9 | for (int i = 1; i < n; i++) { 10 | dp[i] = min3(dp[index2] * 2, dp[index3] * 3, dp[index5] * 5); 11 | 12 | if (dp[i] == dp[index2] * 2) { 13 | index2++; 14 | } 15 | if (dp[i] == dp[index3] * 3) { 16 | index3++; 17 | } 18 | if (dp[i] == dp[index5] * 5) { 19 | index5++; 20 | } 21 | } 22 | return dp[n - 1]; 23 | } 24 | 25 | private int min3(int num1, int num2, int num3) { 26 | return Integer.min(Integer.min(num1, num2), num3); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /dynamic-programming/0264-ugly-number-ii/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | public int nthUglyNumber(int n) { 4 | int[] primes = new int[3]; 5 | primes[0] = 2; 6 | primes[1] = 3; 7 | primes[2] = 5; 8 | int[] indexes = new int[3]; 9 | int[] dp = new int[n]; 10 | dp[0] = 1; 11 | for (int i = 1; i < n; i++) { 12 | dp[i] = Integer.MAX_VALUE; 13 | for (int j = 0; j < 3; j++) { 14 | dp[i] = Integer.min(dp[i], dp[indexes[j]] * primes[j]); 15 | } 16 | for (int j = 0; j < 3; j++) { 17 | if (dp[i] == dp[indexes[j]] * primes[j]) { 18 | indexes[j]++; 19 | } 20 | } 21 | } 22 | return dp[n - 1]; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /dynamic-programming/0279-perfect-squares/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public int numSquares(int n) { 4 | int[] dp = new int[n + 1]; 5 | // dp[1] = 1; 6 | for (int i = 1; i <= n; i++) { 7 | // int min = Integer.MAX_VALUE; 8 | int min = n; 9 | // 这个等于号特别重要,i - j * j 等于 0 的时候, 10 | // 表达式 1 + dp[i - j * j] = 1 ,表示它自己就是一个完全平方式,所以结果是 1 11 | for (int j = 1; i - j * j >= 0; j++) { 12 | min = Integer.min(1 + dp[i - j * j], min); 13 | } 14 | dp[i] = min; 15 | } 16 | return dp[n]; 17 | } 18 | 19 | public static void main(String[] args) { 20 | Solution2 solution2 = new Solution2(); 21 | int numSquares = solution2.numSquares(12); 22 | System.out.println(numSquares); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /dynamic-programming/0279-perfect-squares/src/Solution3.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | // 与 Solution2 是同一种写法 4 | public class Solution3 { 5 | 6 | public int numSquares(int n) { 7 | int[] dp = new int[n + 1]; 8 | Arrays.fill(dp, 4); 9 | dp[0] = 0; 10 | for (int i = 1; i <= n; i++) { 11 | for (int j = 1; i - j * j >= 0; j++) { 12 | dp[i] = Math.min(dp[i], 1 + dp[i - j * j]); 13 | } 14 | } 15 | return dp[n]; 16 | } 17 | 18 | public static void main(String[] args) { 19 | Solution3 solution3 = new Solution3(); 20 | int numSquares = solution3.numSquares(12); 21 | System.out.println(numSquares); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /dynamic-programming/0279-perfect-squares/src/Solution4.java: -------------------------------------------------------------------------------- 1 | 2 | // 练习(2刷) 3 | public class Solution4 { 4 | 5 | public int numSquares(int n) { 6 | int[] dp = new int[n + 1]; 7 | for (int i = 1; i <= n; i++) { 8 | int res = 4; 9 | for (int j = 1; i - j * j >= 0; j++) { 10 | res = Math.min(1 + dp[i - j * j], res); 11 | } 12 | dp[i] = res; 13 | } 14 | // System.out.println(Arrays.toString(dp)); 15 | return dp[n]; 16 | } 17 | 18 | public static void main(String[] args) { 19 | Solution4 solution4 = new Solution4(); 20 | int numSquares = solution4.numSquares(200); 21 | System.out.println(numSquares); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /dynamic-programming/0279-perfect-squares/src/Solution5.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | public class Solution5 { 4 | 5 | public int numSquares(int n) { 6 | int[] dp = new int[n + 1]; 7 | Arrays.fill(dp, 4); 8 | dp[0] = 0; 9 | for (int i = 1; i <= n; i++) { 10 | for (int j = 1; i - j * j >= 0; j++) { 11 | dp[i] = Math.min(dp[i], dp[i - j * j] + 1); 12 | } 13 | } 14 | return dp[n]; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /dynamic-programming/0303-range-sum-query-immutable(动态规划)/src/NumArray.java: -------------------------------------------------------------------------------- 1 | public class NumArray { 2 | // cumsum 实现 3 | // [1,2,3,4] 4 | // [1,3,6,10] 5 | 6 | private int[] nums; 7 | 8 | public NumArray(int[] nums) { 9 | this.nums = nums; 10 | for (int i = 1; i < nums.length; i++) { 11 | nums[i] = nums[i] + nums[i - 1]; 12 | } 13 | } 14 | 15 | public int sumRange(int i, int j) { 16 | return nums[j] - (i - 1 < 0 ? 0 : nums[i - 1]); 17 | } 18 | 19 | public static void main(String[] args) { 20 | int[] nums = {1, 2, 3, 4}; 21 | NumArray numArray = new NumArray(nums); 22 | int result = numArray.sumRange(2, 3); 23 | System.out.println(result); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /dynamic-programming/0337-house-robber-iii/src/Solution.java: -------------------------------------------------------------------------------- 1 | // 打家劫舍(三):房子呈二叉树分布 2 | 3 | class TreeNode { 4 | int val; 5 | TreeNode left; 6 | TreeNode right; 7 | 8 | TreeNode(int x) { 9 | val = x; 10 | } 11 | } 12 | 13 | public class Solution { 14 | 15 | public int rob(TreeNode root) { 16 | if (root == null) { 17 | return 0; 18 | } 19 | int val = root.val; 20 | 21 | if (root.left != null) { 22 | val += rob(root.left.left) + rob(root.left.right); 23 | } 24 | 25 | if (root.right != null) { 26 | val += rob(root.right.left) + rob(root.right.right); 27 | } 28 | return Math.max(val, rob(root.left) + rob(root.right)); 29 | } 30 | } -------------------------------------------------------------------------------- /dynamic-programming/0343-integer-break/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int integerBreak(int n) { 4 | int[] dp = new int[n + 1]; 5 | dp[0] = 0; 6 | dp[1] = 1; 7 | dp[2] = 1; 8 | 9 | for (int i = 3; i < n + 1; i++) { 10 | dp[i] = max3(Math.max(dp[i - 1], i - 1), 2 * Math.max(dp[i - 2], i - 2), 3 * Math.max(dp[i - 3], i - 3)); 11 | } 12 | return dp[n]; 13 | } 14 | 15 | private int max3(int num1, int num2, int num3) { 16 | return Math.max(Math.max(num1, num2), num3); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /dynamic-programming/0343-integer-break/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public int integerBreak(int n) { 4 | int[] dp = {0, 1, 1}; 5 | for (int i = 3; i < n + 1; i++) { 6 | dp[i % 3] = max3(Math.max(dp[(i - 1) % 3], i - 1), 2 * Math.max(dp[(i - 2) % 3], i - 2), 3 * Math.max(dp[(i - 3) % 3], i - 3)); 7 | } 8 | return dp[n % 3]; 9 | } 10 | 11 | private int max3(int num1, int num2, int num3) { 12 | return Math.max(Math.max(num1, num2), num3); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /dynamic-programming/0343-integer-break2/src/Solution2.java: -------------------------------------------------------------------------------- 1 | // 动态规划 2 | 3 | public class Solution2 { 4 | 5 | public int integerBreak(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 | for (int j = 1; j < i; j++) { 11 | dp[i] = max3(dp[i], j * dp[i - j], j * (i - j)); 12 | } 13 | } 14 | return dp[n]; 15 | } 16 | 17 | private int max3(int num1, int num2, int num3) { 18 | return Math.max(Math.max(num1, num2), num3); 19 | } 20 | 21 | public static void main(String[] args) { 22 | Solution2 s = new Solution2(); 23 | int maxBreak = s.integerBreak(10); 24 | System.out.println(maxBreak); 25 | for (int i = 1; i < 13; i++) { 26 | maxBreak = s.integerBreak(i); 27 | System.out.println(maxBreak); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /dynamic-programming/0343-integer-break2/src/Solution3.java: -------------------------------------------------------------------------------- 1 | // 找规律的解法 2 | public class Solution3 { 3 | 4 | public int integerBreak(int n) { 5 | if (n == 2 || n == 3) { 6 | return n - 1; 7 | } 8 | int res = 1; 9 | while (n > 4) { 10 | res *= 3; 11 | n -= 3; 12 | } 13 | return res * n; 14 | } 15 | 16 | public static void main(String[] args) { 17 | Solution3 s = new Solution3(); 18 | int maxBreak = s.integerBreak(4); 19 | System.out.println(maxBreak); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /dynamic-programming/0343-integer-break2/src/Solution4.java: -------------------------------------------------------------------------------- 1 | public class Solution4 { 2 | public int integerBreak(int n) { 3 | if (n <= 1) { 4 | return 1; 5 | } 6 | int[] dp = new int[n + 1]; 7 | dp[0] = 1; 8 | dp[1] = 1; 9 | for (int i = 2; i <= n; i++) { 10 | int max = 0; 11 | for (int j = 1; j < i; j++) { 12 | max = max3(max, j * (i - j), j * dp[i - j]); 13 | } 14 | dp[i] = max; 15 | } 16 | return dp[n]; 17 | } 18 | 19 | private int max3(int num1, int num2, int num3) { 20 | return Integer.max(Integer.max(num1, num2), num3); 21 | } 22 | 23 | public static void main(String[] args) { 24 | Solution solution = new Solution(); 25 | int integerBreak = solution.integerBreak(8); 26 | System.out.println(integerBreak); 27 | } 28 | } -------------------------------------------------------------------------------- /dynamic-programming/0343-integer-break2/src/Solution5.java: -------------------------------------------------------------------------------- 1 | public class Solution5 { 2 | public int integerBreak(int n) { 3 | if (n <= 2) { 4 | return 1; 5 | } 6 | if (n == 3) { 7 | return 2; 8 | } 9 | if (n == 4) { 10 | return 4; 11 | } 12 | // 接下来就是 n >= 5 的时候的逻辑了 13 | int res = 1; 14 | while (n > 4) { 15 | res *= 3; 16 | n -= 3; 17 | } 18 | res *= n; 19 | return res; 20 | } 21 | 22 | public static void main(String[] args) { 23 | Solution2 solution2 = new Solution2(); 24 | int integerBreak = solution2.integerBreak(8); 25 | System.out.println(integerBreak); 26 | } 27 | } -------------------------------------------------------------------------------- /dynamic-programming/0343-integer-break2/src/Solution6.java: -------------------------------------------------------------------------------- 1 | public class Solution6 { 2 | 3 | /** 4 | * @param n 5 | * @return 6 | */ 7 | 8 | public int integerBreak(int n) { 9 | int[] dp = new int[n + 1]; 10 | dp[0] = 1; 11 | dp[1] = 1; 12 | for (int i = 2; i <= n; i++) { 13 | int max = 0; 14 | for (int j = 1; j < i; j++) { 15 | max = max3(max, j * (i - j), j * dp[i - j]); 16 | } 17 | dp[i] = max; 18 | } 19 | return dp[n]; 20 | } 21 | 22 | private int max3(int num1, int num2, int num3) { 23 | return Math.max(num1, Math.max(num2, num3)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /dynamic-programming/0376-wiggle-subsequence/376.md: -------------------------------------------------------------------------------- 1 | 2 | # 求一个序列的最大摇摆子序列的长度 3 | 4 | ## LeetCode 第 376 题 5 | 6 | 英文地址 中文地址 7 | 8 | ## 解题要点 9 | 10 | + 按照题目中给出的例子找出规律 11 | + 如果我们要得出摇摆子序列的最大长度,面对小部分递增或者递减的子序列,我们应该保留它们的头和尾,中间的部分不要,这是贪心算法的应用,下面以题目中给出的例子为例: 12 | 13 | [1,17,5,10,13,15,10,5,16,8] 14 | 15 | [5,10,13,15] 是原序列的一个递增子序列,我们保留 5 是因为 5 在原序列中与它的前一位 17 以及之前的 1 可以构成摇摆序列,**如果我们选 10 ,那么这个 10 与在 [5,10,13,15] 之后的 10 就不能构成摇摆子序列了,因此,我们希望我们能保留的这个值越大,则保留的这个值与递增序列后面的那 1 个值构成摇摆序列的可能性就越大,这里就体现了贪心 **; 16 | 17 | + 在具体实现的时候,我们可以根据示例画出简单的状态机,那么编码起来逻辑就很清晰了,这一点是必须要掌握的。 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /dynamic-programming/0376-wiggle-subsequence/src/Solution3.java: -------------------------------------------------------------------------------- 1 | // 根据 Solution2 而来,是一种更少空间复杂度的写法 2 | public class Solution3 { 3 | 4 | public int wiggleMaxLength(int[] nums) { 5 | int len = nums.length; 6 | if (len == 0) { 7 | return 0; 8 | } 9 | int up = 1; 10 | int down = 1; 11 | for (int i = 1; i < len; i++) { 12 | if (nums[i] > nums[i - 1]) { 13 | up = down + 1; 14 | } else if (nums[i] < nums[i - 1]) { 15 | down = up + 1; 16 | } 17 | } 18 | return Math.max(up, down); 19 | } 20 | 21 | public static void main(String[] args) { 22 | int[] nums = {1, 17, 5, 10, 13, 15, 10, 5, 16, 8}; 23 | Solution3 solution3 = new Solution3(); 24 | int wiggleMaxLength = solution3.wiggleMaxLength(nums); 25 | System.out.println(wiggleMaxLength); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /dynamic-programming/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 | // 因为 0 表示空集,空集和它"前面"的元素凑成一种解法,所以是 1 7 | // 这一步要加深体会 8 | dp[0] = 1; 9 | for (int i = 1; i < target + 1; i++) { 10 | for (int num : nums) { 11 | if (i >= num) { 12 | dp[i] = dp[i] + dp[i - num]; 13 | } 14 | } 15 | } 16 | return dp[target]; 17 | } 18 | 19 | public static void main(String[] args) { 20 | Solution solution = new Solution(); 21 | int[] nums = {1, 2, 3}; 22 | int target = 4; 23 | int combinationSum4 = solution.combinationSum4(nums, target); 24 | System.out.println(combinationSum4); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /dynamic-programming/0509-fibonacci-number/src/Solution.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/4 4:03 下午 4 | */ 5 | public class Solution { 6 | 7 | // 动态规划 8 | // 时间复杂度:O(N) 9 | // 空间复杂度:O(N) 10 | 11 | public int fib(int N) { 12 | if (N < 2) { 13 | return N; 14 | } 15 | int[] dp = new int[N + 1]; 16 | 17 | dp[0] = 0; 18 | dp[1] = 1; 19 | for (int i = 2; i < N + 1; i++) { 20 | dp[i] = dp[i - 1] + dp[i - 2]; 21 | } 22 | return dp[N]; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /dynamic-programming/0509-fibonacci-number/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/4 4:03 下午 4 | */ 5 | public class Solution2 { 6 | 7 | // 动态规划:使用滚动变量 8 | // 时间复杂度:O(N) 9 | // 空间复杂度:O(1) 10 | 11 | public int fib(int N) { 12 | if (N < 2) { 13 | return N; 14 | } 15 | int a = 0; 16 | int b = 1; 17 | int c = 0; 18 | for (int i = 2; i < N + 1; i++) { 19 | c = a + b; 20 | a = b; 21 | b = c; 22 | } 23 | return c; 24 | } 25 | 26 | // 其它解法:记忆化递归、矩阵乘法 27 | } 28 | -------------------------------------------------------------------------------- /dynamic-programming/0518-coin-change-2/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 2019/9/8 6:07 PM 4 | */ 5 | public class Solution2 { 6 | 7 | public int change(int amount, int[] coins) { 8 | int len = coins.length; 9 | int[][] dp = new int[len + 1][amount + 1]; 10 | dp[0][0] = 1; 11 | 12 | for (int i = 1; i <= len; i++) { 13 | for (int j = 0; j <= amount; j++) { 14 | dp[i][j] = dp[i - 1][j]; 15 | if (j - coins[i - 1] >= 0) { 16 | dp[i][j] += dp[i][j - coins[i - 1]]; 17 | } 18 | } 19 | } 20 | return dp[len][amount]; 21 | } 22 | 23 | public static void main(String[] args) { 24 | int amount = 5; 25 | int[] coins = {1, 2, 5}; 26 | Solution2 solution2 = new Solution2(); 27 | int res = solution2.change(amount, coins); 28 | System.out.println(res); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /dynamic-programming/0518-coin-change-2/src/Solution3.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 2019/9/8 6:55 PM 4 | */ 5 | public class Solution3 { 6 | 7 | public int change(int amount, int[] coins) { 8 | int[] dp = new int[amount + 1]; 9 | dp[0] = 1; 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 | 22 | public static void main(String[] args) { 23 | int amount = 500; 24 | int[] coins = {3, 5, 7, 8, 9, 10, 11}; 25 | // 35502874 26 | Solution3 solution3 = new Solution3(); 27 | int res = solution3.change(amount, coins); 28 | System.out.println(res); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /dynamic-programming/0518-coin-change-2/src/Solution5.java: -------------------------------------------------------------------------------- 1 | import java.io.File; 2 | import java.io.IOException; 3 | 4 | /** 5 | * @author liwei 6 | * @date 2019/9/9 11:50 AM 7 | */ 8 | 9 | 10 | public class Solution5 { 11 | 12 | public static void main(String[] args) throws IOException { 13 | System.out.println("-12 \t\t:" + Integer.toBinaryString(-12)); 14 | System.out.println("-12 >>> 2 \t:" + Integer.toBinaryString((-12) >>> 2)); 15 | System.out.println(-12 >>> 2); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /greedy/0012-integer-to-roman/src/Solution3.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/29 2:01 下午 4 | */ 5 | public class Solution3 { 6 | 7 | // 一位一位打表做 8 | 9 | public String intToRoman(int num) { 10 | // 个位 11 | String[] one = new String[]{"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"}; 12 | // 十位 13 | String[] two = new String[]{"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"}; 14 | // 百位 15 | String[] three = new String[]{"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"}; 16 | // 千位 17 | String[] four = new String[]{"", "M", "MM", "MMM"}; 18 | return four[num / 1000] + three[(num / 100) % 10] + two[(num / 10) % 10] + one[num % 10]; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /greedy/0055-jump-game/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/15 10:30 上午 4 | */ 5 | public class Solution2 { 6 | 7 | /** 8 | * 从后向前走,避免了很多重复的计算 9 | * 最后一个位置一定为 true 10 | * 11 | * @param nums 12 | * @return 13 | */ 14 | public boolean canJump(int[] nums) { 15 | int len = nums.length; 16 | if (len < 1) { 17 | return false; 18 | } 19 | boolean[] check = new boolean[len]; 20 | // 初始化的时候,设置为 true 表示可以到达 21 | check[len - 1] = true; 22 | for (int i = len - 1; i >= 0; i--) { 23 | int curStep = nums[i]; 24 | for (int j = 0; j <= curStep; j++) { 25 | if (check[i + j]) { 26 | check[i] = true; 27 | break; 28 | } 29 | } 30 | } 31 | return check[0]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /greedy/0055-jump-game/src/Solution3.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/15 10:30 上午 4 | */ 5 | public class Solution3 { 6 | /** 7 | * 贪心算法 8 | * 9 | * @param nums 10 | * @return 11 | */ 12 | public boolean canJump(int[] nums) { 13 | int len = nums.length; 14 | if (len < 1) { 15 | return false; 16 | } 17 | int lastPosition = len - 1; 18 | for (int i = len - 1; i >= 0; i--) { 19 | if (i + nums[i] >= lastPosition) { 20 | lastPosition = i; 21 | } 22 | } 23 | return lastPosition == 0; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /greedy/0055-jump-game/src/Solution4.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/11/28 9:23 下午 4 | */ 5 | public class Solution4 { 6 | 7 | // 贪心算法 8 | 9 | public boolean canJump(int[] nums) { 10 | int maxReach = 0; 11 | int len = nums.length; 12 | for (int i = 0; i < len; i++) { 13 | if (i > maxReach) { 14 | return false; 15 | } 16 | maxReach = Math.max(maxReach, i + nums[i]); 17 | } 18 | return true; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /greedy/0055-jump-game/src/Solution5.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/11/28 9:23 下午 4 | */ 5 | public class Solution5 { 6 | 7 | // 动态规划 8 | // [2, 3, 1, 1, 4] 9 | // dp[i]:[0, i - 1] 这个区间里的元素跳到 nums[i] 的时候还能再跳几格 10 | 11 | // 只要能遍历到最后一格就 ok 12 | 13 | public boolean canJump(int[] nums) { 14 | int len = nums.length; 15 | int[] dp = new int[len]; 16 | 17 | for (int i = 1; i < len; i++) { 18 | dp[i] = Math.max(dp[i - 1], nums[i - 1]) - 1; 19 | if (dp[i] < 0) { 20 | return false; 21 | } 22 | } 23 | return true; 24 | } 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /greedy/0392-is-subsequence(贪心算法、动态规划、二分查找)/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/6/24 下午6:18 4 | */ 5 | public class Solution2 { 6 | 7 | public boolean isSubsequence(String s, String t) { 8 | int slen = s.length(); 9 | int tlen = t.length(); 10 | int i = 0; 11 | int j = 0; 12 | while (i < slen && j < tlen) { 13 | if (s.charAt(i) == t.charAt(j)) { 14 | i++; 15 | } 16 | j++; 17 | } 18 | return i == slen; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /greedy/0435-non-overlapping-intervals/src/Solution2.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.Comparator; 3 | 4 | /** 5 | * @author liweiwei1419 6 | * @date 2019/11/2 10:09 上午 7 | */ 8 | public class Solution2 { 9 | 10 | // 贪心算法:区间按照结尾端点升序排序 11 | 12 | public int eraseOverlapIntervals(int[][] intervals) { 13 | int len = intervals.length; 14 | if (len < 2) { 15 | return 0; 16 | } 17 | 18 | // 区间按照结尾端点升序排序 19 | Arrays.sort(intervals, Comparator.comparingInt(a -> a[1])); 20 | 21 | int res = 1; 22 | int end = intervals[0][1]; 23 | for (int i = 1; i < len; i++) { 24 | if (intervals[i][0] >= end) { 25 | res += 1; 26 | end = intervals[i][1]; 27 | } 28 | } 29 | return len - res; 30 | } 31 | } -------------------------------------------------------------------------------- /greedy/0435-non-overlapping-intervals/src/Solution3.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.Comparator; 3 | 4 | public class Solution3 { 5 | 6 | // 贪心算法:最先结束的区间,一定是最优解的一部分 7 | 8 | public int eraseOverlapIntervals(int[][] intervals) { 9 | int len = intervals.length; 10 | if (len < 2) { 11 | return 0; 12 | } 13 | 14 | Arrays.sort(intervals, Comparator.comparingInt(a -> a[1])); 15 | 16 | // 计算哪些区间被丢弃 17 | int res = 0; 18 | int end = intervals[0][1]; 19 | for (int i = 1; i < len; i++) { 20 | if (intervals[i][0] < end) { 21 | res++; 22 | } else { 23 | end = intervals[i][1]; 24 | } 25 | } 26 | return res; 27 | } 28 | } -------------------------------------------------------------------------------- /hash-table/0001-two-sum/src/Solution3.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 2019/8/26 10:59 PM 4 | */ 5 | public class Solution3 { 6 | 7 | // 暴力解法,时间复杂度 O(N^2) 8 | 9 | public int[] twoSum(int[] nums, int target) { 10 | int len = nums.length; 11 | // 最后一位不要遍历,因为它的后面已经没有元素了 12 | for (int i = 0; i < len - 1; i++) { 13 | for (int j = i + 1; j < len; j++) { 14 | if (nums[i] + nums[j] == target) { 15 | return new int[]{i, j}; 16 | } 17 | } 18 | } 19 | return new int[]{-1, -1}; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /hash-table/0187-repeated-dna-sequences/src/Solution2.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.HashSet; 3 | import java.util.List; 4 | 5 | /** 6 | * @author liwei 7 | * @date 18/7/1 上午9:36 8 | */ 9 | public class Solution2 { 10 | 11 | public List findRepeatedDnaSequences(String s) { 12 | HashSet seen = new HashSet<>(); 13 | HashSet repeated = new HashSet<>(); 14 | 15 | int len = s.length(); 16 | for (int i = 0; i + 9 < len; i++) { 17 | String segment = s.substring(i, i + 10); 18 | if (!seen.add(segment)) { 19 | repeated.add(segment); 20 | } 21 | } 22 | return new ArrayList<>(repeated); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /hash-table/0202-happy-number/src/Solution2.java: -------------------------------------------------------------------------------- 1 | import java.util.HashSet; 2 | import java.util.Set; 3 | 4 | class Solution2 { 5 | public boolean isHappy(int n) { 6 | Set set1 = new HashSet<>(); 7 | String numberStr = String.valueOf(n); 8 | while (true) { 9 | int sum = 0; 10 | for (int i = 0; i < numberStr.length(); i++) { 11 | sum += Math.pow(Integer.valueOf(String.valueOf(numberStr.charAt(i))), 2); 12 | } 13 | if (sum == 1) { 14 | return true; 15 | } else if (set1.contains(sum)) { 16 | return false; 17 | } else { 18 | set1.add(sum); 19 | numberStr = String.valueOf(sum); 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /hash-table/0205-isomorphic-strings/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | public boolean isIsomorphic(String s, String t) { 4 | int slen = s.length(); 5 | int tlen = t.length(); 6 | if (slen != tlen) { 7 | return false; 8 | } 9 | Character[] map = new Character[256]; 10 | boolean[] set = new boolean[256]; 11 | for (int i = 0; i < slen; i++) { 12 | char key = s.charAt(i); 13 | char value = t.charAt(i); 14 | if (map[key] == null) { 15 | // 建立映射关系 16 | if (set[value]) { 17 | return false; 18 | } 19 | map[key] = value; 20 | set[value] = true; 21 | } else { 22 | if (map[key] != value) { 23 | return false; 24 | } 25 | } 26 | } 27 | return true; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /hash-table/0217-contains-duplicate/src/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.HashSet; 2 | import java.util.Set; 3 | 4 | /** 5 | * 使用 hash 表进行检查 6 | */ 7 | public class Solution { 8 | 9 | public boolean containsDuplicate(int[] nums) { 10 | Set set = new HashSet<>(); 11 | for (int num : nums) { 12 | if (set.contains(num)) { 13 | return true; 14 | } else { 15 | set.add(num); 16 | } 17 | } 18 | return false; 19 | } 20 | 21 | public boolean containsDuplicate1(int[] nums) { 22 | Set set = new HashSet<>(); 23 | for (int num : nums) { 24 | boolean success = set.add(num); 25 | if (!success) { 26 | // 如果没有添加成功,表示有重复元素,直接返回就可以了 27 | return true; 28 | } 29 | } 30 | return false; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /hash-table/0217-contains-duplicate/src/Solution2.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | /** 4 | * 排序,逐个检查 5 | */ 6 | public class Solution2 { 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 | 17 | for (int i = 0; i < len - 1; i++) { 18 | if (nums[i] == nums[i + 1]) { 19 | return true; 20 | } 21 | } 22 | return false; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /hash-table/0220-contains-duplicate-iii/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | /** 4 | * 暴力解法:会超时,不推荐 5 | * 6 | * @param nums 7 | * @param k 8 | * @param t 9 | * @return 10 | */ 11 | public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) { 12 | 13 | // k 滑动窗口长度 14 | // t 是半径 15 | int len = nums.length; 16 | if (len == 0 || k <= 0 || t < 0) { 17 | return false; 18 | } 19 | 20 | for (int i = 0; i < len; i++) { 21 | for (int j = i + 1; j - i <= k && j < len; j++) { 22 | if (Math.abs((long) nums[j] - (long) nums[i]) <= t) { 23 | return true; 24 | } 25 | } 26 | } 27 | return false; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /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 | } 28 | -------------------------------------------------------------------------------- /hash-table/0560-subarray-sum-equals-k/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/9/20 12:07 下午 4 | */ 5 | public class Solution2 { 6 | /** 7 | * 暴力解法:固定了起点 8 | * @param nums 9 | * @param k 10 | * @return 11 | */ 12 | public int subarraySum(int[] nums, int k) { 13 | int count = 0; 14 | int len = nums.length; 15 | for (int left = 0; left < len; left++) { 16 | int sum = 0; 17 | // 区间里可能会有一些互相抵销的元素 18 | for (int right = left; right < len; right++) { 19 | sum += nums[right]; 20 | if (sum == k){ 21 | count++; 22 | } 23 | } 24 | } 25 | return count; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /hash-table/0560-subarray-sum-equals-k/src/Solution3.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/9/20 12:16 下午 4 | */ 5 | public class Solution3 { 6 | /** 7 | * 构建前缀和数组,以空间换时间 8 | * 9 | * @param nums 10 | * @param k 11 | * @return 12 | */ 13 | public int subarraySum(int[] nums, int k) { 14 | int len = nums.length; 15 | int[] preSum = new int[len + 1]; 16 | preSum[0] = 0; 17 | for (int i = 0; i < len; i++) { 18 | preSum[i + 1] = preSum[i] + nums[i]; 19 | } 20 | int count = 0; 21 | for (int left = 0; left < len; left++) { 22 | for (int right = left + 1; right <= len; right++) { 23 | if (preSum[right] - preSum[left] == k) { 24 | count++; 25 | } 26 | } 27 | } 28 | return count; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /hash-table/0560-subarray-sum-equals-k/src/Solution4.java: -------------------------------------------------------------------------------- 1 | import java.util.HashMap; 2 | import java.util.Map; 3 | 4 | /** 5 | * @author liweiwei1419 6 | * @date 2019/9/20 12:21 下午 7 | */ 8 | public class Solution4 { 9 | 10 | public int subarraySum(int[] nums, int k) { 11 | Map hash = new HashMap<>(); 12 | hash.put(0, 1); 13 | int sum = 0; 14 | int count = 0; 15 | for (int num : nums) { 16 | sum += num; 17 | if (hash.containsKey(sum - k)) { 18 | count += hash.get(sum - k); 19 | } 20 | hash.put(sum, hash.getOrDefault(sum, 0) + 1); 21 | } 22 | return count; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /linked-list/0021-merge-two-sorted-lists/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 使用递归方法完成 3 | * 4 | * @author liwei 5 | */ 6 | public class Solution2 { 7 | 8 | /** 9 | * 使用递归 10 | * 11 | * @param l1 有序链表 12 | * @param l2 有序链表 13 | * @return 有序链表 14 | */ 15 | public ListNode mergeTwoLists(ListNode l1, ListNode l2) { 16 | // 先写递归终止的条件 17 | if (l1 == null) { 18 | return l2; 19 | } 20 | if (l2 == null) { 21 | return l1; 22 | } 23 | // 假设规模小的问题已经解决,如何建立和原始规模问题之间的关系 24 | ListNode mergeNode; 25 | if (l1.val < l2.val) { 26 | // l1 被选出,谁小谁在前面 27 | l1.next = mergeTwoLists(l1.next, l2); 28 | return l1; 29 | } else { 30 | // l2 被选出,谁小谁在前面 31 | l2.next = mergeTwoLists(l1, l2.next); 32 | return l2; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /linked-list/0021-merge-two-sorted-lists/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | 4 | 5 | } 6 | -------------------------------------------------------------------------------- /linked-list/0024-swap-nodes-in-pairs/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | public ListNode swapPairs(ListNode head) { 4 | if (head == null || head.next == null) { 5 | return head; 6 | } 7 | ListNode p1 = head; 8 | ListNode p2 = head.next; 9 | // 没有必要这么写 10 | p2.next = swapPairs(p2.next); 11 | p1.next = p2.next; 12 | p2.next = p1; 13 | return p2; 14 | } 15 | public static void main(String[] args) { 16 | // 给定 1->2->3->4, 你应该返回 2->1->4->3. 17 | int[] nums = {1, 2, 3, 4}; 18 | ListNode head = new ListNode(nums); 19 | Solution3 solution2 = new Solution3(); 20 | ListNode swapPairs = solution2.swapPairs(head); 21 | System.out.println(swapPairs); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /linked-list/0083-remove-duplicates-from-sorted-list/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public ListNode deleteDuplicates(ListNode head) { 4 | ListNode curNode = head; 5 | // 当前和下一个结点都非空的时候才删除 6 | while (curNode != null && curNode.next != null) { 7 | // 值相同的时候考虑删除 8 | if (curNode.val == curNode.next.val) { 9 | ListNode deleteNode = curNode.next; 10 | // 看看是否还可以删除 11 | while (deleteNode.next != null && deleteNode.val == deleteNode.next.val) { 12 | deleteNode = deleteNode.next; 13 | } 14 | // 穿针引线 15 | curNode.next = deleteNode.next; 16 | deleteNode.next = null; 17 | } else { 18 | curNode = curNode.next; 19 | } 20 | } 21 | return head; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /linked-list/0086-partition-list/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | 4 | } 5 | -------------------------------------------------------------------------------- /linked-list/0092-reverse-linked-list-ii/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | public ListNode reverseBetween(ListNode head, int m, int n) { 3 | // 创建一个虚拟的节点(dummy) 4 | ListNode dummy = new ListNode(-1); 5 | dummy.next = head; 6 | ListNode pre = dummy; 7 | int k = 0; 8 | while (++k < m) { 9 | if (pre != null) { 10 | pre = pre.next; 11 | } 12 | } 13 | // tail 是尾巴的意思 14 | ListNode tail = pre.next; 15 | while (++k <= n) { 16 | ListNode temp = pre.next; 17 | pre.next = tail.next; 18 | tail.next = tail.next.next; 19 | pre.next.next = temp; 20 | } 21 | return dummy.next; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /linked-list/0092-reverse-linked-list-ii/src/Solution3.java: -------------------------------------------------------------------------------- 1 | 2 | public class Solution3 { 3 | 4 | public ListNode reverseBetween(ListNode head, int m, int n) { 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 | 13 | ListNode next; 14 | for (int i = 0; i < n - m; i++) { 15 | next = cur.next; 16 | cur.next = next.next; 17 | next.next = pre.next; 18 | pre.next = next; 19 | } 20 | return dummyNode.next; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /linked-list/0092-reverse-linked-list-ii/src/Solution4.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 2019/8/14 3:19 PM 4 | */ 5 | public class Solution2 { 6 | 7 | // 复杂的"穿针引线",使用 3 个指针 8 | 9 | public ListNode reverseBetween(ListNode head, int m, int n) { 10 | ListNode dummyNode = new ListNode(-1); 11 | dummyNode.next = head; 12 | ListNode pre = dummyNode; 13 | for (int i = 0; i < m - 1; i++) { 14 | pre = pre.next; 15 | } 16 | ListNode cur = pre.next; 17 | 18 | ListNode next; 19 | for (int i = 0; i < n - m; i++) { 20 | next = cur.next; 21 | cur.next = next.next; 22 | next.next = pre.next; 23 | pre.next = next; 24 | } 25 | return dummyNode.next; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /linked-list/0141-linked-list-cycle/src/Solution.java: -------------------------------------------------------------------------------- 1 | class ListNode { 2 | int val; 3 | ListNode next; 4 | 5 | ListNode(int x) { 6 | val = x; 7 | next = null; 8 | } 9 | } 10 | 11 | 12 | public class Solution { 13 | 14 | // 快慢指针 15 | 16 | public boolean hasCycle(ListNode head) { 17 | // 特判 18 | if (head == null || head.next == null) { 19 | return false; 20 | } 21 | 22 | ListNode slow = head; 23 | ListNode fast = head; 24 | 25 | // 慢指针一次走一步、快指针一次走两步 26 | // 注意:快指针可以走的条件 fast != null && fast.next != null 27 | 28 | while (fast != null && fast.next != null) { 29 | slow = slow.next; 30 | fast = fast.next.next; 31 | if (slow == fast) { 32 | return true; 33 | } 34 | } 35 | return false; 36 | } 37 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /linked-list/0160-intersection-of-two-linked-lists/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 2019/8/14 11:52 AM 4 | */ 5 | public class Solution2 { 6 | 7 | public ListNode getIntersectionNode(ListNode headA, ListNode headB) { 8 | // 特判 9 | if (headA == null || headB == null) { 10 | return null; 11 | } 12 | 13 | ListNode head1 = headA; 14 | ListNode head2 = headB; 15 | 16 | while (head1 != head2) { 17 | if (head1 != null) { 18 | head1 = head1.next; 19 | } else { 20 | head1 = headB; 21 | } 22 | 23 | if (head2 != null) { 24 | head2 = head2.next; 25 | } else { 26 | head2 = headA; 27 | } 28 | } 29 | return head1; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /linked-list/0237-delete-node-in-a-linked-list/src/Solution.java: -------------------------------------------------------------------------------- 1 | class ListNode { 2 | int val; 3 | ListNode next; 4 | ListNode(int x) { val = x; } 5 | } 6 | 7 | public class Solution { 8 | public void deleteNode(ListNode node) { 9 | // 第 1 步:把待删除结点的下一结点的值赋值给自己 10 | ListNode nextNode = node.next; 11 | node.val = nextNode.val; 12 | 13 | // 第 2 步:删除下一个结点 14 | node.next = nextNode.next; 15 | nextNode.next = null; 16 | } 17 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /linked-list/0460-lfu-cache/README.md: -------------------------------------------------------------------------------- 1 | # 花花酱给出了两种解法 2 | 3 | http://zxi.mytechroad.com/blog/hashtable/leetcode-460-lfu-cache/ 4 | http://zxi.mytechroad.com/blog/hashtable/leetcode-460-lfu-cache/ 5 | http://zxi.mytechroad.com/blog/hashtable/leetcode-460-lfu-cache/ 6 | 7 | https://leetcode.com/problems/lfu-cache/discuss/94547/Java-O(1)-Solution-Using-Two-HashMap-and-One-DoubleLinkedList 8 | 9 | 460. LFU缓存 10 | 11 | LFU 是 Least Frequently Used 近期最少使用算法,在缓存满的时候,移除那个频率最小的 k-v 对。 12 | 13 | LRU 算法是首先淘汰最长时间未被使用的页面,而 LFU 是先淘汰一定时间内被访问次数最少的页面。 14 | 15 | 16 | 比较与 LRU (LeetCode 第 146 题)的区别: 17 | 18 | + https://blog.csdn.net/jmspan/article/details/54132779 19 | 20 | + https://blog.csdn.net/xidiancoder/article/details/77504050 21 | 22 | + http://blog.jerkybible.com/2017/01/17/LeetCode-460-LFU-Cache/ 23 | -------------------------------------------------------------------------------- /math/0007-reverse-integer/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 要特别注意到反转以后整数越界的问题 4 | 5 | public int reverse(int x) { 6 | int sign = x >= 0 ? 1 : -1; 7 | long res = 0; 8 | x = sign * x; 9 | while (x > 0) { 10 | res = res * 10 + x % 10; 11 | x = x / 10; 12 | } 13 | res = sign * res; 14 | if (res > Integer.MAX_VALUE || res < Integer.MIN_VALUE) { 15 | return 0; 16 | } 17 | return (int) res; 18 | } 19 | 20 | public static void main(String[] args) { 21 | int x = 1534236469; 22 | Solution solution = new Solution(); 23 | int reverse = solution.reverse(x); 24 | System.out.println(reverse); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /math/0007-reverse-integer/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public int reverse(int x) { 4 | if (x == 0) { 5 | return 0; 6 | } 7 | 8 | int sign = 1; 9 | if (x < 0) { 10 | sign = -1; 11 | x = -1 * x; 12 | } 13 | 14 | long res = 0; 15 | while (x != 0) { 16 | res = res * 10 + x % 10; 17 | x /= 10; 18 | 19 | } 20 | 21 | res *= sign; 22 | if (res > Integer.MAX_VALUE || res < Integer.MIN_VALUE) { 23 | return 0; 24 | } 25 | return (int) res; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /math/0007-reverse-integer/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | public int reverse(int x) { 4 | if (x == 0) { 5 | return 0; 6 | } 7 | long res = 0; 8 | while (x != 0) { 9 | res = res * 10 + x % 10; 10 | x /= 10; 11 | if (res > Integer.MAX_VALUE || res < Integer.MIN_VALUE) { 12 | return 0; 13 | } 14 | } 15 | return (int) res; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /math/0007-reverse-integer/src/Solution4.java: -------------------------------------------------------------------------------- 1 | public class Solution4 { 2 | 3 | public int reverse(int x) { 4 | int sign = x >= 0 ? 1 : -1; 5 | long res = 0; 6 | // 这一步相当于取绝对值 7 | x = sign * x; 8 | // 下面这一步其实是求每个个位数的套路 9 | while (x > 0) { 10 | res = res * 10 + x % 10; 11 | x = x / 10; 12 | } 13 | res = sign * res; 14 | if (res > Integer.MAX_VALUE || res < Integer.MIN_VALUE) { 15 | return 0; 16 | } 17 | return (int) res; 18 | } 19 | 20 | public static void main(String[] args) { 21 | Solution solution = new Solution(); 22 | int x = 1534236469; 23 | int reverse = solution.reverse(x); 24 | System.out.println(reverse); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /math/0007-reverse-integer/src/Solution5.java: -------------------------------------------------------------------------------- 1 | public class Solution5 { 2 | 3 | public int reverse(int x) { 4 | if (x == 0) { 5 | return 0; 6 | } 7 | 8 | int sign = 1; 9 | if (x < 0) { 10 | sign = -1; 11 | x = -1 * x; 12 | } 13 | 14 | long res = 0; 15 | while (x != 0) { 16 | res = res * 10 + x % 10; 17 | x /= 10; 18 | } 19 | 20 | res *= sign; 21 | if (res > Integer.MAX_VALUE || res< Integer.MIN_VALUE) { 22 | return 0; 23 | } 24 | return (int) res; 25 | } 26 | 27 | public static void main(String[] args) { 28 | Solution2 solution2 = new Solution2(); 29 | int reverse = solution2.reverse(123); 30 | System.out.println(reverse); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /math/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 | // 在执行得到反转的过程中,会改变 x 的值,所以用 x 的副本去完成这个逻辑 9 | return x == reverse(x); 10 | } 11 | 12 | private int reverse(int x) { 13 | int reverse = 0; 14 | while (x != 0) { 15 | reverse = reverse * 10 + x % 10; 16 | x /= 10; 17 | } 18 | return reverse; 19 | } 20 | 21 | public static void main(String[] args) { 22 | int x = 12321; 23 | Solution solution = new Solution(); 24 | boolean palindrome = solution.isPalindrome(x); 25 | System.out.println(palindrome); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /math/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 | 17 | public static void main(String[] args) { 18 | Solution2 solution2 = new Solution2(); 19 | int x = 12321; 20 | boolean palindrome = solution2.isPalindrome(x); 21 | System.out.println(palindrome); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /math/0168-excel-sheet-column-title/src/Solution.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/7/5 下午10:45 4 | */ 5 | public class Solution { 6 | 7 | // 原理和进制转换是一样的 8 | 9 | private static final int OFFSET = 'A'; 10 | 11 | public String convertToTitle(int n) { 12 | if (n <= 0) { 13 | return ""; 14 | } 15 | StringBuilder stringBuilder = new StringBuilder(); 16 | while (n != 0) { 17 | n--; 18 | stringBuilder.append((char) (n % 26 + OFFSET)); 19 | n /= 26; 20 | } 21 | return stringBuilder.reverse().toString(); 22 | } 23 | 24 | public static void main(String[] args) { 25 | Solution solution = new Solution(); 26 | for (int i = 0; i <= 30; i++) { 27 | String convertToTitle = solution.convertToTitle(i); 28 | System.out.println(convertToTitle); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /math/0171-excel-sheet-column-number/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 利用 ASCII 码做一个偏移常量 4 | private static final int OFFSET = (int) 'A' - 1; 5 | 6 | public int titleToNumber(String s) { 7 | int len = s.length(); 8 | int res = 0; 9 | for (int i = 0; i < len; i++) { 10 | int curVal = s.charAt(i) - OFFSET; 11 | res = res * 26 + curVal; 12 | } 13 | return res; 14 | } 15 | 16 | public static void main(String[] args) { 17 | System.out.println(OFFSET); 18 | Solution solution = new Solution(); 19 | String s = "ZY"; 20 | int titleToNumber = solution.titleToNumber(s); 21 | System.out.println(titleToNumber); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /math/0263-ugly-number/src/Main.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/6/22 下午10:03 4 | */ 5 | public class Main { 6 | 7 | // 打印出所有质数因子 8 | public static void main(String[] args) { 9 | int num = 150; 10 | while (num!=1){ 11 | for (int i = 2; i <= num; i++) { 12 | if (num % i == 0) { 13 | num /= i; 14 | System.out.println(i); 15 | break; 16 | } 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /math/0263-ugly-number/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 编写一个程序判断给定的数是否为丑数。 4 | // 丑数就是只包含质因数 2, 3, 5 的正整数。 5 | 6 | public boolean isUgly(int num) { 7 | if (num <= 0) { 8 | return false; 9 | } 10 | while (num % 5 == 0) { 11 | num /= 5; 12 | } 13 | while (num % 3 == 0) { 14 | num /= 3; 15 | } 16 | while (num % 2 == 0) { 17 | num /= 2; 18 | } 19 | return num == 1; 20 | } 21 | } -------------------------------------------------------------------------------- /math/0263-ugly-number/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public boolean isUgly(int num) { 4 | if (num <= 0) { 5 | return false; 6 | } 7 | int[] factors = new int[]{2, 3, 5}; 8 | for (int factor : factors) { 9 | while (num % factor == 0) { 10 | num /= factor; 11 | } 12 | } 13 | return num == 1; 14 | } 15 | } -------------------------------------------------------------------------------- /math/0268-missing-number/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int missingNumber(int[] nums) { 4 | int n = nums.length; 5 | int sum = (n + 1) * n / 2; 6 | for (int i = 0; i < n; i++) { 7 | sum -= nums[i]; 8 | } 9 | return sum; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /math/0292-nim-game/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // https://blog.csdn.net/fly_yr/article/details/50071367 4 | 5 | public boolean canWinNim(int n) { 6 | return n % 4 != 0; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /math/0397-integer-replacement/README.md: -------------------------------------------------------------------------------- 1 | # 参考资料: 2 | + https://segmentfault.com/a/1190000007318944 3 | + http://massivealgorithms.blogspot.com/2016/09/leetcode-397-integer-replacement.html 4 | 5 | 当 n 为偶数时,下一次迭代 n 的取值确定为 n / 2; 6 | 当 n 为奇数时,下一次迭代 n 的取值 n + 1 或者 n - 1,由其二进制表示中的最低两位数决定: 7 | 若 n 的最低两位数为 01,则令 n = n - 1 8 | 否则,若 n 的最低两位数为 11,则令 n = n + 1 9 | 这样处理是为了使 n 的二进制表式中 1 的数目尽可能少,从而减少迭代次数。 -------------------------------------------------------------------------------- /math/0397-integer-replacement/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 使用递归的写法,要特别注意大整数溢出的情况 4 | 5 | public int integerReplacement(int n) { 6 | return longReplacement(n); 7 | } 8 | 9 | private int longReplacement(long n) { 10 | if (n <= 1) { 11 | return 0; 12 | } 13 | if (n == 2) { 14 | return 1; 15 | } 16 | if (n % 2 == 0) { 17 | return longReplacement(n / 2) + 1; 18 | } 19 | return 1 + Math.min(longReplacement(n + 1), longReplacement(n - 1)); 20 | } 21 | 22 | public static void main(String[] args) { 23 | Solution solution = new Solution(); 24 | int n = Integer.MAX_VALUE; 25 | int integerReplacement = solution.integerReplacement(n); 26 | System.out.println(integerReplacement); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /math/0397-integer-replacement/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | // 接下来把递归改成动态规划,这个解法通不过,不过采用动态的方式就可以了 4 | // 这行解法空间复杂度太高,会 超出内存限制 5 | 6 | public int integerReplacement(int n) { 7 | // 0 要占一个位子,所以要给出 n+1 个位子 8 | 9 | if (n <= 1) { 10 | return 0; 11 | } 12 | int[] dp = new int[n + 1]; 13 | dp[0] = 0; 14 | dp[1] = 0; 15 | dp[2] = 1; 16 | for (int i = 3; i <= n; i++) { 17 | if (i % 2 == 0) { 18 | dp[i] = dp[i / 2] + 1; 19 | } else { 20 | // 这样写就太死板了 21 | // dp[i] = 1 + Math.min(dp[i - 1], dp[i + 1]); 22 | dp[i] = Math.min(dp[i - 1] + 1, dp[(i + 1) / 2] + 2); 23 | } 24 | } 25 | return dp[n]; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /math/0397-integer-replacement/src/Solution3.java: -------------------------------------------------------------------------------- 1 | import java.util.HashMap; 2 | import java.util.Map; 3 | 4 | public class Solution3 { 5 | 6 | // 接下来把递归改成动态规划,使用 Hash 表 7 | // 使用动态的红黑树就不会 超出内存限制 了 8 | 9 | public int integerReplacement(int n) { 10 | // 0 要占一个位子,所以要给出 n+1 个位子 11 | if (n <= 1) { 12 | return 0; 13 | } 14 | Map map = new HashMap<>(); 15 | map.put(1, 0); 16 | return helper(n, map); 17 | } 18 | 19 | private int helper(int n, Map map) { 20 | Integer value = map.get(n); 21 | if (value == null) { 22 | if (n % 2 == 0) { 23 | value = helper(n / 2, map) + 1; 24 | } else { 25 | // n-1 /2 26 | // n+1 /2 27 | value = 2 + Math.min(helper(n / 2, map), helper(n / 2 + 1, map)); 28 | } 29 | } 30 | return value; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /math/0397-integer-replacement/src/Solution6.java: -------------------------------------------------------------------------------- 1 | public class Solution6 { 2 | 3 | public int integerReplacement(int n) { 4 | if (n == Integer.MAX_VALUE) { 5 | return 32; 6 | } 7 | if (n == 1) { 8 | return 0; 9 | } 10 | if (n == 2) { 11 | return 1; 12 | } 13 | if (n % 2 == 0) { 14 | return 1 + integerReplacement(n / 2); 15 | } 16 | return 1 + Math.min(integerReplacement(n - 1), integerReplacement(n + 1)); 17 | } 18 | 19 | public static void main(String[] args) { 20 | System.out.println(Integer.toBinaryString(Integer.MAX_VALUE)); 21 | System.out.println(Integer.MAX_VALUE); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /math/0507-perfect-number/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public boolean checkPerfectNumber(int num) { 4 | if (num == 1) { 5 | return false; 6 | } 7 | // 所有乘法因子的和存在这里 8 | int res = 1; 9 | // 可能的乘法因子,从 2 开始 10 | int factor = 2; 11 | while (factor * factor < num) { 12 | if (num % factor == 0 ) { 13 | res += factor; 14 | res += (num / factor); 15 | } 16 | factor += 1; 17 | } 18 | // 把中间那个数单独拿出来 19 | if (factor * factor == num) { 20 | res += factor; 21 | } 22 | return res == num; 23 | } 24 | 25 | public static void main(String[] args) { 26 | Solution solution = new Solution(); 27 | int num = 28; 28 | boolean res = solution.checkPerfectNumber(num); 29 | System.out.println(res); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /math/0633-sum-of-square-numbers/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public boolean judgeSquareSum(int c) { 4 | if (c < 0) { 5 | return false; 6 | } 7 | if (c == 0 || c == 1) { 8 | return true; 9 | } 10 | int limit = (int) Math.sqrt(c); 11 | for (int i = 0; i <= limit; i++) { 12 | double another = Math.sqrt(c - i * i); 13 | if (another - (int) another == 0) { 14 | return true; 15 | } 16 | } 17 | return false; 18 | } 19 | 20 | public static void main(String[] args) { 21 | Solution2 solution2 = new Solution2(); 22 | int n = 2; 23 | boolean judgeSquareSum = solution2.judgeSquareSum(n); 24 | System.out.println(judgeSquareSum); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /math/0836-rectangle-overlap(数学)/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 从判断两条线段是否有交点推广开来 4 | 5 | public boolean isRectangleOverlap(int[] rec1, int[] rec2) { 6 | return (Math.max(rec1[0], rec2[0]) < Math.min(rec1[2], rec2[2])) && 7 | (Math.max(rec1[1], rec2[1]) < Math.min(rec1[3], rec2[3])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /math/0868-binary-gap(数学)/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | // 参考了官方解答: 4 | // https://leetcode-cn.com/articles/binary-gap/ 5 | 6 | public int binaryGap(int N) { 7 | int pre = -1; 8 | int res = 0; 9 | int mask = 1; 10 | // 因为是正数,所以左移 30 位就够了 11 | for (int i = 0; i < 31; i++) { 12 | if ((N & mask) != 0) { 13 | if (pre >= 0) { 14 | res = Math.max(res, i - pre); 15 | } 16 | pre = i; 17 | } 18 | mask <<= 1; 19 | } 20 | return res; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /math/0868-binary-gap(数学)/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | // 还可以再节约一些空间 3 | 4 | public int binaryGap(int N) { 5 | // 因为是正数,所以 31 位就可以了 6 | int[] index = new int[31]; 7 | // 有数字 1 的索引 8 | int oneIndex = 0; 9 | int mask = 1; 10 | for (int i = 0; i < 31; i++) { 11 | if ((N & mask) != 0) { 12 | index[oneIndex] = i; 13 | oneIndex++; 14 | } 15 | mask <<= 1; 16 | } 17 | int res = 0; 18 | for (int i = 0; i < oneIndex - 1; i++) { 19 | res = Math.max(res, index[i + 1] - index[i]); 20 | } 21 | return res; 22 | } 23 | 24 | public static void main(String[] args) { 25 | Solution3 solution3 = new Solution3(); 26 | int binaryGap = solution3.binaryGap(22); 27 | System.out.println(binaryGap); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /recursion/0010-regular-expression-matching/src/Solution.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/8 4:16 下午 4 | */ 5 | public class Solution { 6 | 7 | // 递归 + 分类讨论 8 | // 使用递归的思想,第 1 个匹配了,后面的递归处理就可以了 9 | 10 | public boolean isMatch(String s, String p) { 11 | if (p.isEmpty()) { 12 | return s.isEmpty(); 13 | } 14 | boolean firstMatch = !s.isEmpty() && (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.'); 15 | if (p.length() > 1 && p.charAt(1) == '*') { 16 | // '*' 匹配 0 次 17 | if (isMatch(s, p.substring(2))) { 18 | return true; 19 | } 20 | // '*' 至少匹配 1 次 21 | return firstMatch && isMatch(s.substring(1), p); 22 | } 23 | return firstMatch && isMatch(s.substring(1), p.substring(1)); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /recursion/0010-regular-expression-matching/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/9 12:55 下午 4 | */ 5 | public class Solution2 { 6 | public boolean isMatch(String s, String p) { 7 | if (p.length() == 0){ 8 | return s.length() == 0; 9 | } 10 | 11 | boolean firstMatch = s.length() >= 1 && (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.'); 12 | 13 | if (p.length() > 1 && p.charAt(1) == '*'){ 14 | if (isMatch(s, p.substring(2))){ 15 | return true; 16 | } 17 | return firstMatch && isMatch(s.substring(1), p); 18 | } 19 | 20 | return firstMatch && isMatch(s.substring(1), p.substring(1)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /sliding-window/.idea/description.html: -------------------------------------------------------------------------------- 1 | Simple Java application that includes a class with main() method -------------------------------------------------------------------------------- /sliding-window/.idea/markdown-navigator/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /sliding-window/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /sliding-window/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /sliding-window/.idea/project-template.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sliding-window/0003-longest-substring-without-repeating-characters/src/Solution4.java: -------------------------------------------------------------------------------- 1 | import java.util.HashMap; 2 | import java.util.Map; 3 | 4 | /** 5 | * @author liweiwei1419 6 | * @date 2019/11/24 8:28 上午 7 | */ 8 | public class Solution4 { 9 | public int lengthOfLongestSubstring(String s) { 10 | int len = s.length(); 11 | // 特判 12 | if (len < 2) { 13 | return len; 14 | } 15 | 16 | int res = 1; 17 | Map map = new HashMap<>(len); 18 | int left = 0; 19 | for (int right = 0; right < len; right++) { 20 | Character c = s.charAt(right); 21 | if (map.containsKey(c)) { 22 | left = Math.max(left, map.get(c) + 1); 23 | } 24 | res = Math.max(res, right - left + 1); 25 | map.put(c, right); 26 | } 27 | return res; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /sliding-window/0209-minimum-size-subarray-sum/src/Solution4.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 2019/7/22 10:37 AM 4 | */ 5 | public class Solution4 { 6 | 7 | // 3 种写法本质上都是一样:滑动窗口 8 | public int minSubArrayLen2(int s, int[] nums) { 9 | int len = nums.length; 10 | if (len == 0) { 11 | return 0; 12 | } 13 | int l = 0; 14 | int segmentSum = 0; 15 | int minSubArrayLen = len + 1; 16 | for (int i = 0; i < len; i++) { 17 | 18 | segmentSum += nums[i]; 19 | while (segmentSum >= s) { 20 | minSubArrayLen = Integer.min(minSubArrayLen, i - l + 1); 21 | segmentSum -= nums[l]; 22 | l++; 23 | } 24 | } 25 | if (minSubArrayLen == len + 1) { 26 | return 0; 27 | } 28 | return minSubArrayLen; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /sliding-window/0978-longest-turbulent-subarray/src/Solution.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/11 11:28 下午 4 | */ 5 | public class Solution { 6 | public int maxTurbulenceSize(int[] A) { 7 | int len = A.length; 8 | if (len == 1) { 9 | return 1; 10 | } 11 | int res = 1; 12 | int left = 0; 13 | int right = 1; 14 | boolean isde = false; 15 | while (right < len) { 16 | if (A[right] == A[right - 1]) { 17 | left = right; 18 | right++; 19 | } else if (right - left == 1 || (A[right] - A[right - 1] < 0 != isde)) { 20 | isde = A[right] - A[right - 1] < 0; 21 | res = Math.max(res, right - left + 1); 22 | right++; 23 | } else { 24 | left = right - 1; 25 | } 26 | } 27 | return res; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /stack/0020-valid-parentheses/src/Solution2.java: -------------------------------------------------------------------------------- 1 | import java.util.Stack; 2 | 3 | /** 4 | * @author liweiwei1419 5 | * @date 2019/8/22 7:41 PM 6 | */ 7 | public class Solution2 { 8 | 9 | public boolean isValid2(String s) { 10 | int len = s.length(); 11 | if (len == 0) { 12 | return true; 13 | } 14 | Stack stack = new Stack<>(); 15 | for (int i = 0; i < len; i++) { 16 | if (s.charAt(i) == '(') { 17 | stack.push(')'); 18 | } else if (s.charAt(i) == '[') { 19 | stack.push(']'); 20 | } else if (s.charAt(i) == '{') { 21 | stack.push('}'); 22 | } else { 23 | if (stack.isEmpty() || stack.pop() != s.charAt(i)) { 24 | return false; 25 | } 26 | } 27 | } 28 | return stack.isEmpty(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /stack/0155-min-stack2/src/Main.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 2019/7/15 10:56 PM 4 | */ 5 | public class Main { 6 | 7 | public static void main(String[] args) { 8 | int a = Integer.MAX_VALUE; 9 | System.out.println(Integer.toBinaryString(a)); 10 | System.out.println(a); 11 | System.out.println(a + 1); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /stack/0155-min-stack2/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 | -------------------------------------------------------------------------------- /stack/0316-remove-duplicate-letters/src/Solution2.java: -------------------------------------------------------------------------------- 1 | import java.util.Stack; 2 | 3 | /** 4 | * @author liwei 5 | * @date 2019/6/27 10:26 AM 6 | */ 7 | public class Solution2 { 8 | 9 | public String removeDuplicateLetters(String s) { 10 | int len = s.length(); 11 | Stack stack = new Stack<>(); 12 | for (int i = 0; i < len; i++) { 13 | if (stack.contains(s.charAt(i))) { 14 | continue; 15 | } 16 | while (!stack.isEmpty() && s.charAt(i) < stack.peek() && s.indexOf(stack.peek(), i) != -1) { 17 | stack.pop(); 18 | } 19 | stack.add(s.charAt(i)); 20 | } 21 | 22 | StringBuilder sb = new StringBuilder(); 23 | for (Character c : stack) { 24 | sb.append(c); 25 | } 26 | return sb.toString(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /string/0010-regular-expression-matching/src/Solution3.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/9/22 10:56 下午 4 | */ 5 | public class Solution3 { 6 | public boolean isMatch(String s, String p) { 7 | if (p.isEmpty()) { 8 | return s.isEmpty(); 9 | } 10 | boolean firstMatch = !s.isEmpty() && (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.'); 11 | if (p.length() > 1 && p.charAt(1) == '*') { 12 | if (isMatch(s, p.substring(2))) { 13 | return true; 14 | } 15 | return firstMatch && isMatch(s.substring(1), p); 16 | } 17 | return firstMatch && isMatch(s.substring(1), p.substring(1)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /string/0010-regular-expression-matching/src/Solution4.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/9/23 1:12 下午 4 | */ 5 | public class Solution4 { 6 | 7 | // 递归 8 | 9 | public boolean isMatch(String s, String p) { 10 | if (p.isEmpty()) { 11 | return s.isEmpty(); 12 | } 13 | boolean firstMatch = !s.isEmpty() && (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.'); 14 | if (p.length() > 1 && p.charAt(1) == '*') { 15 | // '*' 表示 0 次 16 | if (isMatch(s, p.substring(2))) { 17 | return true; 18 | } 19 | return firstMatch && isMatch(s.substring(1), p); 20 | } 21 | return firstMatch && isMatch(s.substring(1), p.substring(1)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /string/0028-implement-strstr/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int strStr(String haystack, String needle) { 4 | int hlen = haystack.length(); 5 | int nlen = needle.length(); 6 | if (hlen == 0) { 7 | return -1; 8 | } 9 | if (nlen == 0) { 10 | return 0; 11 | } 12 | return haystack.indexOf(needle); 13 | } 14 | 15 | public static void main(String[] args) { 16 | Solution solution = new Solution(); 17 | String haystack = "hello"; 18 | String needle = "ll"; 19 | int strStr = solution.strStr(haystack, needle); 20 | System.out.println(strStr); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /string/0028-implement-strstr/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/6/28 下午1:33 4 | */ 5 | public class Solution2 { 6 | 7 | public int strStr(String haystack, String needle) { 8 | int hlen = haystack.length(); 9 | int nlen = needle.length(); 10 | if (nlen == 0) { 11 | return 0; 12 | } 13 | for (int i = 0; i <= hlen - nlen; i++) { 14 | if (needle.equals(haystack.substring(i, i + nlen))) { 15 | return i; 16 | } 17 | } 18 | return -1; 19 | } 20 | 21 | public static void main(String[] args) { 22 | Solution2 solution2 = new Solution2(); 23 | String haystack = "a"; 24 | String needle = "a"; 25 | int strStr = solution2.strStr(haystack, needle); 26 | System.out.println(strStr); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /string/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 | 19 | public static void main(String[] args) { 20 | String s = "a "; 21 | Solution2 solution2 = new Solution2(); 22 | int lengthOfLastWord = solution2.lengthOfLastWord(s); 23 | System.out.println(lengthOfLastWord); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /string/0344-reverse-string/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by liwei on 17/9/23. 3 | */ 4 | public class Solution2 { 5 | public String reverseString(String s) { 6 | char[] cArray = s.toCharArray(); 7 | int i = 0; 8 | int j = cArray.length - 1; 9 | while (i < j) { 10 | swap(cArray, i, j); 11 | i++; 12 | j--; 13 | } 14 | return new String(cArray); 15 | } 16 | 17 | private void swap(char[] s, int index1, int index2) { 18 | if (index1 == index2) { 19 | return; 20 | } 21 | char temp = s[index1]; 22 | s[index1] = s[index2]; 23 | s[index2] = temp; 24 | } 25 | 26 | public static void main(String[] args) { 27 | Solution2 solution = new Solution2(); 28 | String result = solution.reverseString("hello world"); 29 | System.out.println(result); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /string/0443-string-compression(字符串)/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liweiwei1419/Learning-Algorithms-by-LeetCode/633cdfc78b70f0aaa2dd4ac8c1b6a9043d2c0149/string/0443-string-compression(字符串)/README.md -------------------------------------------------------------------------------- /string/0459-repeated-substring-pattern(字符串)/src/Solution3.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 不好理解,但是代码看上去很酷 3 | * 4 | * @author liwei 5 | * @date 18/7/1 下午4:11 6 | */ 7 | public class Solution3 { 8 | 9 | public boolean repeatedSubstringPattern3(String s) { 10 | // 掐头去尾只要包含就可以了 11 | return ((s + s).substring(1, 2 * s.length() - 1).contains(s)); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /string/0521-longest-uncommon-subsequence-i/src/Solution.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 任何字符串本身都是一个子序列,空字符串是任何字符串的子序列。 3 | * 只需要判断两字符串是否相等,如果相等就返回 -1 ,不相等就返回较长的字符串长度。算是有一些坑的问题了,这道问题踩的人比较多。 4 | * 5 | * @author liwei 6 | */ 7 | public class Solution { 8 | 9 | public int findLUSlength(String a, String b) { 10 | if (a != null && a.equals(b)) { 11 | return -1; 12 | } 13 | return Math.max(a.length(), b.length()); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tree/0100-same-tree/src/Solution.java: -------------------------------------------------------------------------------- 1 | class TreeNode { 2 | int val; 3 | TreeNode left; 4 | TreeNode right; 5 | 6 | TreeNode(int x) { 7 | val = x; 8 | } 9 | } 10 | 11 | public class Solution { 12 | 13 | public boolean isSameTree(TreeNode p, TreeNode q) { 14 | // 先处理最特殊的情况,都为空结点的时候 15 | if (p == null && q == null) { 16 | return true; 17 | } 18 | // 走到这里说明两个结点都同时不为空,那么其中之一为空,或者两个结点的值不相等的时候,返回 false 19 | if (p == null || q == null || p.val != q.val) { 20 | return false; 21 | } 22 | return isSameTree(p.left, q.left) && isSameTree(p.right, q.right); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tree/0100-same-tree/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public boolean isSameTree(TreeNode p, TreeNode q) { 4 | if (p == null && q == null) { 5 | return true; 6 | } 7 | if (p == null || q == null || p.val != q.val) { 8 | return false; 9 | } 10 | return isSameTree(p.left, q.left) && isSameTree(p.right, q.right); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tree/0104-maximum-depth-of-binary-tree/src/Solution.java: -------------------------------------------------------------------------------- 1 | 2 | class TreeNode { 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } 11 | 12 | // 求一棵二叉树的最大深度 13 | 14 | public class Solution { 15 | 16 | public int maxDepth(TreeNode root) { 17 | if (root == null) { 18 | return 0; 19 | } 20 | return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1; 21 | } 22 | } 23 | 24 | 25 | -------------------------------------------------------------------------------- /tree/0108-convert-sorted-array-to-binary-search-tree/src/Solution.java: -------------------------------------------------------------------------------- 1 | class TreeNode { 2 | int val; 3 | TreeNode left; 4 | TreeNode right; 5 | 6 | TreeNode(int x) { 7 | val = x; 8 | } 9 | } 10 | 11 | public class Solution { 12 | 13 | private TreeNode merge(int[] nums, int left, int right) { 14 | if (left == right + 1) { 15 | return null; 16 | } 17 | int mid = left + (right - left) / 2; 18 | TreeNode treeNode = new TreeNode(nums[mid]); 19 | treeNode.left = merge(nums, left, mid - 1); 20 | treeNode.right = merge(nums, mid + 1, right); 21 | return treeNode; 22 | } 23 | 24 | public TreeNode sortedArrayToBST(int[] nums) { 25 | int len = nums.length; 26 | if (len == 0) { 27 | return null; 28 | } 29 | return merge(nums, 0, len - 1); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tree/0108-convert-sorted-array-to-binary-search-tree/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | private TreeNode merge(int[] nums, int left, int right) { 4 | if (left == right) { 5 | return null; 6 | } 7 | int mid = left + (right - left) / 2; 8 | TreeNode treeNode = new TreeNode(nums[mid]); 9 | treeNode.left = merge(nums, left, mid); 10 | treeNode.right = merge(nums, mid + 1, right); 11 | return treeNode; 12 | } 13 | 14 | public TreeNode sortedArrayToBST(int[] nums) { 15 | int len = nums.length; 16 | if (len == 0) { 17 | return null; 18 | } 19 | return merge(nums, 0, len); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tree/0108-convert-sorted-array-to-binary-search-tree/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | public TreeNode sortedArrayToBST(int[] nums) { 4 | int len = nums.length; 5 | if (len == 0) { 6 | return null; 7 | } 8 | int l = 0; 9 | int r = len - 1; 10 | return sortedArrayToBST(nums, l, r); 11 | } 12 | 13 | private TreeNode sortedArrayToBST(int[] nums, int left, int right) { 14 | // 递归终止的条件要先写 15 | if (left > right) { 16 | return null; 17 | } 18 | int mid = left + (right - left) / 2; 19 | TreeNode root = new TreeNode(nums[mid]); 20 | root.left = sortedArrayToBST(nums, left, mid - 1); 21 | root.right = sortedArrayToBST(nums, mid + 1, right); 22 | return root; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tree/0108-convert-sorted-array-to-binary-search-tree/src/Solution4.java: -------------------------------------------------------------------------------- 1 | public class Solution4 { 2 | 3 | // 将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。 4 | 5 | public TreeNode sortedArrayToBST(int[] nums) { 6 | int len = nums.length; 7 | if (len == 0) { 8 | return null; 9 | } 10 | return helper(nums, 0, len - 1); 11 | } 12 | 13 | private TreeNode helper(int[] nums, int left, int right) { 14 | if (left > right) { 15 | return null; 16 | } 17 | int mid = left + (right - left) / 2; 18 | TreeNode root = new TreeNode(nums[mid]); 19 | root.left = helper(nums, left, mid - 1); 20 | root.right = helper(nums, mid + 1, right); 21 | return root; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tree/0110-balanced-binary-tree/src/Solution.java: -------------------------------------------------------------------------------- 1 | class TreeNode { 2 | int val; 3 | TreeNode left; 4 | TreeNode right; 5 | 6 | TreeNode(int x) { 7 | val = x; 8 | } 9 | } 10 | 11 | class Solution { 12 | 13 | public boolean isBalanced(TreeNode root) { 14 | if (root == null) { 15 | return true; 16 | } 17 | return depth(root) != -1; 18 | } 19 | 20 | private int depth(TreeNode root) { 21 | if (root == null) { 22 | return 0; 23 | } 24 | int left = depth(root.left); 25 | int right = depth(root.right); 26 | 27 | if (left == -1 || right == -1 || Math.abs(left - right) > 1) { 28 | return -1; 29 | } 30 | return Integer.max(left, right) + 1; 31 | } 32 | } -------------------------------------------------------------------------------- /tree/0110-balanced-binary-tree/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | /** 4 | * 使用后序遍历验证是否平衡二叉树,方法和 Solution 是一样的 5 | * 6 | * @param root 7 | * @return 8 | */ 9 | public boolean isBalanced(TreeNode root) { 10 | if (root == null) { 11 | return true; 12 | } 13 | return helper(root) != -1; 14 | } 15 | 16 | private int helper(TreeNode node) { 17 | if (node == null) { 18 | return 0; 19 | } 20 | int left = helper(node.left); 21 | int right = helper(node.right); 22 | if (left == -1 || right == -1 || Math.abs(left - right) > 1) { 23 | return -1; 24 | } 25 | return Integer.max(left, right) + 1; 26 | } 27 | } -------------------------------------------------------------------------------- /tree/0110-balanced-binary-tree/src/Solution3.java: -------------------------------------------------------------------------------- 1 | public class Solution3 { 2 | 3 | public boolean isBalanced(TreeNode root) { 4 | if (root == null) { 5 | return true; 6 | } 7 | return helper(root) != -1; 8 | } 9 | 10 | private int helper(TreeNode node) { 11 | if (node == null) { 12 | return 0; 13 | } 14 | int left = helper(node.left); 15 | int right = helper(node.right); 16 | if (left == -1 || right == -1 || Math.abs(left - right) > 1) { 17 | return -1; 18 | } 19 | return Math.max(left, right) + 1; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tree/0111-minimum-depth-of-binary-tree/src/Solution.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/15 11:53 上午 4 | */ 5 | class TreeNode { 6 | int val; 7 | TreeNode left; 8 | TreeNode right; 9 | 10 | TreeNode(int x) { 11 | val = x; 12 | } 13 | } 14 | public class Solution { 15 | public int minDepth(TreeNode root) { 16 | if (root == null) { 17 | return 0; 18 | } 19 | // 这一步要特别注意,是一个很容易被忽略的情况 20 | if (root.left == null || root.right == null) { 21 | return Integer.max(minDepth(root.left), minDepth(root.right)) + 1; 22 | 23 | } 24 | return Integer.min(minDepth(root.left), minDepth(root.right)) + 1; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tree/0112-path-sum/src/Solution.java: -------------------------------------------------------------------------------- 1 | class TreeNode { 2 | int val; 3 | TreeNode left; 4 | TreeNode right; 5 | 6 | TreeNode(int x) { 7 | val = x; 8 | } 9 | } 10 | 11 | /** 12 | * @author liweiwei1419 13 | * @date 2019/10/15 11:54 上午 14 | */ 15 | public class Solution { 16 | public boolean hasPathSum(TreeNode root, int sum) { 17 | if (root == null) { 18 | return false; 19 | } 20 | if (root.left == null && root.right == null) { 21 | return sum == root.val; 22 | } 23 | boolean left = hasPathSum(root.left, sum - root.val); 24 | boolean right = hasPathSum(root.right, sum - root.val); 25 | return left || right; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tree/0144-binary-tree-preorder-traversal/src/Solution2.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.List; 3 | import java.util.Stack; 4 | 5 | public class Solution2 { 6 | 7 | // 二叉树的前序遍历(教科书一样的写法) 8 | // 要使用栈,而不是使用队列 9 | 10 | public List preorderTraversal(TreeNode root) { 11 | List result = new ArrayList<>(); 12 | if (root == null) { 13 | return result; 14 | } 15 | Stack stack = new Stack<>(); 16 | stack.push(root); 17 | while (!stack.isEmpty()) { 18 | TreeNode node = stack.pop(); 19 | result.add(node.val); 20 | if (node.right != null) { 21 | stack.push(node.right); 22 | } 23 | if (node.left != null) { 24 | stack.push(node.left); 25 | } 26 | } 27 | return result; 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /tree/0144-binary-tree-preorder-traversal/src/Solution3.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.List; 3 | 4 | 5 | public class Solution3 { 6 | 7 | private List result = new ArrayList<>(); 8 | 9 | private void preOrder(TreeNode treeNode) { 10 | if (treeNode == null) { 11 | return; 12 | } 13 | result.add(treeNode.val); 14 | preOrder(treeNode.left); 15 | preOrder(treeNode.right); 16 | } 17 | 18 | public List preorderTraversal(TreeNode root) { 19 | preOrder(root); 20 | return result; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tree/0144-binary-tree-preorder-traversal/src/Solution4.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.List; 3 | import java.util.Stack; 4 | 5 | public class Solution4 { 6 | 7 | public List preorderTraversal(TreeNode root) { 8 | List res = new ArrayList<>(); 9 | if (root == null) { 10 | return res; 11 | } 12 | Stack stack = new Stack<>(); 13 | stack.push(root); 14 | while (!stack.empty()) { 15 | TreeNode top = stack.pop(); 16 | res.add(top.val); 17 | if (top.right != null) { 18 | stack.push(top.right); 19 | } 20 | if (top.left != null) { 21 | stack.push(top.left); 22 | } 23 | } 24 | return res; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tree/0226-invert-binary-tree/src/Solution.java: -------------------------------------------------------------------------------- 1 | 2 | class TreeNode { 3 | int val; 4 | TreeNode left; 5 | TreeNode right; 6 | 7 | TreeNode(int x) { 8 | val = x; 9 | } 10 | } 11 | 12 | public class Solution { 13 | 14 | // 经典问题:反转二叉树 15 | 16 | // 使用前序遍历 17 | // 递归求解二叉树的问题,往往先处理节点为 null 的情况,可以减少很多为 null 的判断。 18 | 19 | public TreeNode invertTree(TreeNode root) { 20 | if (root == null) { 21 | return null; 22 | } 23 | // 左子树和右子树交换,即使左右子树都空也不影响正确性 24 | TreeNode temp = root.left; 25 | root.left = root.right; 26 | root.right = temp; 27 | 28 | // 递归翻转左右子树 29 | invertTree(root.left); 30 | invertTree(root.right); 31 | return root; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tree/0226-invert-binary-tree/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/7/3 下午6:10 4 | */ 5 | public class Solution2 { 6 | 7 | // 使用后序遍历 8 | 9 | public TreeNode invertTree(TreeNode root) { 10 | if (root == null) { 11 | return null; 12 | } 13 | 14 | invertTree(root.left); 15 | invertTree(root.right); 16 | 17 | TreeNode temp = root.left; 18 | root.left = root.right; 19 | root.right = temp; 20 | return root; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tree/0226-invert-binary-tree/src/Solution4.java: -------------------------------------------------------------------------------- 1 | // 仅仅只是练习 2 | // 思路很简单:先翻转左子树,再翻转右子树,再交换它们 3 | // 递归思想的应用 4 | 5 | public class Solution4 { 6 | 7 | public TreeNode invertTree(TreeNode root) { 8 | if (root == null) { 9 | return root; 10 | } 11 | TreeNode left = root.left; 12 | TreeNode right = root.right; 13 | root.left = invertTree(right); 14 | root.right = invertTree(left); 15 | return root; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tree/0236-lowest-common-ancestor-of-a-binary-tree/src/Solution2.java: -------------------------------------------------------------------------------- 1 | 2 | // 作为练习 3 | public class Solution2 { 4 | 5 | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { 6 | if (root == null || root == p || root == q) { 7 | return root; 8 | } 9 | TreeNode left = lowestCommonAncestor(root.left, p, q); 10 | TreeNode right = lowestCommonAncestor(root.right, p, q); 11 | if (left != null && right != null) { 12 | return root; 13 | } 14 | return left == null ? right : left; 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /tree/0257-binary-tree-paths/src/Solution2.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.List; 3 | 4 | public class Solution2 { 5 | 6 | private void dfs(TreeNode node, String pre, List res) { 7 | // 递归终止条件:走到根节点的时候,就可以把沿途积累的字符串添加到结果集中 8 | if (node.left == null && node.right == null) { 9 | res.add(pre + node.val); 10 | return; 11 | } 12 | if (node.left != null) { 13 | dfs(node.left, pre + node.val + "->", res); 14 | } 15 | if (node.right != null) { 16 | dfs(node.right, pre + node.val + "->", res); 17 | } 18 | } 19 | 20 | public List binaryTreePaths(TreeNode root) { 21 | // 将全局的结果保存在这里 22 | List res = new ArrayList<>(); 23 | if (root == null) { 24 | return res; 25 | } 26 | dfs(root, "", res); 27 | return res; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tree/0404-sum-of-left-leaves(树)/src/Solution.java: -------------------------------------------------------------------------------- 1 | class TreeNode { 2 | int val; 3 | TreeNode left; 4 | TreeNode right; 5 | 6 | TreeNode(int x) { 7 | val = x; 8 | } 9 | } 10 | 11 | /** 12 | * https://leetcode-cn.com/problems/sum-of-left-leaves/description/ 13 | */ 14 | public class Solution { 15 | 16 | public int sumOfLeftLeaves(TreeNode root) { 17 | if (root == null) { 18 | return 0; 19 | } 20 | // 表明是叶子节点 21 | if (root.left != null && root.left.left == null && root.left.right == null) { 22 | return root.left.val + sumOfLeftLeaves(root.right); 23 | } 24 | return sumOfLeftLeaves(root.left) + sumOfLeftLeaves(root.right); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tree/0404-sum-of-left-leaves(树)/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 18/7/3 下午9:44 4 | */ 5 | public class Solution2 { 6 | 7 | public int sumOfLeftLeaves(TreeNode root) { 8 | if (root == null) { 9 | return 0; 10 | } 11 | // 判断是叶子结点 12 | if (root.left != null && root.left.left == null && root.left.right == null) { 13 | return root.left.val + sumOfLeftLeaves(root.right); 14 | } 15 | return sumOfLeftLeaves(root.left) + sumOfLeftLeaves(root.right); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tree/0437-path-sum-iii(树)/src/Solution.java: -------------------------------------------------------------------------------- 1 | class TreeNode { 2 | int val; 3 | TreeNode left; 4 | TreeNode right; 5 | 6 | TreeNode(int x) { 7 | val = x; 8 | } 9 | } 10 | 11 | 12 | public class Solution { 13 | 14 | private int dfs(TreeNode root, int sum) { 15 | int result = 0; 16 | if (root == null) { 17 | return 0; 18 | } 19 | if (root.val == sum) { 20 | // 后面的满足条件的路径之和为 0 21 | result++; 22 | } 23 | result += dfs(root.left, sum - root.val); 24 | result += dfs(root.right, sum - root.val); 25 | return result; 26 | } 27 | 28 | public int pathSum(TreeNode root, int sum) { 29 | if (root == null) { 30 | return 0; 31 | } 32 | return dfs(root, sum) + pathSum(root.left, sum) + pathSum(root.right, sum); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /two-pointers/0011-container-with-most-water/src/Solution.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 2019/8/27 11:14 PM 4 | */ 5 | public class Solution { 6 | 7 | // 暴力解法,时间复杂度太高,我们应该使用指针对撞的方法 8 | 9 | public int maxArea(int[] height) { 10 | int len = height.length; 11 | if (len < 2) { 12 | return 0; 13 | } 14 | int res = 0; 15 | for (int i = 0; i < len - 1; i++) { 16 | for (int j = i + 1; j < len; j++) { 17 | res = Math.max(res, Math.min(height[i], height[j]) * (j - i)); 18 | } 19 | } 20 | return res; 21 | } 22 | 23 | public static void main(String[] args) { 24 | int[] height = {1, 8, 6, 2, 5, 4, 8, 3, 7}; 25 | Solution solution = new Solution(); 26 | int res = solution.maxArea(height); 27 | System.out.println(res); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /two-pointers/0011-container-with-most-water/src/Solution3.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/29 1:28 下午 4 | */ 5 | public class Solution3 { 6 | 7 | public int maxArea(int[] height) { 8 | int len = height.length; 9 | if (len < 2) { 10 | return 0; 11 | } 12 | 13 | int left = 0; 14 | int right = len - 1; 15 | 16 | int res = 0; 17 | while (left < right) { 18 | int minHeight = Math.min(height[left], height[right]); 19 | res = Math.max(res, minHeight * (right - left)); 20 | 21 | if (height[left] == minHeight) { 22 | left++; 23 | } else { 24 | right--; 25 | } 26 | } 27 | return res; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /two-pointers/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 | // j 是马上要赋值的那个索引 9 | int j = 1; 10 | int pre = nums[0]; 11 | for (int i = 1; i < len; i++) { 12 | if (nums[i] != pre) { 13 | nums[j] = nums[i]; 14 | pre = nums[j]; 15 | j++; 16 | } 17 | } 18 | return j; 19 | 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /two-pointers/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 | // 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 | } 19 | -------------------------------------------------------------------------------- /two-pointers/0088-merge-sorted-array/src/Solution.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/11/25 4 | */ 5 | public class Solution { 6 | 7 | public void merge(int[] nums1, int m, int[] nums2, int n) { 8 | int i = m - 1; 9 | int j = n - 1; 10 | 11 | int end = m + n - 1; 12 | for (int k = end; k >= 0; k--) { 13 | if (i < 0) { 14 | nums1[k] = nums2[j]; 15 | j--; 16 | } else if (j < 0) { 17 | break; 18 | } else if (nums1[i] >= nums2[j]) { 19 | nums1[k] = nums1[i]; 20 | i--; 21 | } else { 22 | nums1[k] = nums2[j]; 23 | j--; 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /two-pointers/0167-two-sum-ii-input-array-is-sorted2/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | // 双指针对撞 while 写法 4 | 5 | public int[] twoSum(int[] numbers, int target) { 6 | int left = 0; 7 | int right = numbers.length - 1; 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 | throw new RuntimeException("在数组中没有找到这样的两个数,使得它们的和为指定值"); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /two-pointers/0334-increasing-triplet-subsequence/src/Solution.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liwei 3 | * @date 2019/8/31 1:30 PM 4 | */ 5 | public class Solution { 6 | 7 | // 思想:双指针 8 | // 空间复杂度:O(N) 9 | // 时间复杂度:O(1) 10 | 11 | public boolean increasingTriplet(int[] nums) { 12 | // 注意:两个都是小于等于 13 | int one = Integer.MAX_VALUE; 14 | int two = Integer.MAX_VALUE; 15 | for (int num : nums) { 16 | if (num <= one) { 17 | one = num; 18 | } else if (num <= two) { 19 | // 执行到这里一定有 num > one 20 | two = num; 21 | } else { 22 | // 执行到这里一定有 num > two > one 23 | return true; 24 | } 25 | } 26 | return false; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /two-pointers/0713-subarray-product-less-than-k/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/9/20 3:15 下午 4 | */ 5 | public class Solution2 { 6 | 7 | // 滑动窗口模板 8 | 9 | public int numSubarrayProductLessThanK(int[] nums, int k) { 10 | if (k <= 1) { 11 | return 0; 12 | } 13 | int len = nums.length; 14 | int left = 0; 15 | int count = 0; 16 | int product = 1; 17 | for (int right = 0; right < len; right++) { 18 | product *= nums[right]; 19 | while (product >= k) { 20 | product /= nums[left]; 21 | left++; 22 | } 23 | count += (right - left + 1); 24 | } 25 | return count; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /股票问题/0121-best-time-to-buy-and-sell-stock/src/Solution.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/28 10:40 上午 4 | */ 5 | public class Solution { 6 | 7 | // 暴力枚举 8 | // 时间复杂度:O(N^2) 9 | 10 | public int maxProfit(int[] prices) { 11 | int len = prices.length; 12 | if (len < 2) { 13 | return 0; 14 | } 15 | 16 | // 有可能不做交易,因此结果集的初始值设置为 0 17 | int res = 0; 18 | for (int i = 0; i < len - 1; i++) { 19 | for (int j = i + 1; j < len; j++) { 20 | res = Math.max(res, prices[j] - prices[i]); 21 | } 22 | } 23 | return res; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /股票问题/0121-best-time-to-buy-and-sell-stock/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/28 10:40 上午 4 | */ 5 | public class Solution2 { 6 | 7 | // 对暴力方法的优化:我们只关心之前(不包括现在)看到的最低股价 8 | // 时间复杂度:O(N) 9 | 10 | public int maxProfit(int[] prices) { 11 | int len = prices.length; 12 | if (len < 2) { 13 | return 0; 14 | } 15 | 16 | int res = 0; 17 | 18 | // 表示在当前位置之前的最小值,假设修正法(打擂台法) 19 | int minVal = prices[0]; 20 | // 注意:这里从 1 开始 21 | for (int i = 1; i < len; i++) { 22 | res = Math.max(res, prices[i] - minVal); 23 | minVal = Math.min(minVal, prices[i]); 24 | } 25 | return res; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /股票问题/0121-best-time-to-buy-and-sell-stock/src/Solution5.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/28 10:40 上午 4 | */ 5 | public class Solution5 { 6 | 7 | // 动态规划 8 | 9 | public int maxProfit(int[] prices) { 10 | int len = prices.length; 11 | if (len < 2) { 12 | return 0; 13 | } 14 | 15 | int[][] dp = new int[2][2]; 16 | dp[0][0] = 0; 17 | dp[0][1] = -prices[0]; 18 | for (int i = 1; i < len; i++) { 19 | dp[i & 1][0] = Math.max(dp[(i - 1) & 1][0], dp[(i - 1) & 1][1] + prices[i]); 20 | dp[i & 1][1] = Math.max(dp[(i - 1) & 1][1], -prices[i]); 21 | } 22 | return dp[(len - 1) & 1][0]; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /股票问题/0121-best-time-to-buy-and-sell-stock/src/Solution6.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/28 10:40 上午 4 | */ 5 | public class Solution6 { 6 | 7 | 8 | public int maxProfit(int[] prices) { 9 | int len = prices.length; 10 | if (len < 2) { 11 | return 0; 12 | } 13 | 14 | int[] dp = new int[2]; 15 | dp[0] = 0; 16 | dp[1] = -prices[0]; 17 | for (int i = 1; i < len; i++) { 18 | dp[0] = Math.max(dp[0], dp[1] + prices[i]); 19 | dp[1] = Math.max(dp[1], -prices[i]); 20 | } 21 | return dp[0]; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /股票问题/0121-best-time-to-buy-and-sell-stock/src/Solution8.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/28 10:40 上午 4 | */ 5 | public class Solution8 { 6 | 7 | public int maxProfit(int[] prices) { 8 | int len = prices.length; 9 | if (len < 2) { 10 | return 0; 11 | } 12 | 13 | int pre = prices[1] - prices[0]; 14 | // 还是要考虑到 [7 , 6, 5, 4, 3] 这种不交易的情况 15 | // 初值应该考虑 0 16 | int res = Math.max(0, pre); 17 | int diff; 18 | int cur; 19 | 20 | for (int i = 1; i < len - 1; i++) { 21 | diff = prices[i + 1] - prices[i]; 22 | cur = Math.max(diff, pre + diff); 23 | res = Math.max(res, cur); 24 | pre = cur; 25 | } 26 | return res; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /股票问题/0122-best-time-to-buy-and-sell-stock-ii/src/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public int maxProfit(int[] prices) { 4 | int res = 0; 5 | int len = prices.length; 6 | for (int i = 0; i < len - 1; i++) { 7 | int diff = prices[i + 1] - prices[i]; 8 | if (diff > 0) { 9 | res += diff; 10 | } 11 | } 12 | return res; 13 | } 14 | 15 | public static void main(String[] args) { 16 | int[] prices = {7, 1, 5, 3, 6, 4}; 17 | Solution solution = new Solution(); 18 | int maxProfit = solution.maxProfit(prices); 19 | System.out.println(maxProfit); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /股票问题/0122-best-time-to-buy-and-sell-stock-ii/src/Solution2.java: -------------------------------------------------------------------------------- 1 | public class Solution2 { 2 | 3 | public int maxProfit(int[] prices) { 4 | int res = 0; 5 | int len = prices.length; 6 | for (int i = 0; i < len - 1; i++) { 7 | res += Math.max(prices[i + 1] - prices[i], 0); 8 | } 9 | return res; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /股票问题/0122-best-time-to-buy-and-sell-stock-ii/src/Solution4.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/29 2:54 下午 4 | */ 5 | public class Solution4 { 6 | 7 | // 动态规划 8 | 9 | // cash:持有现金 10 | // hold:持有股票 11 | 12 | public int maxProfit(int[] prices) { 13 | int len = prices.length; 14 | if (len < 2) { 15 | return 0; 16 | } 17 | 18 | // 状态数组 19 | // 状态转移:cash → hold → cash → hold → cash → hold → cash 20 | int[] cash = new int[len]; 21 | int[] hold = new int[len]; 22 | 23 | cash[0] = 0; 24 | hold[0] = -prices[0]; 25 | 26 | for (int i = 1; i < len; i++) { 27 | // 说明这两行调换顺序也是可以的 28 | cash[i] = Math.max(cash[i - 1], hold[i - 1] + prices[i]); 29 | hold[i] = Math.max(hold[i - 1], cash[i - 1] - prices[i]); 30 | } 31 | return cash[len - 1]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /股票问题/0122-best-time-to-buy-and-sell-stock-ii/src/Solution5.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/29 2:54 下午 4 | */ 5 | public class Solution5 { 6 | 7 | // 动态规划:状态压缩 8 | 9 | // cash:持有现金 10 | // hold:持有股票 11 | 12 | public int maxProfit(int[] prices) { 13 | int len = prices.length; 14 | if (len < 2) { 15 | return 0; 16 | } 17 | 18 | // 状态数组 19 | // 状态转移:cash → hold → cash → hold → cash → hold → cash 20 | 21 | int cash = 0; 22 | int hold = -prices[0]; 23 | 24 | int preCash = cash; 25 | int preHold = hold; 26 | for (int i = 1; i < len; i++) { 27 | cash = Math.max(preCash, preHold + prices[i]); 28 | hold = Math.max(preHold, preCash - prices[i]); 29 | 30 | preCash = cash; 31 | preHold = hold; 32 | 33 | } 34 | return cash; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /股票问题/0122-best-time-to-buy-and-sell-stock-ii/src/Solution6.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/29 2:54 下午 4 | */ 5 | public class Solution6 { 6 | 7 | // 动态规划 8 | 9 | // 0:持有现金 10 | // 1:持有股票 11 | 12 | public int maxProfit(int[] prices) { 13 | int len = prices.length; 14 | if (len < 2) { 15 | return 0; 16 | } 17 | 18 | // 状态数组 19 | // 状态转移:cash → hold → cash → hold → cash → hold → cash 20 | // 状态转移:0 → 1 → 0 → 1 → 0 → 1 → 0 21 | int[][] dp = new int[len][2]; 22 | 23 | dp[0][0] = 0; 24 | dp[0][1] = -prices[0]; 25 | 26 | for (int i = 1; i < len; i++) { 27 | // 说明这两行调换顺序也是可以的 28 | dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]); 29 | dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]); 30 | } 31 | return dp[len - 1][0]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /股票问题/0123-best-time-to-buy-and-sell-stock-iii/src/Solution2.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author liweiwei1419 3 | * @date 2019/10/20 9:52 下午 4 | */ 5 | public class Solution2 { 6 | 7 | 8 | } 9 | -------------------------------------------------------------------------------- /阿里巴巴Java开发手册(华山版).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liweiwei1419/Learning-Algorithms-by-LeetCode/633cdfc78b70f0aaa2dd4ac8c1b6a9043d2c0149/阿里巴巴Java开发手册(华山版).pdf --------------------------------------------------------------------------------