├── .gitignore ├── LICENSE ├── README.md └── solutions ├── 0004-median-of-two-sorted-arrays ├── 0004.md └── 0004.py ├── 0011-Container-With-Most-Water └── 0011.py ├── 0017-Letter-Combinations-of-a-Phone-Number ├── 0017-LeetCode-solution.md └── 0017.py ├── 0020-Valid-Parentheses └── 0020.py ├── 0026-remove-duplicates-from-sorted-array ├── 0026.md └── 0026.py ├── 0033-search-in-rotated-sorted-array ├── 0033.md └── 0033.py ├── 0034-Find-First-and-Last-Position-of-Element-in-Sorted-Array ├── 0034-LeetCode-solution.md ├── 0034.md └── 0034.py ├── 0039-Combination-Sum ├── 0039-LeetCode-solution.md └── 0039.py ├── 0040-Combination-Sum-II ├── 0040-LeetCode-solution.md └── 0040.py ├── 0046-Permutations ├── 0046-LeetCode-solution.md └── 0046.py ├── 0047-Permutations-II ├── 0047-LeetCode-solution.md └── 0047.py ├── 0051-N-Queens ├── 0051-LeetCode-solution.md └── 0051.py ├── 0053-Maximum-Subarray ├── 0053-LeetCode-solution.md └── 0053.py ├── 0069-Sqrt-x ├── 0069-LeetCode-solution.md └── 0069.py ├── 0070-Climbing-Stairs ├── 0070-LeetCode-solution.md └── 0070.py ├── 0074-search-a-2d-matrix ├── 0074.md └── 0074.py ├── 0075-Sort-Colors ├── 0075-LeetCode-solution.md ├── 0075.md └── 0075.py ├── 0077-Combinations ├── 0077-LeetCode-solution.md └── 0077.py ├── 0078-Subsets └── 0078.py ├── 0079-Word-Search ├── 0079-LeetCode-solution.md └── 0079.py ├── 0080-remove-duplicates-from-sorted-array-ii └── 0080.py ├── 0081-search-in-rotated-sorted-array-ii ├── 0081.md └── 0081.py ├── 0088-Merge-Sorted-Array ├── 0088-LeetCode-solution.md ├── 0088.md └── 0088.py ├── 0090-Subsets-II ├── 0090-LeetCode-solution.md └── 0090.py ├── 0093-Restore-IP-Addresses ├── 0093-LeetCode-solution.md └── 0093.py ├── 0095-Unique-Binary-Search-Trees-II ├── 0095-LeetCode-solution.md └── 0095.py ├── 0098-Validate-Binary-Search-Tree ├── 0098-LeetCode-solution.md └── 0098.py ├── 0100-Same-Tree ├── 0100-LeetCode-solution.md └── 0100.py ├── 0101-Symmetric-Tree └── 0101.py ├── 0102-Binary-Tree-Level-Order-Traversal ├── 0102-LeetCode-solution.md └── 0102.py ├── 0103-Binary-Tree-Zigzag-Level-Order-Traversal ├── 0103-LeetCode-solution.md └── 0103.py ├── 0104-Maximum-Depth-of-Binary-Tree └── 0104.py ├── 0105-Construct-Binary-Tree-from-Preorder-and-Inorder-Traversal ├── 0105-LeetCode-solution.md └── 0105.py ├── 0106-Construct-Binary-Tree-from-Inorder-and-Postorder-Traversal ├── 0106-LeetCode-solution.md └── 0106.py ├── 0110-Balanced-Binary-Tree └── 0110.py ├── 0111-Minimum-Depth-of-Binary-Tree ├── 0111-LeetCode-solution.md └── 0111.py ├── 0113-Path-Sum-II ├── 0113-LeetCode-solution.md └── 0113.py ├── 0114-Flatten-Binary-Tree-to-Linked-List ├── 0114-LeetCode-solution.md ├── 0114.go └── 0114.py ├── 0116-Populating-Next-Right-Pointers-in-Each-Node ├── 0116-LeetCode-solution.md ├── 0116.go └── 0116.py ├── 0118-Pascal's-Triangle └── 0118.py ├── 0121-Best-Time-to-Buy-and-Sell-Stock ├── 0121-LeetCode-solution.md └── 0121.py ├── 0122-Best-Time-to-Buy-and-Sell-Stock-II ├── 0122-LeetCode-solution.md └── 0122.py ├── 0123-Best-Time-to-Buy-and-Sell-Stock-III ├── 0123-LeetCode-solution.md └── 0123.py ├── 0127-Word-Ladder ├── 0127-LeetCode-solution.md └── 0127.py ├── 0129-Sum-Root-to-Leaf-Numbers ├── 0129-LeetCode-solution.md └── 0129.py ├── 0130-Surrounded-Regions ├── 0130-LeetCode-solution.md └── 0130.py ├── 0141-Linked-List-Cycle ├── 0141-LeetCode-solution.md └── 0141.py ├── 0144-Binary-Tree-Preorder-Traversal ├── 0144-LeetCode-solution.md └── 0144.py ├── 0145-Binary-Tree-Postorder-Traversal ├── 0145-LeetCode-solution.md └── 0145.py ├── 0153-Find-Minimum-in-Rotated-Sorted-Array ├── 0153-LeetCode-solution.md └── 0153.py ├── 0162-find-peak-element ├── 0162.md └── 0162.py ├── 0167-Two-Sum-II-Input-array-is-sorted ├── 0167-LeetCode-solution.md └── 0167.py ├── 0169-Majority-Element └── 0169.py ├── 0188-Best-Time-to-Buy-and-Sell-Stock-IV ├── 0188-LeetCode-solution.md └── 0188.py ├── 0200-Number-of-Islands ├── 0200-LeetCode-solution.md └── 0200.py ├── 0206-Reverse-Linked-List ├── 0206-LeetCode-solution.md └── 0206.py ├── 0215-Kth-Largest-Element-in-an-Array ├── 0215-LeetCode-solution.md └── 0215.py ├── 0222-Count-Complete-Tree-Nodes ├── 0222-LeetCode-solution.md └── 0222.py ├── 0225-Implement-Stack-using-Queues ├── 0225-LeetCode-solution.md └── 0225.py ├── 0226-Invert-Binary-Tree ├── 0226-LeetCode-solution.md ├── 0226.go └── 0226.py ├── 0230-Kth-Smallest-Element-in-a-BST ├── 0230-LeetCode-solution.md └── 0230.py ├── 0235-Lowest-Common-Ancestor-of-a-Binary-Search-Tree ├── 0235-LeetCode-solution.md └── 0235.py ├── 0236-Lowest-Common-Ancestor-of-a-Binary-Tree ├── 0236-LeetCode-solution.md └── 0236.py ├── 0240-Search-a-2D-Matrix-II ├── 0240-LeetCode-solution.md └── 0240.py ├── 0241-Different-Ways-to-Add-Parentheses ├── 0241-LeetCode-solution.md └── 0241.py ├── 0257-Binary-Tree-Paths ├── 0257-LeetCode-solution.md └── 0257.py ├── 0278-First-Bad-Version ├── 0278-LeetCode-solution.md └── 0278.py ├── 0279-Perfect-Squares ├── 0279-LeetCode-solution.md └── 0279.py ├── 0283-move-zeroes ├── 0283.md └── 0283.py ├── 0300-Longest-Increasing-Subsequence └── 0300.py ├── 0309-Best-Time-to-Buy-and-Sell-Stock-with-Cooldown ├── 0309-LeetCode-solution.md └── 0309.py ├── 0322-Coin-Change └── 0322.py ├── 0332-Reconstruct-Itinerary └── 0332.py ├── 0345-Reverse-Vowels-of-a-String ├── 0345-LeetCode-solution.md └── 0345.py ├── 0347-Top-K-Frequent-Elements ├── 0347-LeetCode-solution.md └── 0347.py ├── 0365-Water-and-Jug-Problem ├── 0365-LeetCode-solution.md └── 0365.py ├── 0392-Is-Subsequence ├── 0392-LeetCode-solution.md └── 0392.py ├── 0406-Queue-Reconstruction-by-Height ├── 0406-LeetCode-solution.md └── 0406.py ├── 0409-Longest-Palindrome ├── 0409-LeetCode-solution.md └── 0409.py ├── 0417-Pacific-Atlantic-Water-Flow ├── 0417-LeetCode-solution .md └── 0417.py ├── 0429-N-ary-Tree-Level-Order-Traversal ├── 0429-LeetCode-solution.md └── 0429.py ├── 0435-Non-overlapping-Intervals ├── 0435-LeetCode-solution.md └── 0435.py ├── 0445-Add-Two-Numbers-II └── 0445.py ├── 0450-Delete-Node-in-a-BST ├── 0450-LeetCode-solution.md └── 0450.py ├── 0451-Sort-Characters-By-Frequency ├── 0451-LeetCode-solution.md └── 0451.py ├── 0452-Minimum-Number-of-Arrows-to-Burst-Balloons ├── 0452-LeetCode-solution.md └── 0452.py ├── 0455-Assign-Cookies ├── 0455-LeetCode-solution.md └── 0455.py ├── 0491-Increasing-Subsequences ├── 0491-LeetCode-solution.md └── 0491.py ├── 0508-Most-Frequent-Subtree-Sum ├── 0508-LeetCode-solution.md └── 0508.py ├── 0509-Fibonacci-Number ├── 0509-LeetCode-solution.md └── 0509.py ├── 0513-Find-Bottom-Left-Tree-Value ├── 0513-LeetCode-solution.md └── 0513.py ├── 0515-Find-Largest-Value-in-Each-Tree-Row ├── 0515-LeetCode-solution.md └── 0515.py ├── 0524-Longest-Word-in-Dictionary-through-Deleting ├── 0524-LeetCode-solution.md └── 0524.py ├── 0529-Minesweeper └── 0529.py ├── 0530-Minimum-Absolute-Difference-in-BST ├── 0530-LeetCode-solution.md └── 0530.py ├── 0538-Convert-BST-to-Greater-Tree ├── 0538-LeetCode-solution.md └── 0538.py ├── 0540-Single-Element-in-a-Sorted-Array ├── 0540-LeetCode-solution.md └── 0540.py ├── 0542-01-Matrix └── 0542.py ├── 0543-Diameter-of-Binary-Tree ├── 0543-LeetCode-solution.md └── 0543.py ├── 0547-Friend-Circles ├── 0547-LeetCode-solution.md └── 0547.py ├── 0559-Maximum-Depth-of-N-ary-Tree ├── 0559-LeetCode-solution.md └── 0559.py ├── 0563-Binary-Tree-Tilt ├── 0563-LeetCode-solution.md └── 0563.py ├── 0589-N-ary-Tree-Preorder-Traversal ├── 0589-LeetCode-solution.md └── 0589.py ├── 0590-N-ary-Tree-Postorder-Traversal ├── 0590-LeetCode-solution.md └── 0590.py ├── 0605-Can-Place-Flowers ├── 0605-LeetCode-solution.md └── 0605.py ├── 0606-Construct-String-from-Binary-Tree ├── 0606-LeetCode-solution.md └── 0606.py ├── 0623-Add-One-Row-to-Tree ├── 0623-LeetCode-solution.md └── 0623.py ├── 0633-Sum-of-Square-Numbers ├── 0633-LeetCode-solution.md └── 0633.py ├── 0647-Palindromic-Substrings ├── 0647-LeetCode-solution.md └── 0647.py ├── 0652-Find-Duplicate-Subtrees ├── 0652-LeetCode-solution.md └── 0652.py ├── 0653-Two-Sum-IV-Input-is-a-BST ├── 0653-LeetCode-solution.md └── 0653.py ├── 0654-Maximum-Binary-Tree ├── 0654-LeetCode-solution.md └── 0654.py ├── 0655-Print-Binary-Tree ├── 0655-LeetCode-solution.md └── 0655.py ├── 0657-Robot-Return-to-Origin └── 0657.py ├── 0662-Maximum-Width-of-Binary-Tree ├── 0662-LeetCode-solution.md └── 0662.py ├── 0665-Non-decreasing-Array ├── 0665-LeetCode-solution.md └── 0665.py ├── 0669-Trim-a-Binary-Search-Tree ├── 0669-LeetCode-solution.md └── 0669.py ├── 0671-Second-Minimum-Node-In-a-Binary-Tree ├── 0671-LeetCode-solution.md └── 0671.py ├── 0680-Valid-Palindrome-II ├── 0680-LeetCode-solution.md └── 0680.py ├── 0695-Max-Area-of-Island ├── 0695-LeetCode-solution.md └── 0695.py ├── 0700-Search-in-a-Binary-Search-Tree ├── 0700-LeetCode-solution.md └── 0700.py ├── 0701-Insert-into-a-Binary-Search-Tree ├── 0701-LeetCode-solution.md └── 0701.py ├── 0702-search-in-a-sorted-array-of-unknown-size ├── 0702.md ├── 0702.pdf └── 0702.py ├── 0704-binary-search ├── 0704.md └── 0704.py ├── 0714-Best-Time-to-Buy-and-Sell-Stock-with-Transaction-Fee ├── 0714-LeetCode-solution.md └── 0714.py ├── 0744-Find-Smallest-Letter-Greater-Than-Target ├── 0744-LeetCode-solution.md └── 0744.py ├── 0783-Minimum-Distance-Between-BST-Nodes ├── 0783-LeetCode-solution.md └── 0783.py ├── 0814-Binary-Tree-Pruning └── 0814.py ├── 0836-Rectangle-Overlap ├── 0836-LeetCode-solution.md └── 0836.py ├── 0875-koko-eating-bananas ├── 0875.md └── 0875.py ├── 0876-Middle-of-the-Linked-List ├── 0876-LeetCode-solution.md └── 0876.py ├── 0892-Surface-Area-of-3D-Shapes ├── 0892-LeetCode-solution.md └── 0892.py ├── 0912-Sort-an-Array ├── 0912.md └── 0912.py ├── 0914-X-of-a-Kind-in-a-Deck-of-Cards ├── 0914-LeetCode-solution.md └── 0914.py ├── 0994-Rotting-Oranges ├── 0994-LeetCode-solution.md └── 0994.py ├── 1013-Partition-Array-Into-Three-Parts-With-Equal-Sum ├── 1013-LeetCode-solution.md └── 1013.py ├── 1038-Binary-Search-Tree-to-Greater-Sum-Tree ├── 1038-LeetCode-solution.md └── 1038.py ├── 1071-Greatest-Common-Divisor-of-Strings ├── 1071-LeetCode-solution.md └── 1071.py ├── 1091-Shortest-Path-in-Binary-Matrix ├── 1091-LeetCode-solution.md └── 1091.py ├── 1103-Distribute-Candies-to-People ├── 1103-LeetCode-solution.md └── 1103.py ├── 1160-Find-Words-That-Can-Be-Formed-by-Characters ├── 1160-LeetCode-solution.md └── 1160.py ├── 1283-find-the-smallest-divisor-given-a-threshold ├── 1283.md └── 1283.py ├── 1358-Number-of-Substrings-Containing-All-Three-Characters ├── 1358.py └── 1538-LeetCode-solution.md ├── 1360-Number-of-Days-Between-Two-Dates ├── 1360-LeetCode-solution.md └── 1360.py ├── 1362-Closest-Divisors ├── 1362-LeetCode-solution.md └── 1362.py ├── 1365-How-Many-Numbers-Are-Smaller-Than-the-Current-Number ├── 1365-LeetCode-solution.md └── 1365.py ├── 1366-Rank-Teams-by-Votes ├── 1366-LeetCode-solution.md └── 1366.py ├── 1367-Linked-List-in-Binary-Tree ├── 1367-LeetCode-solution.md └── 1367.py ├── 1370-Increasing-Decreasing-String ├── 1370-LeetCode-solution.md └── 1370.py ├── 1372-Longest-ZigZag-Path-in-a-Binary-Tree ├── 1372-LeetCode-solution.md └── 1372.py ├── 1374-Generate-a-String-With-Characters-That-Have-Odd-Counts ├── 1374-LeetCode-solution.md └── 1374.py ├── 1375-Bulb-Switcher-III ├── 1375-LeetCode-solution.md └── 1375.py ├── 1376-Time-Needed-to-Inform-All-Employees ├── 1376-LeetCode-solution.md └── 1376.py ├── 1380-Lucky-Numbers-in-a-Matrix ├── 1380-LeetCode-solution.md └── 1380.py ├── 1381-Design-a-Stack-With-Increment-Operation ├── 1381-LeetCode-solution.md └── 1381.py ├── 1382-Balance-a-Binary-Search-Tree ├── 1382-LeetCode-solution.md └── 1382.py ├── 1385-Find-the-Distance-Value-Between-Two-Arrays ├── 1385-LeetCode-solution.md └── 1385.py ├── 1386-Cinema-Seat-Allocation ├── 1386-LeetCode-solution.md └── 1386.py ├── 1387-Sort-Integers-by-The-Power-Value ├── 1387-LeetCode-solution.md └── 1387.py ├── 1389-Create-Target-Array-in-the-Given-Order ├── 1389-LeetCode-solution.md └── 1389.py ├── 1390-Four-Divisors ├── 1390-LeetCode-solution.md └── 1390.py ├── 1394-Find-Lucky-Integer-in-an-Array ├── 1394-LeetCode-solution.md └── 1394.py ├── 1395-Count-Number-of-Teams ├── 1395-LeetCode-solution.md └── 1395.py ├── 1396-Design-Underground-System ├── 1396-LeetCode-solution.md └── 1396.py ├── 1408-String-Matching-in-an-Array ├── 1408-LeetCode-solution.md └── 1408.py ├── 1409-Queries-on-a-Permutation-With-Key ├── 1409-LeetCode-solution.md └── 1409.py ├── 1410-HTML-Entity-Parser ├── 1410-LeetCode-solution.md └── 1410.py ├── 1413-Minimum-Value-to-Get-Positive-Step-by-Step-Sum └── 1413.py ├── 1414-Find-the-Minimum-Number-of-Fibonacci-Numbers-Whose-Sum-Is-K └── 1414.py ├── 1415-The-k-th-Lexicographical-String-of-All-Happy-Strings-of-Length-n └── 1415.py ├── 1417-Reformat-The-String └── 1417.py ├── Interview-01.06-compress-string-lcci ├── 0106-LeetCode-solution.md └── 0106.py ├── Interview-01.07-rotate-matrix-lcci ├── 0107-LeetCode-solution.md └── 0107.py ├── Interview-03-shu-zu-zhong-zhong-fu-de-shu-zi-lcof ├── 03-LeetCode-solution.md └── 03.py ├── Interview-04-er-wei-shu-zu-zhong-de-cha-zhao-lcof ├── 04-LeetCode-solution.md └── 04.py ├── Interview-04.02-Minimum-Height-Tree-LCCI ├── 04-02-LeetCode-solution.md └── 0402.py ├── Interview-04.03-List-of-Depth-LCCI ├── 04-03-LeetCode-solution.md └── 0403.py ├── Interview-04.04-Check-Balance-LCCI ├── 04-04-LeetCode-solution.md └── 0404.py ├── Interview-04.05-Legal-Binary-Search-Tree-LCCI ├── 04-05-LeetCode-solution.md └── 0405.py ├── Interview-04.06-Successor-LCCI ├── 04-06-LeetCode-solution.md └── 0406.py ├── Interview-04.08-First-Common-Ancestor-LCCI ├── 04-08-LeetCode-solution.md └── 0408.py ├── Interview-04.10-check-subtree-lcci ├── 0410-LeetCode-solution.md └── 0410.py ├── Interview-04.12-Paths-with-Sum-LCCI └── 0412.py ├── Interview-05-ti-huan-kong-ge-lcof ├── 05-LeetCode-solution.md └── 05.py ├── Interview-06-cong-wei-dao-tou-da-yin-lian-biao-lcof ├── 06-LeetCode-solution.md ├── 06.go └── 06.py ├── Interview-07-zhong-jian-er-cha-shu-lcof ├── 07-LeetCode-solution.md └── 07.py ├── Interview-09-yong-liang-ge-zhan-shi-xian-dui-lie-lcof ├── 09-LeetCode-solution.md └── 09.py ├── Interview-10-fei-bo-na-qi-shu-lie-lcof ├── 10-1.py ├── 10-2.go └── 10-LeetCode-solution.md ├── Interview-10-qing-wa-tiao-tai-jie-wen-ti-lcof ├── 10-2.py └── 10-LeetCode-solution.md ├── Interview-10.01-Sorted-Merge-LCCI ├── 1001-LeetCode-solution.md └── 1001.py ├── Interview-11-xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof ├── 11-LeetCode-solution.md └── 11.py ├── Interview-13-ji-qi-ren-de-yun-dong-fan-wei-lcof └── 13.py ├── Interview-15-er-jin-zhi-zhong-1de-ge-shu-lcof └── 15.py ├── Interview-17-da-yin-cong-1dao-zui-da-de-nwei-shu-lcof ├── 17-LeetCode-solution.md └── 17.py ├── Interview-17.12-BiNode-LCCI ├── 17-12-LeetCode-solution.md └── 1712.py ├── Interview-17.16-The-Masseuse-LCCI └── 1716.py ├── Interview-26-shu-de-zi-jie-gou-lcof ├── 26-LeetCode-solution.md └── 26.py ├── Interview-27-er-cha-shu-de-jing-xiang-lcof ├── 27-LeetCode-solution.md └── 27.py ├── Interview-28-dui-cheng-de-er-cha-shu-lcof └── 28.py ├── Interview-32-cong-shang-dao-xia-da-yin-er-cha-shu-ii-lcof ├── 32-2-LeetCode-solution.md └── 32-2.py ├── Interview-32-cong-shang-dao-xia-da-yin-er-cha-shu-iii-lcof ├── 32-3-LeetCode-solution.md └── 32-3.py ├── Interview-32-cong-shang-dao-xia-da-yin-er-cha-shu-lcof ├── 32-LeetCode-solution.md └── 32.py ├── Interview-33-er-cha-sou-suo-shu-de-hou-xu-bian-li-xu-lie-lcof ├── 33-LeetCode-solution.md └── 33.py ├── Interview-34-er-cha-shu-zhong-he-wei-mou-yi-zhi-de-lu-jing-lcof ├── 34-LeetCode-solution.md └── 34.py ├── Interview-36-er-cha-sou-suo-shu-yu-shuang-xiang-lian-biao-lcof └── 36.py ├── Interview-37-xu-lie-hua-er-cha-shu-lcof ├── 37-LeetCode-solution.md └── 37.py ├── Interview-53-que-shi-de-shu-zi-lcof ├── 53-2-LeetCode-solution.md └── 53-2.py ├── Interview-53-zai-pai-xu-shu-zu-zhong-cha-zhao-shu-zi-lcof ├── 53-1-LeetCode-solution.md └── 53-1.py ├── Interview-54-er-cha-sou-suo-shu-de-di-kda-jie-dian-lcof └── 54.py ├── Interview-55-er-cha-shu-de-shen-du-lcof └── 55.py ├── Interview-55-ping-heng-er-cha-shu-lcof └── 55.py ├── Interview-57-II ├── 5702-LeetCode-solution.md └── 5702.py ├── Interview-59-II ├── 5902-LeetCode-solution.md └── 5902.py ├── Interview-62-yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof ├── 62-LeetCode-solution.md └── 62.py ├── Interview-68-er-cha-shu-de-zui-jin-gong-gong-zu-xian-lcof ├── 68-2-LeetCode-solution.md └── 68-2.py ├── Interview-68-er-cha-sou-suo-shu-de-zui-jin-gong-gong-zu-xian-lcof ├── 68-1-LeetCode-solution.md └── 68-1.py ├── LCP06-na-ying-bi └── 06.py ├── LCP07-chuan-di-xin-xi └── 07.py └── LCP08-ju-qing-hong-fa-shi-jian └── 08.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Zhou Wang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /solutions/0004-median-of-two-sorted-arrays/0004.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float: 3 | def getKthElement(k): 4 | index1, index2 = 0, 0 5 | while True: 6 | if index1 == m: 7 | return nums2[index2 + k - 1] 8 | if index2 == n: 9 | return nums1[index1 + k - 1] 10 | if k == 1: 11 | return min(nums1[index1], nums2[index2]) 12 | 13 | newIndex1 = min(index1 + k // 2 - 1, m - 1) 14 | newIndex2 = min(index2 + k // 2 - 1, n - 1) 15 | mid1, mid2 = nums1[newIndex1], nums2[newIndex2] 16 | if mid1 <= mid2: 17 | # 排除 nums1[:mid1] 18 | k -= newIndex1 - index1 + 1 19 | index1 = newIndex1 + 1 20 | else: 21 | # 排除 nums2[:mid2] 22 | k -= newIndex2 - index2 + 1 23 | index2 = newIndex2 + 1 24 | 25 | m, n = len(nums1), len(nums2) 26 | totalLength = m + n 27 | if totalLength % 2 == 1: 28 | return getKthElement((totalLength + 1) // 2) 29 | else: 30 | return (getKthElement(totalLength // 2) + getKthElement(totalLength // 2 + 1)) / 2 -------------------------------------------------------------------------------- /solutions/0011-Container-With-Most-Water/0011.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def maxArea(self, height: List[int]) -> int: 3 | i, j = 0, len(height) - 1 4 | res = 0 5 | while i < j: 6 | # 每次移动短板 7 | if height[i] < height[j]: 8 | res = max(res, height[i] * (j - i)) 9 | i += 1 10 | else: 11 | res = max(res, height[j] * (j - i)) 12 | j -= 1 13 | return res -------------------------------------------------------------------------------- /solutions/0017-Letter-Combinations-of-a-Phone-Number/0017.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def letterCombinations(self, digits: str) -> List[str]: 5 | # solution one: backtracking 6 | kbmaps = {'2': 'abc', '3': 'def', '4': 'ghi', '5': 'jkl', '6': 'mno', '7': 'pqrs', '8': 'tuv', '9': 'wxyz'} 7 | ans = [] 8 | self.dfs(digits, 0, ans, '', kbmaps) 9 | return ans 10 | 11 | def dfs(self, string, index, ans, path, kbmaps): 12 | if index == len(string): 13 | if path != '': # while digits = '', return [] not [''] 14 | ans.append(path) 15 | return 16 | for i in kbmaps[string[index]]: 17 | self.dfs(string, index + 1, ans, path + i, kbmaps) 18 | 19 | # solution two: brute force search 20 | if digits == "": 21 | return [] 22 | d = {'2' : "abc", '3' : "def", '4' : "ghi", '5' : "jkl", '6' : "mno", '7' : "pqrs", '8' : "tuv", '9' : "wxyz"} 23 | ans = [''] 24 | for x in digits: 25 | ans = [y + c for c in d[x] for y in ans] 26 | return ans 27 | 28 | if __name__ == "__main__": 29 | digits = "23" 30 | print(Solution().letterCombinations(digits)) -------------------------------------------------------------------------------- /solutions/0020-Valid-Parentheses/0020.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def isValid(self, s: str) -> bool: 3 | dic = {'}': '{', ']': '[', ')': '('} 4 | stack = [] 5 | for c in s: 6 | if stack and c in dic: 7 | if stack[-1] == dic[c]: 8 | stack.pop() 9 | else: 10 | return False 11 | else: 12 | stack.append(c) 13 | return not stack -------------------------------------------------------------------------------- /solutions/0026-remove-duplicates-from-sorted-array/0026.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def removeDuplicates(self, nums: List[int]) -> int: 3 | if not nums: 4 | return 0 5 | 6 | n = len(nums) 7 | fast, slow = 1, 1 8 | while fast < n: 9 | if nums[fast] != nums[fast - 1]: 10 | nums[slow] = nums[fast] 11 | slow += 1 12 | fast += 1 13 | 14 | return slow 15 | 16 | # index = 0 17 | # for i in range(1, len(nums)): 18 | # if nums[i] != nums[index]: 19 | # index += 1 20 | # nums[index] = nums[i] 21 | # return index + 1 -------------------------------------------------------------------------------- /solutions/0033-search-in-rotated-sorted-array/0033.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def search(self, nums: List[int], target: int) -> int: 3 | left, right = 0, len(nums) - 1 4 | # 左闭右闭 5 | while left <= right: 6 | mid = (left + right) >> 1 7 | if nums[mid] == target: 8 | return mid 9 | if nums[0] <= nums[mid]: 10 | # 左半边有序 11 | if nums[0] <= target < nums[mid]: 12 | right = mid - 1 13 | elif nums[mid] == target: 14 | return mid 15 | else: 16 | left = mid + 1 17 | else: 18 | # 右半边有序 19 | if nums[mid] < target <= nums[-1]: 20 | left = mid + 1 21 | elif nums[mid] == target: 22 | return mid 23 | else: 24 | right = mid - 1 25 | return -1 -------------------------------------------------------------------------------- /solutions/0039-Combination-Sum/0039.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]: 5 | n = len(candidates) 6 | if n == 0: 7 | return [] 8 | 9 | # accelerate 剪枝提速,非必需 10 | candidates.sort() 11 | 12 | path, res = [], [] 13 | self.dfs(candidates, 0, n, path, res, target) 14 | return res 15 | 16 | def dfs(self, candidates, start, n, path, res, target): 17 | # 1.valid result 递归终止情况 18 | if target == 0: 19 | res.append(path[:]) 20 | return 21 | 22 | for i in range(start, n): 23 | tmp = target - candidates[i] 24 | # 3.pruning 剪枝 25 | if tmp < 0: 26 | break 27 | # 2.backtrack and update 回溯以及更新 path 28 | path.append(candidates[i]) 29 | self.dfs(candidates, i, n, path, res, tmp) 30 | path.pop() 31 | 32 | if __name__ == '__main__': 33 | candidates = [2, 3, 6, 7] 34 | target = 7 35 | print(Solution().combinationSum(candidates, target)) -------------------------------------------------------------------------------- /solutions/0040-Combination-Sum-II/0040.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]: 5 | n = len(candidates) 6 | if n == 0: 7 | return [] 8 | 9 | # accelerate 剪枝提速,非必需 10 | candidates.sort() 11 | 12 | path, res = [], [] 13 | self.dfs(candidates, 0, n, path, res, target) 14 | return res 15 | 16 | def dfs(self, candidates, start, n, path, res, target): 17 | # 1.valid result 递归终止情况 18 | if target == 0: 19 | res.append(path[:]) 20 | return 21 | 22 | for i in range(start, n): 23 | tmp = target - candidates[i] 24 | # 3.pruning 剪枝 25 | if tmp < 0: 26 | break 27 | # 防止出现这种情况:一个数字使用多次 28 | if i > start and candidates[i] == candidates[i - 1]: 29 | continue 30 | # 2.backtrack and update 回溯以及更新 path 31 | path.append(candidates[i]) 32 | self.dfs(candidates, i + 1, n, path, res, tmp) 33 | path.pop() 34 | 35 | if __name__ == '__main__': 36 | candidates = [10,1,2,7,6,1,5] 37 | target = 8 38 | # candidates = [2,5,2,1,2] 39 | # target = 5 40 | print(Solution().combinationSum2(candidates, target)) -------------------------------------------------------------------------------- /solutions/0053-Maximum-Subarray/0053.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def maxSubArray(self, nums): 3 | """ 4 | :type nums: List[int] 5 | :rtype: int 6 | """ 7 | if not nums: 8 | return 0 9 | dp = 0 10 | sum = -0xFFFFFFFF 11 | for i in range(len(nums)): 12 | dp = nums[i] + (dp if dp > 0 else 0) # if dp > 0: dp = nums[i] + dp, else: dp = nums[i] 13 | sum = max(sum, dp) 14 | return sum 15 | 16 | if __name__ == "__main__": 17 | nums = [-2,1,-3,4,-1,2,1,-5,4] 18 | print(Solution().maxSubArray(nums)) -------------------------------------------------------------------------------- /solutions/0069-Sqrt-x/0069.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def mySqrt(self, x): 3 | """ 4 | :type x: int 5 | :rtype: int 6 | """ 7 | # solution one: binary search 8 | low, high, mid = 0, x, x / 2 9 | while low <= high: 10 | if mid ** 2 > x: 11 | high = mid - 1 12 | else: 13 | low = mid + 1 14 | mid = (low + high) / 2 15 | return int(mid) 16 | 17 | # # solution two: Newton's method 18 | # res = x 19 | # while res * res > x: 20 | # res = (res + x / res) / 2 21 | # return int(res) 22 | 23 | # # solution three: math 24 | # import math 25 | # return int(math.sqrt(x)) 26 | 27 | if __name__ == "__main__": 28 | x = 8 29 | print(Solution().mySqrt(x)) -------------------------------------------------------------------------------- /solutions/0070-Climbing-Stairs/0070.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def climbStairs(self, n: int) -> int: 3 | # 初始条件和斐波那契数列有区别 4 | dp_0, dp_1 = 1, 1 5 | for _ in range(n): 6 | dp_0, dp_1 = dp_1, dp_0 + dp_1 7 | return dp_0 -------------------------------------------------------------------------------- /solutions/0074-search-a-2d-matrix/0074.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def searchMatrix(self, matrix: List[List[int]], target: int) -> bool: 3 | m, n = len(matrix) - 1, len(matrix[0]) - 1 4 | left0, right0 = 0, m 5 | while left0 < right0: 6 | mid0 = (left0 + right0 + 1) >> 1 7 | if matrix[mid0][0] == target: 8 | return True 9 | # 将区间划分成[left, mid - 1]和[mid, right] 10 | elif matrix[mid0][0] < target: 11 | left0 = mid0 12 | else: 13 | right0 = mid0 - 1 14 | left1, right1 = 0, n 15 | while left1 <= right1: 16 | mid1 = (left1 + right1) >> 1 17 | if matrix[left0][mid1] == target: 18 | return True 19 | elif matrix[left0][mid1] < target: 20 | left1 = mid1 + 1 21 | else: 22 | right1 = mid1 - 1 23 | return False -------------------------------------------------------------------------------- /solutions/0077-Combinations/0077.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def combine(self, n: int, k: int) -> List[List[int]]: 5 | # # solution one:回溯 6 | # # special judgment 7 | # if n <= 0 or k <= 0 or k > n: 8 | # return [] 9 | 10 | # res = [] 11 | # self.dfs(1, k, n, [], res) 12 | # return res 13 | 14 | # def dfs(self, start, k, n, path, res): 15 | # # 1.valid result 16 | # if len(path) == k: 17 | # res.append(path[:]) 18 | # return 19 | 20 | # # 3.pruning 21 | # for i in range(start, n - (k - len(path)) + 2): 22 | # # 2.backtrack and update 23 | # path.append(i) 24 | # self.dfs(i + 1, k, n, path, res) 25 | # path.pop() 26 | 27 | # solution two:回溯 28 | res = [] 29 | # 特判 30 | if k <= 0 or n <= 0: 31 | return [] 32 | 33 | def backtrack(start, path): 34 | if len(path) == k: 35 | # 注意这里是 path[:] 36 | res.append(path[:]) 37 | return 38 | for i in range(start, n + 1): 39 | path.append(i) 40 | backtrack(i + 1, path) 41 | path.pop() 42 | 43 | backtrack(1, []) 44 | return res 45 | 46 | if __name__ == "__main__": 47 | n = 4 48 | k = 2 49 | print(Solution().combine(n, k)) -------------------------------------------------------------------------------- /solutions/0078-Subsets/0078.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def subsets(self, nums: List[int]) -> List[List[int]]: 5 | res = [] 6 | n = len(nums) 7 | 8 | def backtrack(nums, start, path): 9 | # 加入 path 10 | res.append(path) 11 | # i 从 start 开始递增 12 | for i in range(start, n): 13 | # 回溯及更新 path 14 | # path.append([nums[i]]) 15 | backtrack(nums, i + 1, path + [nums[i]]) 16 | # path.pop() 17 | 18 | backtrack(nums, 0, []) 19 | return res 20 | 21 | if __name__ == "__main__": 22 | nums = [1,2,3] 23 | print(Solution().subsets(nums)) -------------------------------------------------------------------------------- /solutions/0079-Word-Search/0079.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def exist(self, board: List[List[str]], word: str) -> bool: 5 | if not board: 6 | return False 7 | 8 | for i in range(len(board)): 9 | for j in range(len(board[0])): 10 | if self.dfs(board, i, j, word): 11 | return True 12 | return False 13 | 14 | def dfs(self, board, i, j, word): 15 | if len(word) == 0: 16 | return True 17 | if i < 0 or i >= len(board) or j < 0 or j >= len(board[0]) or word[0] != board[i][j]: 18 | return False 19 | tmp, board[i][j] = board[i][j], '#' # '#': visited 20 | ans = self.dfs(board, i - 1, j, word[1:]) or self.dfs(board, i + 1, j, word[1:]) or self.dfs(board, i, j - 1, word[1:]) or self.dfs(board, i, j + 1, word[1:]) 21 | board[i][j] = tmp # recover board[i][j] 22 | return ans 23 | 24 | if __name__ == "__main__": 25 | board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]] 26 | word = "ABCCED" 27 | print(Solution().exist(board, word)) -------------------------------------------------------------------------------- /solutions/0080-remove-duplicates-from-sorted-array-ii/0080.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wonz5130/LeetCode-Solutions/a67809dac5939936b3c85829ac9991936e672229/solutions/0080-remove-duplicates-from-sorted-array-ii/0080.py -------------------------------------------------------------------------------- /solutions/0081-search-in-rotated-sorted-array-ii/0081.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def search(self, nums: List[int], target: int) -> bool: 3 | left, right = 0, len(nums) - 1 4 | while left <= right: 5 | mid = (left + right) >> 1 6 | if nums[mid] == target: 7 | return True 8 | elif nums[left] == nums[mid] and nums[mid] == nums[right]: 9 | left += 1 10 | right -= 1 11 | elif nums[left] <= nums[mid]: 12 | if nums[left] <= target < nums[mid]: 13 | right = mid - 1 14 | else: 15 | left = mid + 1 16 | else: 17 | if nums[mid] < target <= nums[right]: 18 | left = mid + 1 19 | else: 20 | right = mid - 1 21 | return False -------------------------------------------------------------------------------- /solutions/0088-Merge-Sorted-Array/0088.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def merge(self, nums1, m, nums2, n): 3 | """ 4 | :type nums1: List[int] 5 | :type m: int 6 | :type nums2: List[int] 7 | :type n: int 8 | :rtype: None Do not return anything, modify nums1 in-place instead. 9 | """ 10 | # solution 1: 双指针 11 | nums = [] 12 | p1, p2 = 0, 0 13 | while p1 < m or p2 < n: 14 | if p1 == m: 15 | nums.append(nums2[p2]) 16 | p2 += 1 17 | elif p2 == n: 18 | nums.append(nums1[p1]) 19 | p1 += 1 20 | elif nums1[p1] <= nums2[p2]: 21 | nums.append(nums1[p1]) 22 | p1 += 1 23 | elif nums1[p1] > nums2[p2]: 24 | nums.append(nums2[p2]) 25 | p2 += 1 26 | nums1[:] = nums 27 | 28 | # solution 2: 逆向双指针 29 | # while m > 0 and n > 0: 30 | # if nums1[m - 1] > nums2[n - 1]: 31 | # nums1[m + n - 1] = nums1[m - 1] 32 | # m -= 1 33 | # else: 34 | # nums1[m + n - 1] = nums2[n - 1] 35 | # n -= 1 36 | # if n > 0: # 如果 nums2 有剩余, 全部加到 nums1 中 37 | # nums1[:n] = nums2[:n] 38 | 39 | if __name__ == "__main__": 40 | nums1 = [1,2,3,0,0,0] 41 | nums2 = [2,5,6] 42 | m, n = 3, 3 43 | Solution().merge(nums1, m, nums2, n) 44 | print(nums1) -------------------------------------------------------------------------------- /solutions/0090-Subsets-II/0090.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def subsetsWithDup(self, nums: List[int]) -> List[List[int]]: 6 | res = [] 7 | n = len(nums) 8 | # 先对 nums 进行排序 9 | nums.sort() 10 | 11 | def backtrack(nums, start, path): 12 | # 加入 res 13 | res.append(path) 14 | # i 从 start 开始递增 15 | for i in range(start, n): 16 | # 剪枝:当前元素和前一个元素相同 17 | if i > start and nums[i - 1] == nums[i]: 18 | continue 19 | # 回溯及更新 path 20 | # path.append([nums[i]]) 21 | backtrack(nums, i + 1, path + [nums[i]]) 22 | # path.pop() 23 | 24 | backtrack(nums, 0, []) 25 | return res 26 | 27 | if __name__ == "__main__": 28 | nums = [1,2,2] 29 | print(Solution().subsetsWithDup(nums)) -------------------------------------------------------------------------------- /solutions/0095-Unique-Binary-Search-Trees-II/0095.py: -------------------------------------------------------------------------------- 1 | # from typing import List 2 | 3 | # # Definition for a binary tree node. 4 | # class TreeNode: 5 | # def __init__(self, x): 6 | # self.val = x 7 | # self.left = None 8 | # self.right = None 9 | 10 | class Solution: 11 | def generateTrees(self, n: int) -> List[TreeNode]: 12 | if n == 0: 13 | return [] 14 | else: 15 | return self.generateTreesDFS(1, n) 16 | 17 | # DFS 18 | def generateTreesDFS(self, left, right): 19 | if left > right: 20 | return [None] 21 | ans = [] 22 | for i in range(left, right + 1): 23 | left_nodes = self.generateTreesDFS(left, i - 1) # all possible left subtrees if i is choosen to be a root 24 | right_nodes = self.generateTreesDFS(i + 1, right) # all possible right subtrees if i is choosen to be a root 25 | for left_node in left_nodes: 26 | for right_node in right_nodes: 27 | root = TreeNode(i) 28 | root.left = left_node 29 | root.right = right_node 30 | ans.append(root) 31 | return ans -------------------------------------------------------------------------------- /solutions/0098-Validate-Binary-Search-Tree/0098.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def isValidBST(self, root: TreeNode) -> bool: 10 | return self.isValid(root, None, None) 11 | 12 | def isValid(self, root: TreeNode, min_: TreeNode, max_: TreeNode): 13 | if not root: 14 | return True 15 | if min_ != None and root.val <= min_.val: 16 | return False 17 | if max_ != None and root.val >= max_.val: 18 | return False 19 | return self.isValid(root.left, min_, root) and self.isValid(root.right, root, max_) -------------------------------------------------------------------------------- /solutions/0100-Same-Tree/0100.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def isSameTree(self, p: TreeNode, q: TreeNode) -> bool: 10 | # 两棵树都为空 11 | if not p and not q: 12 | return True 13 | # 一棵树为空,另一棵不为空 14 | elif not p or not q: 15 | return False 16 | # 两棵树都非空,但节点值不同 17 | elif p.val != q.val: 18 | return False 19 | # 分别判断左子树和右子树 20 | return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right) -------------------------------------------------------------------------------- /solutions/0101-Symmetric-Tree/0101.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def isSymmetric(self, root: TreeNode) -> bool: 10 | def recur(L, R): 11 | # 左右子树都为空 12 | if not L and not R: 13 | return True 14 | # 有一个不为空 15 | if not L or not R or L.val != R.val: 16 | return False 17 | # L的左子树和R的右子树,L的右子树和R的左子树 18 | return recur(L.left, R.right) and recur(L.right, R.left) 19 | 20 | # 特判:root为空 21 | if not root: 22 | return True 23 | return recur(root.left, root.right) -------------------------------------------------------------------------------- /solutions/0102-Binary-Tree-Level-Order-Traversal/0102.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def levelOrder(self, root: TreeNode) -> List[List[int]]: 10 | # solution one: 非递归 11 | import collections 12 | if not root: 13 | return [] 14 | 15 | res, q = [], collections.deque() 16 | q.append(root) 17 | while q: 18 | # 输出是二维数组 19 | temp = [] 20 | for x in range(len(q)): 21 | node = q.popleft() 22 | temp.append(node.val) 23 | if node.left: 24 | q.append(node.left) 25 | if node.right: 26 | q.append(node.right) 27 | res.append(temp) 28 | return res 29 | 30 | # solution two: 递归 31 | res = [] 32 | 33 | def helper(root, depth): 34 | if not root: 35 | return 36 | if len(res) == depth: 37 | res.append([]) 38 | res[depth].append(root.val) 39 | helper(root.left, depth + 1) 40 | helper(root.right, depth + 1) 41 | helper(root , 0) 42 | return res -------------------------------------------------------------------------------- /solutions/0103-Binary-Tree-Zigzag-Level-Order-Traversal/0103.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def zigzagLevelOrder(self, root: TreeNode) -> List[List[int]]: 10 | import collections 11 | if not root: 12 | return [] 13 | 14 | res, q = [], collections.deque() 15 | flag = False # 做奇偶判断 16 | q.append(root) 17 | 18 | while q: 19 | temp = [] 20 | flag = not flag 21 | for _ in range(len(q)): 22 | node = q.popleft() 23 | # 头插 24 | if flag: 25 | temp.append(node.val) 26 | # 尾插 27 | else: 28 | temp.insert(0, node.val) 29 | if node.left: 30 | q.append(node.left) 31 | if node.right: 32 | q.append(node.right) 33 | res.append(temp) 34 | 35 | return res -------------------------------------------------------------------------------- /solutions/0104-Maximum-Depth-of-Binary-Tree/0104.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def maxDepth(self, root: TreeNode) -> int: 10 | # solution one: DFS 11 | if not root: 12 | return 0 13 | return max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1 14 | 15 | # solution two: BFS 16 | if not root: 17 | return 0 18 | q, res = [root], 0 19 | # 当q为空时跳出 20 | while q: 21 | tmp = [] 22 | for node in q: 23 | if node.left: 24 | tmp.append(node.left) 25 | if node.right: 26 | tmp.append(node.right) 27 | q = tmp 28 | res += 1 29 | return res -------------------------------------------------------------------------------- /solutions/0105-Construct-Binary-Tree-from-Preorder-and-Inorder-Traversal/0105.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode: 10 | if not preorder: 11 | return None 12 | root = TreeNode(preorder[0]) 13 | 14 | # 根在中序遍历中的索引 15 | i = inorder.index(root.val) 16 | # left: preorder[1] ~ preorder[i], inorder[0] ~ inorder[i-1] 17 | root.left = self.buildTree(preorder[1:i+1], inorder[:i]) 18 | # right: preorder[i+1] ~ preorder[-1], inorder[i+1] ~ inorder[-1] 19 | root.right = self.buildTree(preorder[i+1:], inorder[i+1:]) 20 | 21 | return root -------------------------------------------------------------------------------- /solutions/0106-Construct-Binary-Tree-from-Inorder-and-Postorder-Traversal/0106.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode: 10 | if not postorder: 11 | return None 12 | root = TreeNode(postorder[-1]) 13 | 14 | # 根在中序遍历中的索引 15 | i = inorder.index(root.val) 16 | # left: inorder[0] ~ inorder[i-1], postorder[0] ~ postorder[i-1] 17 | root.left = self.buildTree(inorder[:i], postorder[:i]) 18 | # right: inorder[i+1] ~ inorder[-1], postorder[i] ~ postorder[-2] 19 | root.right = self.buildTree(inorder[i+1:], postorder[i:-1]) 20 | 21 | return root -------------------------------------------------------------------------------- /solutions/0110-Balanced-Binary-Tree/0110.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def isBalanced(self, root: TreeNode) -> bool: 10 | # solution one: 后序+剪枝 11 | def recur(root): 12 | if not root: 13 | return 0 14 | left = recur(root.left) 15 | if left == -1: 16 | return -1 17 | right = recur(root.right) 18 | if right == -1: 19 | return -1 20 | # 左右子树深度差 <= 1,符合平衡二叉树 21 | return max(left, right) + 1 if abs(left - right) <= 1 else -1 22 | 23 | # 若 recur(root) != -1,说明平衡 24 | return recur(root) != -1 25 | 26 | # solution two: 前序+判断深度 27 | # 特判:root 为空 28 | if not root: 29 | return True 30 | # 当前子树是否平衡 31 | # 当前子树的左子树是否平衡 32 | # 当前子树的右子树是否平衡 33 | return abs(self.depth(root.left) - self.depth(root.right)) <= 1 and \ 34 | self.isBalanced(root.left) and self.isBalanced(root.right) 35 | 36 | # 计算深度 37 | def depth(self, root): 38 | if not root: 39 | return 0 40 | return max(self.depth(root.left), self.depth(root.right)) + 1 41 | -------------------------------------------------------------------------------- /solutions/0111-Minimum-Depth-of-Binary-Tree/0111.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def minDepth(self, root: TreeNode) -> int: 10 | # solution one: DFS 11 | # 根为空 12 | if not root: 13 | return 0 14 | 15 | # 左右子树都为空 16 | if not root.left and not root.right: 17 | return 1 18 | 19 | min_depth = 10**9 20 | if root.left: 21 | min_depth = min(self.minDepth(root.left), min_depth) 22 | if root.right: 23 | min_depth = min(self.minDepth(root.right), min_depth) 24 | 25 | return min_depth + 1 26 | 27 | # solution two: BFS 28 | import collections 29 | # 根为空 30 | if not root: 31 | return 0 32 | 33 | que = collections.deque([(root, 1)]) 34 | while que: 35 | node, depth = que.popleft() 36 | # 到达叶子节点 37 | if not node.left and not node.right: 38 | return depth 39 | if node.left: 40 | que.append((node.left, depth + 1)) 41 | if node.right: 42 | que.append((node.right, depth + 1)) 43 | 44 | return 0 -------------------------------------------------------------------------------- /solutions/0113-Path-Sum-II/0113.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]: 10 | res, path = [], [] 11 | 12 | # 先序遍历:根左右 13 | def recur(root, target): 14 | if not root: 15 | return 16 | 17 | path.append(root.val) 18 | target -= root.val 19 | # 找到路径 20 | if target == 0 and not root.left and not root.right: 21 | res.append(list(path)) # 复制了一个 path 加入到 res 中,这样修改 path 不影响 res 22 | recur(root.left, target) 23 | recur(root.right, target) 24 | # 向上回溯,需要删除当前节点 25 | path.pop() 26 | 27 | recur(root, sum) 28 | return res -------------------------------------------------------------------------------- /solutions/0114-Flatten-Binary-Tree-to-Linked-List/0114.go: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * type TreeNode struct { 4 | * Val int 5 | * Left *TreeNode 6 | * Right *TreeNode 7 | * } 8 | */ 9 | func flatten(root *TreeNode) { 10 | if root == nil { 11 | return 12 | } 13 | // 递归调用 14 | flatten(root.Left) 15 | flatten(root.Right) 16 | 17 | // 后序遍历:左-右-根 18 | // 左右子树拉平成链表 19 | var left = new(TreeNode) 20 | left = root.Left 21 | var right = new(TreeNode) 22 | right = root.Right 23 | 24 | // 左子树作为右子树 25 | root.Left = nil 26 | root.Right = left 27 | 28 | // 原先右子树接到当前右子树末端 29 | var p = new(TreeNode) 30 | p = root 31 | // 找到当前右子树末端 32 | for { 33 | if p.Right == nil { 34 | break 35 | } 36 | p = p.Right 37 | } 38 | p.Right = right 39 | } -------------------------------------------------------------------------------- /solutions/0114-Flatten-Binary-Tree-to-Linked-List/0114.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | class Solution: 8 | def flatten(self, root: TreeNode) -> None: 9 | """ 10 | Do not return anything, modify root in-place instead. 11 | """ 12 | if not root: 13 | return 14 | 15 | # 递归调用 16 | self.flatten(root.left) 17 | self.flatten(root.right) 18 | 19 | # 后序遍历:左-右-根 20 | # 左右子树拉平成链表 21 | left = TreeNode() 22 | left = root.left 23 | right = TreeNode() 24 | right = root.right 25 | 26 | # 左子树作为右子树 27 | root.left = None 28 | root.right = left 29 | 30 | # 原先右子树接到当前右子树末端 31 | p = TreeNode() 32 | p = root 33 | # 找到当前右子树末端 34 | while p.right != None: 35 | p = p.right 36 | p.right = right -------------------------------------------------------------------------------- /solutions/0116-Populating-Next-Right-Pointers-in-Each-Node/0116.go: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a Node. 3 | * type Node struct { 4 | * Val int 5 | * Left *Node 6 | * Right *Node 7 | * Next *Node 8 | * } 9 | */ 10 | 11 | 12 | // 将每两个相邻节点连接起来 13 | func connectTwoNode(node1 *Node, node2 *Node) { 14 | if node1 == nil && node2 == nil { 15 | return 16 | } 17 | node1.Next = node2 18 | 19 | // 链接相同父节点的两个子节点 20 | connectTwoNode(node1.Left, node1.Right) 21 | connectTwoNode(node2.Left, node2.Right) 22 | // 链接不同父节点的两个子节点 23 | connectTwoNode(node1.Right, node2.Left) 24 | } 25 | 26 | func connect(root *Node) *Node { 27 | if root == nil { 28 | return nil 29 | } 30 | 31 | connectTwoNode(root.Left, root.Right) 32 | return root 33 | } -------------------------------------------------------------------------------- /solutions/0116-Populating-Next-Right-Pointers-in-Each-Node/0116.py: -------------------------------------------------------------------------------- 1 | """ 2 | # Definition for a Node. 3 | class Node: 4 | def __init__(self, val: int = 0, left: 'Node' = None, right: 'Node' = None, next: 'Node' = None): 5 | self.val = val 6 | self.left = left 7 | self.right = right 8 | self.next = next 9 | """ 10 | 11 | class Solution: 12 | def connect(self, root: 'Node') -> 'Node': 13 | if not root: 14 | return None 15 | 16 | # 将每两个相邻节点连接起来 17 | def connectTwoNode(node1: 'Node', node2: 'Node'): 18 | if not node1 or not node2: 19 | return 20 | 21 | node1.next = node2 22 | 23 | # 链接相同父节点的两个子节点 24 | connectTwoNode(node1.left, node1.right) 25 | connectTwoNode(node2.left, node2.right) 26 | # 链接不同父节点的两个子节点 27 | connectTwoNode(node1.right, node2.left) 28 | 29 | connectTwoNode(root.left, root.right) 30 | return root -------------------------------------------------------------------------------- /solutions/0118-Pascal's-Triangle/0118.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def generate(self, numRows: int) -> List[List[int]]: 3 | res = [] 4 | for i in range(numRows): 5 | row = [] 6 | for j in range(0, i + 1): 7 | # 首尾都是 1 8 | if j == 0 or j == i: 9 | row.append(1) 10 | else: 11 | row.append(res[i - 1][j] + res[i - 1][j - 1]) 12 | res.append(row) 13 | return res -------------------------------------------------------------------------------- /solutions/0121-Best-Time-to-Buy-and-Sell-Stock/0121.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def maxProfit(self, prices: List[int]) -> int: 5 | # solution one: 贪心 6 | profit, buy = 0, 0x7FFFFFFF 7 | for price in prices: 8 | if buy > price: 9 | buy = price # 尽量买入价格小的股票 10 | if profit < price - buy: 11 | profit = price - buy # 尽量在最大价格卖出股票 12 | return profit 13 | 14 | # solution two: 动态规划 15 | # K = 1 16 | dp_i_0 = 0 17 | dp_i_1 = float('-inf') # 负无穷 18 | for i in range(len(prices)): 19 | # 昨天没有股票,昨天有股票今天卖出 20 | dp_i_0 = max(dp_i_0, dp_i_1 + prices[i]) # dp_i_0 和 dp_i_1 可以看成是变量,存储的都是上一次即昨天的值 21 | # 昨天有股票,昨天没有股票今天买入 22 | dp_i_1 = max(dp_i_1, -prices[i]) 23 | return dp_i_0 24 | 25 | if __name__ == "__main__": 26 | prices = [7,1,5,3,6,4] 27 | print(Solution().maxProfit(prices)) -------------------------------------------------------------------------------- /solutions/0122-Best-Time-to-Buy-and-Sell-Stock-II/0122.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def maxProfit(self, prices: List[int]) -> int: 5 | # solution one: 贪心 6 | if not prices or len(prices) == 0: 7 | return 0 8 | profit = 0 9 | for i in range(len(prices)-1): 10 | if(prices[i+1] > prices[i]): 11 | profit += prices[i+1] - prices[i] 12 | return profit 13 | 14 | # solution two: 动态规划 15 | dp_i_0 = 0 16 | dp_i_1 = float('-inf') # 负无穷 17 | for i in range(len(prices)): 18 | temp = dp_i_0 19 | # 昨天没有股票,昨天有股票今天卖出 20 | dp_i_0 = max(dp_i_0, dp_i_1 + prices[i]) # dp_i_0 和 dp_i_1 可以看成是变量,存储的都是上一次即昨天的值 21 | # 昨天有股票,昨天没有股票今天买入 22 | dp_i_1 = max(dp_i_1, temp - prices[i]) 23 | return dp_i_0 24 | 25 | if __name__ == "__main__": 26 | prices = [7,1,5,3,6,4] 27 | print(Solution().maxProfit(prices)) -------------------------------------------------------------------------------- /solutions/0123-Best-Time-to-Buy-and-Sell-Stock-III/0123.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def maxProfit(self, prices: List[int]) -> int: 5 | dp_i_2_0, dp_i_1_0 = 0, 0 6 | # dp_i_2_1, dp_i_1_1 = -prices[0], -prices[0] # 会报错:list index out of range 7 | dp_i_2_1, dp_i_1_1 = float('-inf'), float('-inf') # 负无穷 8 | for i in range(len(prices)): 9 | # 昨天没有股票,昨天有股票今天卖出 10 | dp_i_2_0 = max(dp_i_2_0, dp_i_2_1 + prices[i]) 11 | # 昨天有股票,昨天没有股票今天买入 12 | dp_i_2_1 = max(dp_i_2_1, dp_i_1_0 - prices[i]) 13 | # 昨天没有股票,昨天有股票今天卖出 14 | dp_i_1_0 = max(dp_i_1_0, dp_i_1_1 + prices[i]) 15 | # 昨天有股票,昨天没有股票今天买入 16 | dp_i_1_1 = max(dp_i_1_1, -prices[i]) 17 | 18 | return dp_i_2_0 19 | 20 | if __name__ == "__main__": 21 | prices = [3,3,5,0,0,3,1,4] 22 | print(Solution().maxProfit(prices)) -------------------------------------------------------------------------------- /solutions/0129-Sum-Root-to-Leaf-Numbers/0129.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def sumNumbers(self, root: TreeNode) -> int: 10 | def dfs(root: TreeNode, sumNumber: int) -> int: 11 | if not root: 12 | return 0 13 | tmpsum = sumNumber * 10 + root.val 14 | # 叶子节点 15 | if not root.left and not root.right: 16 | return tmpsum 17 | else: 18 | return dfs(root.left, tmpsum) + dfs(root.right, tmpsum) 19 | 20 | return dfs(root, 0) -------------------------------------------------------------------------------- /solutions/0130-Surrounded-Regions/0130.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def solve(self, board: List[List[str]]) -> None: 5 | """ 6 | Do not return anything, modify board in-place instead. 7 | """ 8 | if not board: 9 | return None 10 | 11 | m, n = len(board), len(board[0]) 12 | directions = [(-1, 0), (0, 1), (1, 0), (0, -1)] 13 | 14 | def dfs(i, j): 15 | if 0 <= i < m and 0 <= j < n and board[i][j] == "O": # change "O" to "*" 16 | board[i][j] = "*" 17 | for k in range(4): 18 | dfs(i + directions[k][0], j + directions[k][1]) 19 | 20 | # search left and right 21 | for i in range(m): 22 | dfs(i, 0) 23 | dfs(i, n - 1) 24 | 25 | # search up and down 26 | for i in range(n): 27 | dfs(0, i) 28 | dfs(m - 1, i) 29 | 30 | for i in range(m): 31 | for j in range(n): 32 | if board[i][j] == "O": # change "O" to "X" 33 | board[i][j] = "X" 34 | elif board[i][j] == "*": # change "*" to "O" 35 | board[i][j] = "O" 36 | 37 | if __name__ == "__main__": 38 | board = [["X","X","X","X"],["X","O","O","X"],["X","X","O","X"],["X","O","X","X"]] 39 | Solution().solve(board) 40 | print(board) -------------------------------------------------------------------------------- /solutions/0141-Linked-List-Cycle/0141.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode(object): 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.next = None 6 | 7 | class Solution(object): 8 | def hasCycle(self, head): 9 | """ 10 | :type head: ListNode 11 | :rtype: bool 12 | """ 13 | if head == None: 14 | return False 15 | slow, fast = head, head # 快慢双指针 16 | while fast.next != None and fast.next.next != None: # 一定是 fast.next 和 fast.next.next 17 | slow = slow.next 18 | fast = fast.next.next # fast快指针速度是slow慢指针的两倍 19 | if slow == fast: # 如果链表有环, fast 和 slow 必会相遇 20 | return True 21 | return False -------------------------------------------------------------------------------- /solutions/0144-Binary-Tree-Preorder-Traversal/0144.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | class Solution: 8 | def preorderTraversal(self, root: TreeNode) -> List[int]: 9 | # 递归 10 | res = [] 11 | def dfs(root): 12 | if not root: 13 | return [] 14 | res.append(root.val) 15 | dfs(root.left) 16 | dfs(root.right) 17 | 18 | dfs(root) 19 | return res 20 | 21 | # 迭代 22 | res = [] 23 | if not root: 24 | return res 25 | stack = [] 26 | node = root 27 | while stack or node: 28 | while node: 29 | res.append(node.val) 30 | stack.append(node) 31 | # 前序遍历 32 | node = node.left 33 | node = stack.pop() 34 | node = node.right 35 | return res -------------------------------------------------------------------------------- /solutions/0145-Binary-Tree-Postorder-Traversal/0145.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | class Solution: 8 | def postorderTraversal(self, root: TreeNode) -> List[int]: 9 | # 递归 10 | res = [] 11 | def dfs(root): 12 | if not root: 13 | return [] 14 | dfs(root.left) 15 | dfs(root.right) 16 | res.append(root.val) 17 | 18 | dfs(root) 19 | return res 20 | 21 | # 迭代 22 | res = [] 23 | if not root: 24 | return res 25 | stack = [] 26 | node = root 27 | while stack or node: 28 | while node: 29 | # 根节点入栈 30 | stack.append(node) 31 | # 左子树存在 32 | if node.left: 33 | node = node.left 34 | # 左子树不存在,转右子树 35 | else: 36 | node = node.right 37 | # 取出栈顶元素 38 | node = stack.pop() 39 | res.append(node.val) 40 | # 栈不为空且当前节点是栈顶元素的左节点 41 | # stack[-1]就是取出的栈顶元素:node 42 | if stack and node == stack[-1].left: 43 | node = stack[-1].right 44 | # 没有左子树或右子树,退栈 45 | else: 46 | node = None 47 | return res -------------------------------------------------------------------------------- /solutions/0153-Find-Minimum-in-Rotated-Sorted-Array/0153.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def findMin(self, nums): 3 | """ 4 | :type nums: List[int] 5 | :rtype: int 6 | """ 7 | low, high = 0, len(nums) - 1 8 | while low < high: # < not <=, or <= will TLE 9 | mid = int((low + high) / 2) 10 | if nums[mid] <= nums[high]: # <= 11 | high = mid # h = m not m - 1 12 | else: 13 | low = mid + 1 14 | return nums[low] 15 | 16 | if __name__ == "__main__": 17 | nums = [4,5,6,7,0,1,2] 18 | print(Solution().findMin(nums)) -------------------------------------------------------------------------------- /solutions/0162-find-peak-element/0162.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findPeakElement(self, nums: List[int]) -> int: 3 | n = len(nums) 4 | 5 | def get(i: int) -> int: 6 | if i == -1 or i == n: 7 | return float('-inf') 8 | return nums[i] 9 | 10 | left, right = 0, n - 1 11 | while left <= right: 12 | mid = (left + right) >> 1 13 | if get(mid - 1) < get(mid) > get(mid + 1): 14 | return mid 15 | elif get(mid) < get(mid + 1): 16 | left = mid + 1 17 | elif get(mid) > get(mid + 1): 18 | right = mid - 1 -------------------------------------------------------------------------------- /solutions/0167-Two-Sum-II-Input-array-is-sorted/0167.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def twoSum(self, numbers, target): 3 | """ 4 | :type numbers: List[int] 5 | :type target: int 6 | :rtype: List[int] 7 | """ 8 | left = 0 # 从头指向尾 9 | right = len(numbers) - 1 # 从尾指向头 10 | while left < right: 11 | if numbers[left] + numbers[right] == target: 12 | return [left + 1, right + 1] 13 | elif numbers[left] + numbers[right] > target: 14 | right -= 1 15 | else: 16 | left += 1 17 | return [] 18 | 19 | if __name__ == "__main__": 20 | array = [2, 7, 11, 15] 21 | target = 9 22 | print(Solution().twoSum(array, target)) -------------------------------------------------------------------------------- /solutions/0169-Majority-Element/0169.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def majorityElement(self, nums: List[int]) -> int: 5 | # solution one: 哈希表 6 | import collections 7 | counts = collections.Counter(nums) 8 | return max(counts.keys(), key=counts.get) 9 | 10 | # solution two: 排序 11 | nums.sort() 12 | return nums[len(nums)//2] 13 | 14 | # solution three: Boyer-Moore 投票算法 15 | count = 0 16 | candidate = None 17 | 18 | for num in nums: 19 | if count == 0: 20 | candidate = num 21 | # 众数和非众数相互抵消,最后剩下的肯定是众数 22 | count += (1 if num == candidate else -1) 23 | 24 | return candidate 25 | 26 | if __name__ == "__main__": 27 | nums = [3,2,3] 28 | print(Solution().majorityElement(nums)) -------------------------------------------------------------------------------- /solutions/0188-Best-Time-to-Buy-and-Sell-Stock-IV/0188.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def maxProfit(self, k: int, prices: List[int]) -> int: 5 | n = len(prices) 6 | if k > n/2: 7 | # k = inf 8 | dp_i_0 = 0 9 | dp_i_1 = float('-inf') # 负无穷 10 | for i in range(n): 11 | temp = dp_i_0 12 | # 昨天没有股票,昨天有股票今天卖出 13 | dp_i_0 = max(dp_i_0, dp_i_1 + prices[i]) # dp_i_0 和 dp_i_1 可以看成是变量,存储的都是上一次即昨天的值 14 | # 昨天有股票,昨天没有股票今天买入 15 | dp_i_1 = max(dp_i_1, temp - prices[i]) 16 | return dp_i_0 17 | 18 | # k <= len(prices)/2 19 | # dp = [[[0] * 2] * (k+1)] * n # 创建三维数组,这么初始化三维列表,是浅复制,所以修改其中一个值会同时影响其他的值,所以这种方法不正确 20 | dp = [[[0] * 2 for _ in range(k+1)] for _ in range(n)] 21 | for i in range(n): 22 | for j in range(k, 0, -1): # 逆序 23 | if i == 0: 24 | dp[0][j][0] = 0 25 | dp[0][j][1] = -prices[0] 26 | continue 27 | # 昨天没有股票,昨天有股票今天卖出 28 | dp[i][j][0] = max(dp[i-1][j][0], dp[i-1][j][1] + prices[i]) 29 | # 昨天有股票,昨天没有股票今天买入,这里把买入当作一次交易,所以是 j-1 30 | # 如果把 j-1 写在上一行代码即把卖出当作一次交易,运行结果不是正确答案,不知道是为什么 31 | dp[i][j][1] = max(dp[i-1][j][1], dp[i-1][j-1][0] - prices[i]) 32 | 33 | return dp[n-1][k][0] 34 | 35 | if __name__ == "__main__": 36 | prices = [3,3,5,0,0,3,1,4] 37 | k = 2 38 | print(Solution().maxProfit(k, prices)) -------------------------------------------------------------------------------- /solutions/0200-Number-of-Islands/0200.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def numIslands(self, grid: List[List[str]]) -> int: 3 | ans = 0 4 | # m, n = len(grid), len(grid[0]) # Runtime Error 5 | for i in range(len(grid)): 6 | for j in range(len(grid[0])): 7 | if grid[i][j] == "1": 8 | self.dfs(grid, i, j) 9 | ans += 1 10 | return ans 11 | 12 | # dfs template 13 | def dfs(self, grid, i, j): 14 | m, n = len(grid), len(grid[0]) 15 | directions = [(0, 1), (0, -1), (-1, 0), (1, 0)] 16 | grid[i][j] = "0" 17 | for direction in directions: 18 | x, y = i + direction[0], j + direction[1] 19 | if 0 <= x < m and 0 <= y < n: 20 | if grid[x][y] == "1": # change "1" to "0" 21 | self.dfs(grid, x, y) -------------------------------------------------------------------------------- /solutions/0206-Reverse-Linked-List/0206.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.next = None 6 | 7 | class Solution: 8 | def reverseList(self, head: ListNode) -> ListNode: 9 | # solution one: List 10 | pos = head 11 | newList = [] 12 | while pos: 13 | newList.insert(0, pos.val) 14 | pos = pos.next 15 | 16 | pos = head 17 | for _ in newList: 18 | pos.val = _ 19 | pos = pos.next 20 | return head 21 | 22 | # solution two: two point 23 | cur, pre = None, head 24 | while pre: 25 | pos = pre.next 26 | pre.next = cur 27 | cur = pre 28 | pre = pos 29 | return cur 30 | 31 | # solution three: recursion 32 | if not head or not head.next: 33 | return head 34 | 35 | pos = head.next 36 | newList = self.reverseList(pos) 37 | 38 | head.next = None 39 | pos.next = head 40 | return newList -------------------------------------------------------------------------------- /solutions/0215-Kth-Largest-Element-in-an-Array/0215.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def findKthLargest(self, nums, k): 3 | """ 4 | :type nums: List[int] 5 | :type k: int 6 | :rtype: int 7 | """ 8 | low, high = 0, len(nums)-1 9 | while low <= high: 10 | pivot = self.partition(nums, low, high) 11 | if pivot == k - 1: # 第 k 大, 即从大到小排序第 k-1 位置(从 0 开始计算) 12 | return nums[pivot] 13 | if pivot < k - 1: 14 | low = pivot + 1 15 | else: 16 | high = pivot - 1 17 | 18 | # 划分函数 19 | def partition(self, nums, low, high): 20 | pivot_value = nums[high] # 因为是从大到小排序, 所以选 nums[high] 为基值 21 | index = low 22 | for i in range(low, high): 23 | if nums[i] >= pivot_value: 24 | nums[i], nums[index] = nums[index], nums[i] 25 | index += 1 26 | nums[index], nums[high] = nums[high], nums[index] 27 | return index # 返回的 index 即分界点 28 | 29 | """ 30 | # 直接调用 Python 的 heapq 模块 31 | import heapq 32 | list_k = heapq.nlargest(k, nums) 33 | return list_k.pop() 34 | """ 35 | 36 | # return sorted(nums)[-k] # 用 Python 自带的排序算法一行代码就能 AC 37 | 38 | if __name__ == "__main__": 39 | nums = [3,2,1,5,6,4] 40 | k = 2 41 | print(Solution().findKthLargest(nums, k)) -------------------------------------------------------------------------------- /solutions/0222-Count-Complete-Tree-Nodes/0222.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def countNodes(self, root: TreeNode) -> int: 10 | l = TreeNode(None) 11 | l = root 12 | r = TreeNode(None) 13 | r = root 14 | heightleft, heightright = 0, 0 # 记录左右子树的高度 15 | while l != None: 16 | l = l.left 17 | heightleft += 1 18 | while r != None: 19 | r = r.right 20 | heightright += 1 21 | 22 | # 如果左右子树高度相同,则是一棵满二叉树 23 | if heightleft == heightright: 24 | return 2**heightleft - 1 25 | 26 | # 如果左右子树高度不相同,则是按普通二叉树计算 27 | return 1 + self.countNodes(root.left) + self.countNodes(root.right) -------------------------------------------------------------------------------- /solutions/0225-Implement-Stack-using-Queues/0225.py: -------------------------------------------------------------------------------- 1 | class MyStack: 2 | 3 | def __init__(self): 4 | """ 5 | Initialize your data structure here. 6 | """ 7 | self.myStack = [] 8 | 9 | def push(self, x: int) -> None: 10 | """ 11 | Push element x onto stack. 12 | """ 13 | self.myStack.append(x) 14 | 15 | def pop(self) -> int: 16 | """ 17 | Removes the element on top of the stack and returns that element. 18 | """ 19 | # judge if it is empty 20 | if not self.empty(): 21 | return self.myStack.pop() 22 | 23 | def top(self) -> int: 24 | """ 25 | Get the top element. 26 | """ 27 | # judge if it is empty 28 | if not self.empty(): 29 | return self.myStack[-1] 30 | 31 | 32 | def empty(self) -> bool: 33 | """ 34 | Returns whether the stack is empty. 35 | """ 36 | return len(self.myStack) == 0 37 | 38 | 39 | 40 | # Your MyStack object will be instantiated and called as such: 41 | # obj = MyStack() 42 | # obj.push(x) 43 | # param_2 = obj.pop() 44 | # param_3 = obj.top() 45 | # param_4 = obj.empty() -------------------------------------------------------------------------------- /solutions/0226-Invert-Binary-Tree/0226.go: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * type TreeNode struct { 4 | * Val int 5 | * Left *TreeNode 6 | * Right *TreeNode 7 | * } 8 | */ 9 | func invertTree(root *TreeNode) *TreeNode { 10 | // 前序遍历 11 | if root == nil { 12 | return nil 13 | } 14 | 15 | root.Left, root.Right = root.Right, root.Left 16 | 17 | invertTree(root.Left) 18 | invertTree(root.Right) 19 | 20 | return root 21 | } 22 | 23 | 24 | func invertTree(root *TreeNode) *TreeNode { 25 | // 后序遍历 26 | if root == nil { 27 | return nil 28 | } 29 | 30 | invertTree(root.Left) 31 | invertTree(root.Right) 32 | 33 | root.Left, root.Right = root.Right, root.Left 34 | 35 | return root 36 | } -------------------------------------------------------------------------------- /solutions/0226-Invert-Binary-Tree/0226.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def invertTree(self, root: TreeNode) -> TreeNode: 10 | # solution one: 递归 11 | if not root: 12 | return None 13 | # 叶子节点,直接返回自己 14 | if not root.left and not root.right: 15 | return root 16 | 17 | # 交换非叶子节点的左右两棵子树 18 | root.left, root.right = root.right, root.left 19 | if root.left: 20 | self.invertTree(root.left) 21 | if root.right: 22 | self.invertTree(root.right) 23 | return root 24 | 25 | # solution two: 栈 26 | if not root: 27 | return None 28 | # 叶子节点,直接返回自己 29 | if not root.left and not root.right: 30 | return root 31 | 32 | # 栈模拟二叉树 33 | stack = [root] 34 | while stack: 35 | node = stack.pop() 36 | if node: 37 | node.left, node.right = node.right, node.left 38 | stack.append(node.right) 39 | stack.append(node.left) 40 | return root -------------------------------------------------------------------------------- /solutions/0230-Kth-Smallest-Element-in-a-BST/0230.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | class Solution: 8 | def kthSmallest(self, root: TreeNode, k: int) -> int: 9 | # 中序遍历 10 | def inorder(root): 11 | if not root: 12 | return [] 13 | return inorder(root.left) + [root.val] + inorder(root.right) 14 | 15 | return inorder(root)[k - 1] -------------------------------------------------------------------------------- /solutions/0235-Lowest-Common-Ancestor-of-a-Binary-Search-Tree/0235.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': 10 | ancestor = root 11 | while True: 12 | # p q 在左边 13 | if p.val < ancestor.val and q.val < ancestor.val: 14 | ancestor = ancestor.left 15 | # p q 在右边 16 | elif p.val > ancestor.val and q.val > ancestor.val: 17 | ancestor = ancestor.right 18 | # p q 分别在左右,当前节点就是最近公共祖先 19 | else: 20 | break 21 | return ancestor -------------------------------------------------------------------------------- /solutions/0236-Lowest-Common-Ancestor-of-a-Binary-Tree/0236.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': 10 | if not root or root == p or root == q: 11 | return root 12 | 13 | left = self.lowestCommonAncestor(root.left, p, q) 14 | right = self.lowestCommonAncestor(root.right, p, q) 15 | 16 | if not left and not right: 17 | return None 18 | elif left and not right: 19 | return left 20 | elif not left and right: 21 | return right 22 | return root -------------------------------------------------------------------------------- /solutions/0240-Search-a-2D-Matrix-II/0240.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def searchMatrix(self, matrix, target): 5 | """ 6 | :type matrix: List[List[int]] 7 | :type target: int 8 | :rtype: bool 9 | """ 10 | # solution one: 暴力 11 | # 特判 12 | if matrix == []: 13 | return False 14 | 15 | n, m = len(matrix), len(matrix[0]) 16 | for i in range(n): 17 | for j in range(m): 18 | if matrix[i][j] == target: 19 | return True 20 | elif matrix[i][j] > target: 21 | break 22 | return False 23 | 24 | # solution two: 左下角标志数法 25 | i, j = len(matrix) - 1, 0 26 | while i >= 0 and j < len(matrix[0]): 27 | if matrix[i][j] == target: 28 | return True 29 | elif matrix[i][j] > target: 30 | i -= 1 31 | else: 32 | j += 1 33 | return False -------------------------------------------------------------------------------- /solutions/0241-Different-Ways-to-Add-Parentheses/0241.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def diffWaysToCompute(self, input: str) -> List[int]: 5 | # solution: Divide and conquer 6 | if input.isdigit(): # input only contains digital 7 | return [int(input)] 8 | n = len(input) 9 | res = [] 10 | for i in range(n): 11 | if input[i] in '+-*': 12 | lefts = self.diffWaysToCompute(input[:i]) 13 | rights = self.diffWaysToCompute(input[i+1:]) 14 | for left in lefts: 15 | for right in rights: 16 | if input[i] == '+': 17 | res.append(left + right) 18 | elif input[i] == '-': 19 | res.append(left - right) 20 | elif input[i] == '*': 21 | res.append(left * right) 22 | # # use eval 23 | # res.append(eval(str(left) + input[i] + str(right))) 24 | return res 25 | 26 | if __name__ == "__main__": 27 | input = "2-1-1" 28 | print(Solution().diffWaysToCompute(input)) -------------------------------------------------------------------------------- /solutions/0257-Binary-Tree-Paths/0257.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def binaryTreePaths(self, root: TreeNode) -> List[str]: 10 | if not root: 11 | return [] 12 | ans = [] 13 | self.dfs(root, ans, '' + str(root.val)) 14 | return ans 15 | 16 | def dfs(self, root, ans, path): 17 | if root.left == None and root.right == None: 18 | ans.append(path) 19 | if root.left != None: 20 | self.dfs(root.left, ans, path + '->' + str(root.left.val)) 21 | if root.right != None: 22 | self.dfs(root.right, ans, path + '->' + str(root.right.val)) -------------------------------------------------------------------------------- /solutions/0278-First-Bad-Version/0278.py: -------------------------------------------------------------------------------- 1 | # The isBadVersion API is already defined for you. 2 | # @param version, an integer 3 | # @return a bool 4 | # def isBadVersion(version): 5 | 6 | class Solution(object): 7 | def firstBadVersion(self, n): 8 | """ 9 | :type n: int 10 | :rtype: int 11 | """ 12 | low, high = 1, n # 1-n 13 | while low <= high: 14 | mid = int((low + high) / 2) 15 | if isBadVersion(mid) == False: 16 | low = mid + 1 17 | else: 18 | high = mid - 1 19 | return low -------------------------------------------------------------------------------- /solutions/0279-Perfect-Squares/0279.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def numSquares(self, n: int) -> int: 3 | # solution one: BFS 4 | q = [(n, 0)] 5 | visited = [False for i in range(n + 1)] # initialize all False 6 | visited[n] = True 7 | 8 | while any(q): # any: if all elements are False, return False, or return True 9 | num, step = q.pop(0) 10 | 11 | i = 1 12 | Num = num - i ** 2 13 | while Num >= 0: 14 | if Num == 0: 15 | return step + 1 16 | if not visited[Num]: # not visited 17 | q.append((Num, step + 1)) 18 | visited[Num] = True 19 | 20 | i += 1 21 | Num = num - i ** 2 22 | 23 | # solution two: Lagrange's Four-square Theorem 24 | while n % 4 == 0: # reduce n 25 | n /= 4 26 | 27 | if n % 8 == 7: 28 | return 4 29 | 30 | a = 0 31 | while a ** 2 <= n: 32 | b = int((n - a ** 2) ** 0.5) 33 | if a ** 2 + b ** 2 == n: 34 | return (not not a) + (not not b) # whether a and b are positive integers 35 | a += 1 36 | 37 | return 3 38 | 39 | if __name__ == "__main__": 40 | n = 13 41 | print(Solution().numSquares(n)) -------------------------------------------------------------------------------- /solutions/0283-move-zeroes/0283.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def moveZeroes(self, nums: List[int]) -> None: 3 | """ 4 | Do not return anything, modify nums in-place instead. 5 | """ 6 | # solution 1 7 | n = len(nums) 8 | left, right = 0, 0 9 | while right < n: 10 | if nums[right] != 0: 11 | nums[left], nums[right] = nums[right], nums[left] 12 | left += 1 13 | right += 1 14 | 15 | # solution 2 16 | count0 = 0 17 | for i in range(len(nums)): 18 | if nums[i] == 0: 19 | count0 += 1 20 | elif count0 != 0: 21 | nums[i - count0], nums[i] = nums[i], 0 22 | 23 | # solution 3 24 | j = 0 25 | for i in range(len(nums)): 26 | if nums[i] != 0: 27 | nums[j] = nums[i] 28 | if i != j: 29 | nums[i] = 0 30 | j += 1 -------------------------------------------------------------------------------- /solutions/0300-Longest-Increasing-Subsequence/0300.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def lengthOfLIS(self, nums: List[int]) -> int: 5 | # # solution one: 动态规划 6 | # n = len(nums) 7 | # dp = [1] * n # 初始化每个都为 1 8 | # for i in range(n): 9 | # for j in range(i): 10 | # if nums[i] > nums[j]: 11 | # dp[i] = max(dp[i], dp[j] + 1) 12 | 13 | # res = 0 14 | # for i in range(n): 15 | # res = max(res, dp[i]) 16 | # return res 17 | 18 | # solution two: 二分 19 | n = len(nums) 20 | top = [0] * n 21 | # 牌堆数初始化为 0 22 | piles = 0 23 | for i in nums: 24 | poker = i 25 | 26 | # 搜索左侧边界的二分查找 27 | left, right = 0, piles 28 | while left < right: 29 | mid = int((left + right) / 2) 30 | if top[mid] > poker: 31 | right = mid 32 | elif top[mid] < poker: 33 | left = mid + 1 34 | else: 35 | right = mid 36 | 37 | # 新建一个牌堆 38 | if left == piles: 39 | piles += 1 40 | # 把这张牌放到牌堆顶 41 | top[left] = poker 42 | 43 | # 牌堆数就是 LTS 长度 44 | return piles 45 | 46 | if __name__ == "__main__": 47 | nums = [10,9,2,5,3,7,101,18] 48 | print(Solution().lengthOfLIS(nums)) -------------------------------------------------------------------------------- /solutions/0309-Best-Time-to-Buy-and-Sell-Stock-with-Cooldown/0309.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def maxProfit(self, prices: List[int]) -> int: 5 | dp_i_0 = 0 6 | dp_i_1 = float('-inf') # 负无穷 7 | dp_pre_0 = 0 # 表示 dp[i-2][0] 8 | for i in range(len(prices)): 9 | temp = dp_i_0 10 | # 昨天没有股票,昨天有股票今天卖出 11 | dp_i_0 = max(dp_i_0, dp_i_1 + prices[i]) # dp_i_0 和 dp_i_1 可以看成是变量,存储的都是上一次即昨天的值 12 | # 昨天有股票,前天刚卖出股票昨天冷冻期今天买入 13 | dp_i_1 = max(dp_i_1, dp_pre_0 - prices[i]) 14 | dp_pre_0 = temp 15 | 16 | return dp_i_0 17 | 18 | if __name__ == "__main__": 19 | prices = [7,1,5,3,6,4] 20 | print(Solution().maxProfit(prices)) -------------------------------------------------------------------------------- /solutions/0332-Reconstruct-Itinerary/0332.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findItinerary(self, tickets: List[List[str]]) -> List[str]: 3 | from collections import defaultdict 4 | ticket_dict = defaultdict(list) 5 | for item in tickets: 6 | ticket_dict[item[0]].append(item[1]) 7 | 8 | path = ['JFK'] 9 | 10 | def dfs(cur_from): 11 | # 结束条件:path的长度为 tickets 长度 + 1 12 | if len(path) == len(tickets) + 1: 13 | return True 14 | # 按字典序排序 15 | ticket_dict[cur_from].sort() 16 | 17 | for _ in ticket_dict[cur_from]: 18 | # 去掉不合适 19 | cur_to = ticket_dict[cur_from].pop(0) 20 | path.append(cur_to) 21 | # 下一层 22 | if dfs(cur_to): 23 | return True 24 | # 取消选择 25 | path.pop() 26 | # 恢复当前节点 27 | ticket_dict[cur_from].append(cur_to) 28 | return False 29 | 30 | dfs('JFK') 31 | return path -------------------------------------------------------------------------------- /solutions/0345-Reverse-Vowels-of-a-String/0345.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def reverseVowels(self, s): 3 | """ 4 | :type s: str 5 | :rtype: str 6 | """ 7 | left, right = 0, len(s)-1 # 同时赋值 8 | vowels = 'aeiou' 9 | string = list(s) # 字符串不能改变, 所以要转为 list 10 | while left < right: 11 | if string[left].lower() not in vowels: # lower 是取小写 12 | left += 1 13 | elif string[right].lower() not in vowels: 14 | right -= 1 15 | else: 16 | string[left], string[right] = string[right], string[left] 17 | left += 1 18 | right -= 1 19 | return ''.join(string) # 将 string 中的元素以指定的字符连接生成一个新的字符串 20 | 21 | if __name__ == "__main__": 22 | str = "hello" 23 | print(Solution().reverseVowels(str)) -------------------------------------------------------------------------------- /solutions/0347-Top-K-Frequent-Elements/0347.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def topKFrequent(self, nums, k): 3 | """ 4 | :type nums: List[int] 5 | :type k: int 6 | :rtype: List[int] 7 | """ 8 | # 统计元素的频率 9 | count = dict() 10 | for num in nums: 11 | count[num] = count.get(num, 0) + 1 # 返回字典 count 中 num 元素对应的值, 没有就赋值为 0 12 | 13 | # 桶排序 14 | bucket = [[] for i in range(len(nums) + 1)] 15 | for key, value in count.items(): 16 | bucket[value].append(key) 17 | 18 | # 逆序取出前 k 个元素 19 | res = list() 20 | for i in range(len(nums), -1, -1): # 最后一个 -1 表示逆序 21 | if bucket[i]: 22 | res.extend(bucket[i]) # 在列表末尾追加元素 23 | if len(res) >= k: # 只要前 k 个 24 | break 25 | return res[:k] # 输出第 k 个之前的元素(包括第 k 个元素) 26 | 27 | if __name__ == '__main__': 28 | nums = [4,1,1,1,2,2,3] 29 | k = 2 30 | print(Solution().topKFrequent(nums, k)) -------------------------------------------------------------------------------- /solutions/0365-Water-and-Jug-Problem/0365.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def canMeasureWater(self, x: int, y: int, z: int) -> bool: 3 | # solution one: BFS 4 | from collections import deque 5 | queue = deque([[0, 0]]) 6 | visited = set([(0, 0)]) 7 | 8 | while queue: 9 | cur_x, cur_y = queue.pop() 10 | if z in [cur_x, cur_y, cur_x + cur_y]: 11 | return True 12 | for item in [ 13 | # x 加满水,y 加满水 14 | (x, cur_y), (cur_x, y), 15 | # x 清空水,y 清空水 16 | (0, cur_y), (cur_x, 0), 17 | # 把 x 壶的水灌进 y 壶,直至灌满或倒空 18 | (cur_x + cur_y - y, y) if cur_x + cur_y >= y else (0, cur_x + cur_y), 19 | # 把 X 壶的水灌进 Y 壶,直至灌满或倒空 20 | (x, cur_x + cur_y - x) if cur_x + cur_y >= x else (cur_x + cur_y, 0)]: 21 | if item not in visited: 22 | queue.appendleft(item) # 从队列左边加入元素 23 | visited.add(item) 24 | return False 25 | 26 | # solution two: 裴蜀定理 27 | import math 28 | if x + y < z: 29 | return False 30 | if x == z or y == z or x + y == z: 31 | return True 32 | return z % math.gcd(x, y) == 0 -------------------------------------------------------------------------------- /solutions/0392-Is-Subsequence/0392.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def isSubsequence(self, s, t): 3 | """ 4 | :type s: str 5 | :type t: str 6 | :rtype: bool 7 | """ 8 | i, j = 0, 0 9 | while i < len(s) and j < len(t): 10 | if s[i] == t[j]: 11 | i += 1 12 | j += 1 13 | return i == len(s) 14 | 15 | if __name__ == "__main__": 16 | s = "abc" 17 | t = "ahbgdc" 18 | print(Solution().isSubsequence(s, t)) -------------------------------------------------------------------------------- /solutions/0406-Queue-Reconstruction-by-Height/0406.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def reconstructQueue(self, people): 3 | """ 4 | :type people: List[List[int]] 5 | :rtype: List[List[int]] 6 | """ 7 | people.sort(key = lambda x : (-x[0], x[1])) # 按照h从高到低,k从小到大排序 8 | res = [] 9 | for p in people: 10 | res.insert(p[1], p) # 每次只要在p[1]位置插入p就行,因为p[1]表示p前只能出现的个数 11 | return res 12 | 13 | if __name__ == "__main__": 14 | people = [[7,0],[7,1],[6,1],[5,0],[5,2],[4,4]] 15 | print(Solution().reconstructQueue(people)) -------------------------------------------------------------------------------- /solutions/0409-Longest-Palindrome/0409.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def longestPalindrome(self, s: str) -> int: 3 | import collections 4 | # 统计各字符个数 5 | count = collections.Counter(s).values() 6 | sum = 0 7 | for x in count: 8 | if x // 2 > 0: 9 | # 取偶数个字符 10 | sum += x // 2 * 2 11 | if sum == len(s): 12 | return sum 13 | else: 14 | return sum + 1 -------------------------------------------------------------------------------- /solutions/0429-N-ary-Tree-Level-Order-Traversal/0429.py: -------------------------------------------------------------------------------- 1 | """ 2 | # Definition for a Node. 3 | class Node: 4 | def __init__(self, val=None, children=None): 5 | self.val = val 6 | self.children = children 7 | """ 8 | 9 | class Solution: 10 | def levelOrder(self, root: 'Node') -> List[List[int]]: 11 | import collections 12 | res = [] 13 | if not root: 14 | return res 15 | 16 | q = collections.deque() 17 | q.append(root) 18 | # BFS 19 | while q: 20 | tmp = [] 21 | for _ in range(len(q)): 22 | node = q.popleft() 23 | tmp.append(node.val) 24 | # 使用extend在列表末尾一次追加多个值 25 | q.extend(node.children) 26 | res.append(tmp) 27 | return res -------------------------------------------------------------------------------- /solutions/0435-Non-overlapping-Intervals/0435.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def eraseOverlapIntervals(self, intervals): 3 | """ 4 | :type intervals: List[List[int]] 5 | :rtype: int 6 | """ 7 | if not intervals or len(intervals) == 0: 8 | return 0 9 | intervals.sort(key = lambda x: x[0]) # 按左端点从小到大排序 10 | temp_pos = 0 11 | cnt = 0 12 | for i in range(1, len(intervals)): 13 | if intervals[temp_pos][1] > intervals[i][0]: # 当当前区间右端点>i区间左端点 14 | if intervals[i][1] < intervals[temp_pos][1]: # 当i区间右端点<当前区间右端点,表示i区间被覆盖在当前区间中 15 | temp_pos = i # 更新temp_pos,选择覆盖范围小的i区间 16 | cnt += 1 # 当前区间右端点>i区间左端点都要计数+1 17 | else: 18 | temp_pos = i # 当当前区间右端点<=i区间左端点,表示不重叠,要更新temp_pos 19 | return cnt 20 | 21 | if __name__ == "__main__": 22 | intervals = [[1,2],[1,2],[1,2]] 23 | # intervals = [[1,2],[2,3],[3,4],[1,3]] 24 | # intervals = [[1,2],[2,3]] 25 | print(Solution().eraseOverlapIntervals(intervals)) -------------------------------------------------------------------------------- /solutions/0450-Delete-Node-in-a-BST/0450.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def deleteNode(self, root: TreeNode, key: int) -> TreeNode: 10 | # 树为空 11 | if root == None: 12 | return None 13 | # 找到 key,进行删除 14 | if root.val == key: 15 | # 情况 1:两个子节点都为空 16 | # 情况 2:只有一个非空子节点,让这个孩子取代自己 17 | if root.left == None: 18 | return root.right 19 | if root.right == None: 20 | return root.left 21 | # 情况 3:有两个非空子节点,找到左子树的最大值,或者右子树的最小值,取代自己 22 | # Python3 需要先有一个 TreeNode 对象 23 | minNode = TreeNode(None) 24 | minNode = self.getMin(root.right) 25 | root.val = minNode.val 26 | root.right = self.deleteNode(root.right, minNode.val) 27 | # key 在左子树 28 | elif root.val > key: 29 | root.left = self.deleteNode(root.left, key) 30 | # key 在右子树 31 | elif root.val < key: 32 | root.right = self.deleteNode(root.right, key) 33 | return root 34 | 35 | def getMin(self, node: TreeNode): 36 | # BST 最左边的是最小值 37 | while node.left != None: 38 | node = node.left 39 | return node -------------------------------------------------------------------------------- /solutions/0451-Sort-Characters-By-Frequency/0451.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def frequencySort(self, s): 3 | """ 4 | :type s: str 5 | :rtype: str 6 | """ 7 | # # 法一:collections.Counter 8 | # import collections # 需要导入collections 9 | # count = collections.Counter(s).most_common() # Counter类就能统计每个字符出现的次数, 使用most_common函数就能按次序排列 10 | # res = '' 11 | # for char, cnt in count: 12 | # res += char*cnt # 字符与次数相乘 13 | # return res 14 | 15 | # 法二:桶排序 16 | import collections 17 | 18 | # 统计字符个数 19 | ret = [] 20 | count_frequency = collections.defaultdict(int) 21 | for i in s: 22 | count_frequency[i] += 1 # 统计字符个数 23 | 24 | # 桶排序 25 | buckets = [[] for i in range(len(s) + 1)] 26 | for i in count_frequency: # i是字符 27 | # print (i) 28 | buckets[count_frequency[i]].extend(i * count_frequency[i]) 29 | 30 | # 打印排完序的字符串 31 | for i in buckets[::-1]: # -1表示逆序 32 | if(i): 33 | ret.extend(i) 34 | return ''.join(ret) 35 | 36 | # return ''.join(c*-n for n,c in sorted((-s.count(c),c)for c in set(s))) # 一行代码也能解决 37 | 38 | 39 | if __name__ == "__main__": 40 | s = "abcc" 41 | print(Solution().frequencySort(s)) -------------------------------------------------------------------------------- /solutions/0452-Minimum-Number-of-Arrows-to-Burst-Balloons/0452.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def findMinArrowShots(self, points): 3 | """ 4 | :type points: List[List[int]] 5 | :rtype: int 6 | """ 7 | if not points or len(points) == 0: 8 | return 0 9 | points.sort(key = lambda x: x[1]) # 按右端点从小到大排序 10 | temp_pos = points[0][1] 11 | cnt = 1 12 | for i in range(len(points)): 13 | if temp_pos >= points[i][0]: # 当右端点<左端点时,要再加一支箭 14 | continue 15 | temp_pos = points[i][1] 16 | cnt += 1 17 | return cnt 18 | 19 | 20 | if __name__ == "__main__": 21 | points = [[10,16], [2,8], [1,6], [7,12]] 22 | print(Solution().findMinArrowShots(points)) -------------------------------------------------------------------------------- /solutions/0455-Assign-Cookies/0455.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def findContentChildren(self, g, s): 3 | """ 4 | :type g: List[int] 5 | :type s: List[int] 6 | :rtype: int 7 | """ 8 | # 贪心 9 | cnt = 0 10 | g, s = sorted(g), sorted(s) # 从小到大排序 11 | i, j = len(g)-1, len(s)-1 # 指向末尾 12 | while min(i, j) >= 0: 13 | if g[i] <= s[j]: # 贪婪指数要 <= 饼干大小 14 | cnt += 1 15 | j -= 1 16 | i -= 1 # 不管满不满足 size,i 都要往左移一位 17 | return cnt 18 | 19 | if __name__ == "__main__": 20 | g = [1,2,3] 21 | s = [1,1] 22 | print(Solution().findContentChildren(g, s)) -------------------------------------------------------------------------------- /solutions/0491-Increasing-Subsequences/0491.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findSubsequences(self, nums: List[int]) -> List[List[int]]: 3 | # solution one:DFS 4 | res = [] 5 | 6 | def dfs(nums, tmp): 7 | if len(tmp) > 1: 8 | res.append(tmp) 9 | 10 | cur_pres = set() 11 | # 循环 nums 的索引值对 12 | for inx, i in enumerate(nums): 13 | # 当前值已经被遍历 14 | if i in cur_pres: 15 | continue 16 | # 当前值可以加入组成递增子序列 17 | if not tmp or i >= tmp[-1]: 18 | cur_pres.add(i) 19 | dfs(nums[inx + 1:], tmp + [i]) 20 | 21 | dfs(nums, []) 22 | return res -------------------------------------------------------------------------------- /solutions/0508-Most-Frequent-Subtree-Sum/0508.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def findFrequentTreeSum(self, root: TreeNode) -> List[int]: 10 | import collections 11 | res_dic = collections.defaultdict(int) 12 | # 计算子树元素和 13 | def dfs(node): 14 | # 递归边界 15 | if not node: 16 | return 0 17 | tmp_sum = dfs(node.left) + node.val + dfs(node.right) 18 | res_dic[tmp_sum] += 1 19 | return tmp_sum 20 | 21 | if not root: 22 | return [] 23 | dfs(root) 24 | max_cnt = 0 25 | for cnt in res_dic.values(): 26 | max_cnt = max(max_cnt, cnt) 27 | return [key for key, cnt in res_dic.items() if cnt == max_cnt] -------------------------------------------------------------------------------- /solutions/0509-Fibonacci-Number/0509.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def fib(self, n: int) -> int: 3 | # solution one: 递归 4 | if n == 0: 5 | return 0 6 | if n == 1: 7 | return 1 8 | return self.fib(n - 1) + self.fib(n - 2) 9 | 10 | # solution two: 动态规划 11 | dp_0, dp_1 = 0, 1 12 | for _ in range(n): 13 | dp_0, dp_1 = dp_1, dp_0 + dp_1 14 | return dp_0 -------------------------------------------------------------------------------- /solutions/0513-Find-Bottom-Left-Tree-Value/0513.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | class Solution: 8 | def findBottomLeftValue(self, root: TreeNode) -> int: 9 | import collections 10 | q = collections.deque() 11 | q.append(root) 12 | while q: 13 | node = q.popleft() 14 | # 先右后左 15 | if node.right: 16 | q.append(node.right) 17 | if node.left: 18 | q.append(node.left) 19 | # 最后一个必是最左下角的节点 20 | return node.val -------------------------------------------------------------------------------- /solutions/0515-Find-Largest-Value-in-Each-Tree-Row/0515.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | class Solution: 8 | def largestValues(self, root: TreeNode) -> List[int]: 9 | import collections 10 | if not root: 11 | return [] 12 | res = [] 13 | q = collections.deque() 14 | q.append(root) 15 | while q: 16 | size = len(q) 17 | tmp_max = -float('inf') 18 | # 取每一层最大值 19 | for i in range(size): 20 | node = q.popleft() 21 | tmp_max = max(tmp_max, node.val) 22 | # 一层树遍历完,加入该层最大值 23 | if i == size - 1: 24 | res.append(tmp_max) 25 | if node.left: 26 | q.append(node.left) 27 | if node.right: 28 | q.append(node.right) 29 | return res -------------------------------------------------------------------------------- /solutions/0524-Longest-Word-in-Dictionary-through-Deleting/0524.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def findLongestWord(self, s, d): 3 | """ 4 | :type s: str 5 | :type d: List[str] 6 | :rtype: str 7 | """ 8 | res = "" 9 | max = -1 10 | for word in d: 11 | if len(s) < len(word) or len(word) == 0: 12 | continue 13 | j = 0 # j 指针判断 word 中的每个字符 14 | for i in range(len(s)): # i 指针判断 s 中的每个字符 15 | if s[i] == word[j]: 16 | j += 1 # 如果相等, 只移动 j 指针 17 | if j == len(word): # j 指针已移动 word 末尾 18 | if len(word) > max: # 更新 res 和 max 19 | res = word 20 | max = len(word) 21 | elif len(word) == max: 22 | res = min(res, word) # 长度相同则选最小字典序的 word 23 | break 24 | return res 25 | 26 | if __name__ == "__main__": 27 | s = 'abpcplea' 28 | d = ['ale', 'apple', 'monkey', 'plea'] 29 | print(Solution().findLongestWord(s,d)) -------------------------------------------------------------------------------- /solutions/0529-Minesweeper/0529.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def updateBoard(self, board: List[List[str]], click: List[int]) -> List[List[str]]: 3 | # 初始位置是雷,直接改为 X 退出 4 | if board[click[0]][click[1]] == 'M': 5 | board[click[0]][click[1]] = 'X' 6 | return board 7 | 8 | self.m, self.n = len(board), len(board[0]) 9 | direction = ((1, 0), (-1, 0), (0, 1), (0, -1), (1, 1), (-1, 1), (-1, -1), (1, -1)) 10 | 11 | # 检查周围雷的情况 12 | def check(i, j): 13 | cnt = 0 14 | for x, y in direction: 15 | x, y = x + i, y + j 16 | if 0 <= x < self.m and 0 <= y < self.n and board[x][y] == 'M': 17 | cnt += 1 18 | return cnt 19 | 20 | # DFS 21 | def dfs(i ,j): 22 | cnt = check(i, j) 23 | # 周围没有雷 24 | if not cnt: 25 | board[i][j] = 'B' 26 | for x, y in direction: 27 | x, y = x + i, y + j 28 | if 0 <= x < self.m and 0 <= y < self.n and board[x][y] == 'E': 29 | dfs(x, y) 30 | # 标记周围有雷 31 | else: 32 | board[i][j] = str(cnt) 33 | dfs(click[0], click[1]) 34 | return board -------------------------------------------------------------------------------- /solutions/0530-Minimum-Absolute-Difference-in-BST/0530.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def getMinimumDifference(self, root: TreeNode) -> int: 10 | # solution one: dfs遍历取节点值,再单独计算最小绝对差 11 | def dfs(root): 12 | if not root: 13 | return 14 | # 中序遍历是递增的 15 | if root.left: 16 | dfs(root.left) 17 | tmp_val.append(root.val) 18 | if root.right: 19 | dfs(root.right) 20 | tmp_val = [] 21 | dfs(root) 22 | res = float("inf") 23 | for i in range(len(tmp_val) - 1): 24 | res = min(res, abs(tmp_val[i] - tmp_val[i + 1])) 25 | return res 26 | 27 | # solution two: dfs遍历直接进行绝对值比较 28 | pre = -1 29 | res = float("inf") 30 | def dfs(root): 31 | nonlocal pre, res 32 | if not root: 33 | return 34 | # 中序遍历是递增的 35 | if root.left: 36 | dfs(root.left) 37 | if pre != -1: 38 | res = min(res, abs(pre - root.val)) 39 | pre = root.val 40 | if root.right: 41 | dfs(root.right) 42 | dfs(root) 43 | return res -------------------------------------------------------------------------------- /solutions/0538-Convert-BST-to-Greater-Tree/0538.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | class Solution: 8 | def convertBST(self, root: TreeNode) -> TreeNode: 9 | def dfs(root): 10 | nonlocal sumval 11 | if root: 12 | dfs(root.right) 13 | sumval += root.val 14 | root.val = sumval # 将BST转化成累加树 15 | dfs(root.left) 16 | 17 | sumval = 0 18 | dfs(root) 19 | return root -------------------------------------------------------------------------------- /solutions/0540-Single-Element-in-a-Sorted-Array/0540.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def singleNonDuplicate(self, nums): 3 | """ 4 | :type nums: List[int] 5 | :rtype: int 6 | """ 7 | # solution one: binary search 8 | low, high = 0, len(nums) - 1 9 | while low < high: 10 | mid = int((low + high) / 2) # element in list must be int 11 | if mid % 2 == 1: # even position 12 | mid -= 1 13 | if nums[mid] != nums[mid + 1]: # result is on the left of mid 14 | high = mid 15 | else: 16 | low = mid + 2 17 | return nums[low] 18 | 19 | # # solution two: adjacent elements are equal 20 | # for i in range(0, len(nums) - 1, 2): # step = 2 21 | # if nums[i] != nums[i + 1]: 22 | # return nums[i] 23 | # return nums[-1] 24 | 25 | if __name__ == "__main__": 26 | nums = [1,1,2,3,3,4,4,8,8] 27 | print(Solution().singleNonDuplicate(nums)) -------------------------------------------------------------------------------- /solutions/0542-01-Matrix/0542.py: -------------------------------------------------------------------------------- 1 | import collections 2 | 3 | class Solution: 4 | def updateMatrix(self, matrix: List[List[int]]) -> List[List[int]]: 5 | # bfs: 不记录层数 6 | m, n = len(matrix), len(matrix[0]) 7 | q = collections.deque() 8 | res = [[None] * n for _ in range(m)] 9 | 10 | # 把所有 0 放入队列 11 | for i in range(m): 12 | for j in range(n): 13 | if matrix[i][j] == 0: 14 | q.append((i, j)) 15 | res[i][j] = 0 16 | 17 | dirs = [(0, 1), (0, -1), (1, 0), (-1, 0)] 18 | 19 | while q: 20 | x, y = q.popleft() 21 | for dx, dy in dirs: 22 | newx, newy = x + dx, y + dy 23 | if 0 <= newx < m and 0 <= newy < n and res[newx][newy] == None: # 当前为 1 24 | res[newx][newy] = res[x][y] + 1 25 | q.append((newx, newy)) 26 | return res -------------------------------------------------------------------------------- /solutions/0543-Diameter-of-Binary-Tree/0543.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def diameterOfBinaryTree(self, root: TreeNode) -> int: 10 | self.max = 0 11 | self.depth(root) 12 | return self.max 13 | 14 | def depth(self, root): 15 | if not root: 16 | return 0 17 | l = self.depth(root.left) 18 | r = self.depth(root.right) 19 | # 更新最大值 20 | self.max = max(self.max, l + r) 21 | # 返回高度 22 | return max(l, r) + 1 -------------------------------------------------------------------------------- /solutions/0547-Friend-Circles/0547.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def findCircleNum(self, M: List[List[int]]) -> int: 5 | m = len(M) 6 | ans, visited = 0, set() 7 | 8 | # def template 9 | def dfs(i): 10 | for j in range(m): 11 | if M[i][j] and j not in visited: # 1 and not visited 12 | visited.add(j) 13 | dfs(j) 14 | 15 | for i in range(m): 16 | if i not in visited: # not visited 17 | dfs(i) 18 | ans += 1 19 | return ans 20 | 21 | if __name__ == "__main__": 22 | M = [[1,1,0], 23 | [1,1,0], 24 | [0,0,1]] 25 | print(Solution().findCircleNum(M)) -------------------------------------------------------------------------------- /solutions/0559-Maximum-Depth-of-N-ary-Tree/0559.py: -------------------------------------------------------------------------------- 1 | """ 2 | # Definition for a Node. 3 | class Node: 4 | def __init__(self, val=None, children=None): 5 | self.val = val 6 | self.children = children 7 | """ 8 | 9 | class Solution: 10 | def maxDepth(self, root: 'Node') -> int: 11 | # DFS 12 | if not root: 13 | return 0 14 | depth = 0 15 | for child in root.children: 16 | depth = max(self.maxDepth(child), depth) 17 | return depth + 1 18 | 19 | # BFS 20 | import collections 21 | # 特判,不写会报错 22 | if not root: 23 | return 0 24 | 25 | q = collections.deque() 26 | q.append(root) 27 | depth = 0 28 | while q: 29 | for _ in range(len(q)): 30 | node = q.popleft() 31 | for child in node.children: 32 | q.append(child) 33 | depth += 1 34 | return depth -------------------------------------------------------------------------------- /solutions/0563-Binary-Tree-Tilt/0563.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | class Solution: 8 | def findTilt(self, root: TreeNode) -> int: 9 | # 后序遍历 10 | def dfs(root): 11 | nonlocal res 12 | if not root: 13 | return 0 14 | # if root.left: 15 | left = dfs(root.left) 16 | # if root.right: 17 | right = dfs(root.right) 18 | res += abs(left - right) 19 | return root.val + left + right 20 | 21 | res = 0 22 | dfs(root) 23 | return res -------------------------------------------------------------------------------- /solutions/0589-N-ary-Tree-Preorder-Traversal/0589.py: -------------------------------------------------------------------------------- 1 | """ 2 | # Definition for a Node. 3 | class Node: 4 | def __init__(self, val=None, children=None): 5 | self.val = val 6 | self.children = children 7 | """ 8 | 9 | class Solution: 10 | def preorder(self, root: 'Node') -> List[int]: 11 | # DFS 12 | res = [] 13 | def dfs(root): 14 | if not root: 15 | return 16 | res.append(root.val) 17 | for child in root.children: 18 | dfs(child) 19 | 20 | dfs(root) 21 | return res 22 | 23 | # BFS 24 | if not root: 25 | return [] 26 | 27 | q = [root] 28 | res = [] 29 | while q: 30 | # 弹出列表尾部的一个元素 31 | node = q.pop() 32 | res.append(node.val) 33 | # 逆序加入,从右到左 34 | for child in node.children[::-1]: 35 | q.append(child) 36 | return res -------------------------------------------------------------------------------- /solutions/0590-N-ary-Tree-Postorder-Traversal/0590.py: -------------------------------------------------------------------------------- 1 | """ 2 | # Definition for a Node. 3 | class Node: 4 | def __init__(self, val=None, children=None): 5 | self.val = val 6 | self.children = children 7 | """ 8 | 9 | class Solution: 10 | def postorder(self, root: 'Node') -> List[int]: 11 | # DFS 12 | res = [] 13 | def dfs(root): 14 | if not root: 15 | return 16 | for child in root.children: 17 | dfs(child) 18 | res.append(root.val) 19 | 20 | dfs(root) 21 | return res 22 | 23 | # BFS 24 | if not root: 25 | return [] 26 | 27 | q = [root] 28 | res = [] 29 | while q: 30 | # 弹出列表尾部的一个元素 31 | node = q.pop() 32 | res.append(node.val) 33 | # 顺序加入 34 | for child in node.children: 35 | q.append(child) 36 | return res[::-1] -------------------------------------------------------------------------------- /solutions/0605-Can-Place-Flowers/0605.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def canPlaceFlowers(self, flowerbed, n): 3 | """ 4 | :type flowerbed: List[int] 5 | :type n: int 6 | :rtype: bool 7 | """ 8 | if not flowerbed or len(flowerbed) == 0: 9 | return False 10 | cnt = 0 11 | for plot in range(len(flowerbed)): # range:0 - len(flowerbed)-1 12 | if flowerbed[plot] == 1: # already planted flower 13 | continue 14 | if plot > 0 and flowerbed[plot-1] == 1: # left planted flower 15 | continue 16 | if plot < len(flowerbed) - 1 and flowerbed[plot + 1] == 1: # right planted flower 17 | continue 18 | flowerbed[plot] = 1 19 | cnt += 1 20 | if cnt >= n: 21 | return True 22 | else: 23 | return False 24 | 25 | if __name__ == "__main__": 26 | flowerbed = [1,0,0,0,1] 27 | # flowerbed = [1,0,0,0,1,0,0] 28 | n = 1 29 | print(Solution().canPlaceFlowers(flowerbed, n)) -------------------------------------------------------------------------------- /solutions/0606-Construct-String-from-Binary-Tree/0606.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def tree2str(self, t: TreeNode) -> str: 10 | def dfs(root): 11 | if not root: 12 | return '' 13 | # 左子树为空右子树不为空,要加一个() 14 | if not root.left and root.right: 15 | return str(root.val) + '()' + '(' + dfs(root.right) + ')' 16 | # 左子树不为空右子树为空 17 | elif root.left and not root.right: 18 | return str(root.val) + '(' + dfs(root.left) + ')' 19 | # 左右子树都为空 20 | elif not root.left and not root.right: 21 | return str(root.val) 22 | return str(root.val) + '(' + dfs(root.left) + ')' + '(' + dfs(root.right) + ')' 23 | 24 | return dfs(t) -------------------------------------------------------------------------------- /solutions/0623-Add-One-Row-to-Tree/0623.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def addOneRow(self, root: TreeNode, v: int, d: int) -> TreeNode: 10 | if not root: 11 | return 12 | 13 | # 将原先整棵树作为 v 的左子树 14 | if d == 1: 15 | node = TreeNode(v) 16 | node.left = root 17 | return node 18 | 19 | if d == 2: 20 | # 新左节点 21 | L = TreeNode(v) 22 | # 新右节点 23 | R = TreeNode(v) 24 | 25 | L.left = root.left 26 | R.right = root.right 27 | 28 | root.left = L 29 | root.right = R 30 | return root 31 | 32 | # d > 2 不断分解 33 | self.addOneRow(root.left, v, d - 1) 34 | self.addOneRow(root.right, v, d - 1) 35 | return root -------------------------------------------------------------------------------- /solutions/0633-Sum-of-Square-Numbers/0633.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def judgeSquareSum(self, c): 3 | """ 4 | :type c: int 5 | :rtype: bool 6 | """ 7 | a = 0 8 | b = int(c**0.5)+1 9 | while a <= b: # 假如 c = 2, 发现不加 = , 输出 False, 应该输出 True 10 | if a*a + b*b == c: 11 | return True 12 | elif a*a + b*b < c: 13 | a += 1 14 | else: 15 | b -= 1 16 | return False 17 | 18 | if __name__ == "__main__": 19 | c = 5 20 | print(Solution().judgeSquareSum(c)) -------------------------------------------------------------------------------- /solutions/0647-Palindromic-Substrings/0647.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def countSubstrings(self, s: str) -> int: 3 | # solution one: 中心拓展 4 | n = len(s) 5 | ans = 0 6 | for i in range(2 * n - 1): 7 | left, right = int(i / 2), int(i / 2) + i % 2 8 | while left >= 0 and right < n and s[left] == s[right]: 9 | left -= 1 # 往左移 10 | right += 1 # 往右移 11 | ans += 1 12 | return ans 13 | 14 | # solution two: 动态规划 15 | if s is None or s == "": 16 | return 0 17 | 18 | n = len(s) 19 | dp = [[False for _ in range(n)] for _ in range(n)] 20 | res = len(s) 21 | 22 | for i in range(n): 23 | # base case 24 | dp[i][i] = True 25 | # 从左下方往上遍历 26 | for i in range(n - 1, -1, -1): 27 | for j in range(i + 1, n): 28 | if s[i] == s[j]: 29 | # i和j相邻,即回文子串长度为2 30 | if j - i == 1: 31 | dp[i][j] = True 32 | # 除去左右两头,剩下的substring是不是回文子串 33 | else: 34 | dp[i][j] = dp[i + 1][j - 1] 35 | # 不相等就不是回文子串 36 | else: 37 | dp[i][j] = False 38 | if dp[i][j]: 39 | res += 1 40 | return res 41 | 42 | if __name__ == "__main__": 43 | s = "aaa" 44 | print(Solution().countSubstrings(s)) -------------------------------------------------------------------------------- /solutions/0652-Find-Duplicate-Subtrees/0652.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | class Solution: 8 | def findDuplicateSubtrees(self, root: TreeNode) -> List[TreeNode]: 9 | import collections 10 | res = [] 11 | counter = collections.Counter() 12 | 13 | def traverse(root): 14 | if not root: 15 | return '#' 16 | # 后序遍历 17 | left = traverse(root.left) 18 | right = traverse(root.right) 19 | chain = left + ',' + right + ',' + str(root.val) 20 | counter[chain] += 1 21 | # 统计出现两次即是重复子树,加入res 22 | if counter[chain] == 2: 23 | res.append(root) 24 | return chain 25 | 26 | traverse(root) 27 | return res -------------------------------------------------------------------------------- /solutions/0653-Two-Sum-IV-Input-is-a-BST/0653.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | class Solution: 8 | def findTarget(self, root: TreeNode, k: int) -> bool: 9 | # 中序遍历是递增序列 10 | def inorder(root): 11 | if not root: 12 | return [] 13 | return inorder(root.left) + [root.val] + inorder(root.right) 14 | 15 | val = inorder(root) 16 | # 双指针 17 | left, right = 0, len(val) - 1 18 | while left < right: 19 | sumVal = val[left] + val[right] 20 | if sumVal == k: 21 | return True 22 | elif sumVal > k: 23 | right -= 1 24 | else: 25 | left += 1 26 | return False -------------------------------------------------------------------------------- /solutions/0654-Maximum-Binary-Tree/0654.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def constructMaximumBinaryTree(self, nums: List[int]) -> TreeNode: 10 | # 特判 11 | if not nums: 12 | return None 13 | 14 | # 找到数组中的最大值和对应的索引 15 | maxVal = max(nums) 16 | maxIndex = nums.index(maxVal) 17 | 18 | root = TreeNode(nums[maxIndex]) 19 | # 递归构造左右子树 20 | root.left = self.constructMaximumBinaryTree(nums[:maxIndex]) 21 | root.right = self.constructMaximumBinaryTree(nums[maxIndex + 1:]) 22 | 23 | return root -------------------------------------------------------------------------------- /solutions/0655-Print-Binary-Tree/0655.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def printTree(self, root: TreeNode) -> List[List[str]]: 10 | # 求最大深度 11 | def maxDepth(root): 12 | if not root: 13 | return 0 14 | left = maxDepth(root.left) 15 | right = maxDepth(root.right) 16 | return 1 + max(left, right) 17 | 18 | depth = maxDepth(root) 19 | # 二维矩阵宽度 20 | wid = 2**depth - 1 21 | res = [[''] * wid for _ in range(depth)] 22 | 23 | # DFS 24 | def dfs(root, depth, start, end): 25 | # 当前根节点放在(start+end)/2这个中间位置 26 | res[depth - 1][(start + end) // 2] = str(root.val) 27 | if root.left: 28 | dfs(root.left, depth + 1, start, (start + end) // 2) 29 | if root.right: 30 | dfs(root.right, depth + 1, (start + end) // 2, end) 31 | 32 | dfs(root, 1, 0, wid) 33 | return res -------------------------------------------------------------------------------- /solutions/0657-Robot-Return-to-Origin/0657.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def judgeCircle(self, moves: str) -> bool: 3 | # solution one:模拟 4 | n = len(moves) 5 | left, right, up, down = 0, 0, 0, 0 6 | for i in range(n): 7 | if moves[i] == 'L': 8 | left += 1 9 | elif moves[i] == 'R': 10 | right += 1 11 | elif moves[i] == 'U': 12 | up += 1 13 | else: 14 | down += 1 15 | if left == right and up == down: 16 | return True 17 | else: 18 | return False 19 | 20 | # solution two:数学 21 | import collections 22 | c = Counter(moves) 23 | return c["U"] == c["D"] and c["L"] == c["R"] 24 | 25 | # solution three:数学 26 | return moves.count("U") == moves.count("D") and moves.count("L") == moves.count("R") -------------------------------------------------------------------------------- /solutions/0662-Maximum-Width-of-Binary-Tree/0662.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | class Solution: 8 | def widthOfBinaryTree(self, root: TreeNode) -> int: 9 | if not root: 10 | return 0 11 | # 分别是坐标和节点 12 | queue = [(0, root)] 13 | res = 1 14 | # BFS 15 | while queue: 16 | # 首末元素的坐标差就是最大宽度 17 | res = max(res, queue[-1][0] - queue[0][0] + 1) 18 | tmp = [] 19 | for i, q in queue: 20 | if q.left: 21 | tmp.append((i * 2, q.left)) 22 | if q.right: 23 | tmp.append((i * 2 + 1, q.right)) 24 | queue = tmp 25 | return res -------------------------------------------------------------------------------- /solutions/0665-Non-decreasing-Array/0665.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def checkPossibility(self, nums): 3 | """ 4 | :type nums: List[int] 5 | :rtype: bool 6 | """ 7 | # # solution one 8 | # if len(nums) <= 2: 9 | # return True 10 | # nums1, nums2= nums[:], nums[:] 11 | # for i in range(len(nums)-1): 12 | # if nums[i] > nums[i+1]: 13 | # nums1[i] = nums[i+1] # change bigger 14 | # nums2[i+1] = nums[i] # change smaller 15 | # break # only change once, then break 16 | # return nums1 == sorted(nums1) or nums2 == sorted(nums2) 17 | 18 | # solution two 19 | if len(nums) <= 2: 20 | return True 21 | cnt = 0 22 | for i in range(1, len(nums)): 23 | if nums[i-1] > nums[i]: 24 | cnt += 1 25 | if i == 1 or nums[i-2] <= nums[i]: # 3,5,4 -> 3,4,4 26 | nums[i-1] = nums[i] 27 | else: # 4,5,4 -> 4,5,5 28 | nums[i] = nums[i-1] 29 | if cnt > 1: 30 | return False 31 | return True 32 | 33 | if __name__ == "__main__": 34 | nums = [4,2,1] 35 | print(Solution().checkPossibility(nums)) -------------------------------------------------------------------------------- /solutions/0669-Trim-a-Binary-Search-Tree/0669.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | class Solution: 8 | def trimBST(self, root: TreeNode, low: int, high: int) -> TreeNode: 9 | if not root: 10 | return 11 | # 只需考虑根节点需要做什么,其他的交给递归 12 | # 左边的全部小于low,所以都剪枝 13 | if root.val < low: 14 | root = root.right 15 | root = self.trimBST(root, low, high) 16 | # 右边的全部大于high,所以都剪枝 17 | elif root.val > high: 18 | root = root.left 19 | root = self.trimBST(root, low, high) 20 | else: 21 | root.left = self.trimBST(root.left, low, high) 22 | root.right = self.trimBST(root.right, low, high) 23 | return root -------------------------------------------------------------------------------- /solutions/0671-Second-Minimum-Node-In-a-Binary-Tree/0671.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | class Solution: 8 | def findSecondMinimumValue(self, root: TreeNode) -> int: 9 | if not root: 10 | return -1 11 | 12 | def dfs(root, val): 13 | if not root: 14 | return -1 15 | # 根据题意,最小元素一定是根节点,所以只要找到比根节点大的节点就行 16 | if root.val > val: 17 | return root.val 18 | left = dfs(root.left, val) 19 | right = dfs(root.right, val) 20 | if left == -1: 21 | return right 22 | if right == -1: 23 | return left 24 | return min(left, right) 25 | 26 | return dfs(root, root.val) -------------------------------------------------------------------------------- /solutions/0680-Valid-Palindrome-II/0680.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def validPalindrome(self, s): 3 | """ 4 | :type s: str 5 | :rtype: bool 6 | """ 7 | left, right = 0, len(s)-1 # 同时赋值 8 | while left <= right: 9 | if s[left] == s[right]: 10 | left += 1 11 | right -= 1 12 | else: 13 | temp1 = s[:left] + s[left+1:] # 删掉 s[left] 后的字符, 即字符串拼接: s[0] 到 s[left-1] + s[left+1] 到 s[len(s)-1] 14 | temp2 = s[:right] + s[right+1:] 15 | if temp1 == temp1[::-1] or temp2 == temp2[::-1]: # 判断删掉 s[left] 或者删掉 s[right], s是否为回文, [::-1]是从尾到头逆序遍历 16 | return True 17 | else: 18 | return False 19 | return True 20 | 21 | if __name__ == "__main__": 22 | str = "abca" 23 | print(Solution().validPalindrome(str)) -------------------------------------------------------------------------------- /solutions/0695-Max-Area-of-Island/0695.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def maxAreaOfIsland(self, grid: List[List[int]]) -> int: 5 | self.ans = 0 6 | self.island = 0 7 | m, n = len(grid), len(grid[0]) 8 | for i in range(m): 9 | for j in range(n): 10 | if grid[i][j]: # 1: island 11 | self.dfs(grid, i, j) 12 | self.ans = max(self.ans, self.island) 13 | self.island = 0 14 | return self.ans 15 | 16 | # dfs template 17 | def dfs(self, grid, i, j): 18 | m, n = len(grid), len(grid[0]) 19 | grid[i][j] = 0 20 | self.island += 1 21 | directions = [(0, 1), (0, -1), (-1, 0), (1, 0)] 22 | for direction in directions: 23 | x, y = i + direction[0], j + direction[1] 24 | if 0 <= x < m and 0 <= y < n and grid[x][y]: 25 | self.dfs(grid, x, y) 26 | 27 | if __name__ == "__main__": 28 | grid = [[0,0,1,0,0,0,0,1,0,0,0,0,0], 29 | [0,0,0,0,0,0,0,1,1,1,0,0,0], 30 | [0,1,1,0,1,0,0,0,0,0,0,0,0], 31 | [0,1,0,0,1,1,0,0,1,0,1,0,0], 32 | [0,1,0,0,1,1,0,0,1,1,1,0,0], 33 | [0,0,0,0,0,0,0,0,0,0,1,0,0], 34 | [0,0,0,0,0,0,0,1,1,1,0,0,0], 35 | [0,0,0,0,0,0,0,1,1,0,0,0,0]] 36 | print(Solution().maxAreaOfIsland(grid)) -------------------------------------------------------------------------------- /solutions/0700-Search-in-a-Binary-Search-Tree/0700.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def searchBST(self, root: TreeNode, val: int) -> TreeNode: 10 | # 节点不存在 11 | if not root: 12 | return None 13 | if root.val == val: 14 | return root 15 | if root.val < val: 16 | return self.searchBST(root.right, val) 17 | if root.val > val: 18 | return self.searchBST(root.left, val) -------------------------------------------------------------------------------- /solutions/0701-Insert-into-a-Binary-Search-Tree/0701.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | class Solution: 8 | def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode: 9 | # 找到空位置 10 | if not root: 11 | return TreeNode(val) 12 | if root.val < val: 13 | root.right = self.insertIntoBST(root.right, val) 14 | if root.val > val: 15 | root.left = self.insertIntoBST(root.left, val) 16 | return root -------------------------------------------------------------------------------- /solutions/0702-search-in-a-sorted-array-of-unknown-size/0702.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wonz5130/LeetCode-Solutions/a67809dac5939936b3c85829ac9991936e672229/solutions/0702-search-in-a-sorted-array-of-unknown-size/0702.pdf -------------------------------------------------------------------------------- /solutions/0702-search-in-a-sorted-array-of-unknown-size/0702.py: -------------------------------------------------------------------------------- 1 | # """ 2 | # This is ArrayReader's API interface. 3 | # You should not implement it, or speculate about its implementation 4 | # """ 5 | #class ArrayReader: 6 | # def get(self, index: int) -> int: 7 | 8 | class Solution: 9 | def search(self, reader: 'ArrayReader', target: int) -> int: 10 | if reader.get(0) == target: 11 | return 0 12 | 13 | left, right = 0, 1 14 | while reader.get(right) < target: 15 | left = right 16 | right <<= 1 17 | 18 | while left <= right: 19 | pivot = (left + right) >> 1 20 | num = reader.get(pivot) 21 | if num == target: 22 | return pivot 23 | elif num > target: 24 | right = pivot - 1 25 | else: 26 | left = pivot + 1 27 | return -1 -------------------------------------------------------------------------------- /solutions/0704-binary-search/0704.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def search(self, nums: List[int], target: int) -> int: 3 | left, right = 0, len(nums) - 1 4 | while left <= right: 5 | pivot = (left + right) >> 1 6 | if nums[pivot] == target: 7 | return pivot 8 | elif nums[pivot] > target: 9 | right = pivot - 1 10 | else: 11 | left = pivot + 1 12 | return -1 -------------------------------------------------------------------------------- /solutions/0714-Best-Time-to-Buy-and-Sell-Stock-with-Transaction-Fee/0714.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def maxProfit(self, prices: List[int], fee: int) -> int: 5 | dp_i_0 = 0 6 | dp_i_1 = float('-inf') # 负无穷 7 | for i in range(len(prices)): 8 | temp = dp_i_0 9 | # 昨天没有股票,昨天有股票今天卖出,同时减去交易费用 10 | dp_i_0 = max(dp_i_0, dp_i_1 + prices[i] - fee) # dp_i_0 和 dp_i_1 可以看成是变量,存储的都是上一次即昨天的值 11 | # 昨天有股票,昨天没有股票今天买入 12 | dp_i_1 = max(dp_i_1, temp - prices[i]) 13 | return dp_i_0 14 | 15 | if __name__ == "__main__": 16 | prices = [1, 3, 2, 8, 4, 9] 17 | fee = 2 18 | print(Solution().maxProfit(prices, fee)) -------------------------------------------------------------------------------- /solutions/0744-Find-Smallest-Letter-Greater-Than-Target/0744.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def nextGreatestLetter(self, letters, target): 3 | """ 4 | :type letters: List[str] 5 | :type target: str 6 | :rtype: str 7 | """ 8 | low, high = 0, len(letters) - 1 9 | while low <= high: 10 | mid = int((low + high) / 2) # element in list must be int 11 | if letters[mid] <= target: 12 | low = mid + 1 13 | else: 14 | if mid < 1 or (mid >= 1 and letters[mid-1] <= target): 15 | return letters[mid] 16 | high = mid - 1 17 | return letters[0] # 'z' < 'a' 18 | 19 | if __name__ == "__main__": 20 | letters = ["c", "f", "j"] 21 | target = "a" 22 | print(Solution().nextGreatestLetter(letters, target)) -------------------------------------------------------------------------------- /solutions/0783-Minimum-Distance-Between-BST-Nodes/0783.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def minDiffInBST(self, root: TreeNode) -> int: 10 | # solution one: dfs遍历取节点值,再单独计算最小绝对差 11 | def dfs(root): 12 | if not root: 13 | return 14 | # 中序遍历是递增的 15 | if root.left: 16 | dfs(root.left) 17 | tmp_val.append(root.val) 18 | if root.right: 19 | dfs(root.right) 20 | tmp_val = [] 21 | dfs(root) 22 | res = float("inf") 23 | for i in range(len(tmp_val) - 1): 24 | res = min(res, abs(tmp_val[i] - tmp_val[i + 1])) 25 | return res 26 | 27 | # solution two: dfs遍历直接进行绝对值比较 28 | pre = -1 29 | res = float("inf") 30 | def dfs(root): 31 | nonlocal pre, res 32 | if not root: 33 | return 34 | # 中序遍历是递增的 35 | if root.left: 36 | dfs(root.left) 37 | if pre != -1: 38 | res = min(res, abs(pre - root.val)) 39 | pre = root.val 40 | if root.right: 41 | dfs(root.right) 42 | dfs(root) 43 | return res -------------------------------------------------------------------------------- /solutions/0814-Binary-Tree-Pruning/0814.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | class Solution: 8 | def pruneTree(self, root: TreeNode) -> TreeNode: 9 | if not root: 10 | return None 11 | 12 | root.left = self.pruneTree(root.left) 13 | root.right = self.pruneTree(root.right) 14 | # 左右子树为空且当前根节点值为0 15 | if not root.left and not root.right and root.val == 0: 16 | return None 17 | return root -------------------------------------------------------------------------------- /solutions/0836-Rectangle-Overlap/0836.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def isRectangleOverlap(self, rec1: List[int], rec2: List[int]) -> bool: 3 | # 左下角取 max 4 | x1 = max(rec1[0], rec2[0]) 5 | y1 = max(rec1[1], rec2[1]) 6 | # 右上角取 min 7 | x2 = min(rec1[2], rec2[2]) 8 | y2 = min(rec1[3], rec2[3]) 9 | 10 | # 判断是否重叠 11 | if x1 < x2 and y1 < y2: 12 | return True 13 | else: 14 | return False -------------------------------------------------------------------------------- /solutions/0875-koko-eating-bananas/0875.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def minEatingSpeed(self, piles: List[int], h: int) -> int: 3 | left, right = 1, max(piles) 4 | 5 | def getTime(piles: List[int], speed: int) -> int: 6 | time = 0 7 | for pile in piles: 8 | time += (pile + speed - 1) // speed # 如果是用 >>,注意整除 2 是右移一位 9 | return time 10 | 11 | while left < right: 12 | speed = (left + right) >> 1 13 | time = getTime(piles, speed) 14 | if time <= h: 15 | right = speed 16 | else: 17 | left = speed + 1 18 | return left -------------------------------------------------------------------------------- /solutions/0876-Middle-of-the-Linked-List/0876.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.next = None 6 | 7 | class Solution: 8 | def middleNode(self, head: ListNode) -> ListNode: 9 | if not head: 10 | return None 11 | 12 | # 快慢指针 13 | slow, fast = head, head 14 | while fast and fast.next: 15 | slow = slow.next 16 | fast = fast.next.next 17 | return slow -------------------------------------------------------------------------------- /solutions/0892-Surface-Area-of-3D-Shapes/0892.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def surfaceArea(self, grid: List[List[int]]) -> int: 3 | n = len(grid) 4 | cubes, faces = 0, 0 5 | for i in range(n): 6 | for j in range(n): 7 | cubes += grid[i][j] 8 | if grid[i][j] > 0: 9 | # 叠起来的 v 个立方体有 v-1 个接触面 10 | faces += grid[i][j] - 1 11 | if i > 0: 12 | # 当前柱子与上边柱子的接触面数量 13 | faces += min(grid[i-1][j], grid[i][j]) 14 | if j > 0: 15 | # 当前柱子与左边柱子的接触面数量 16 | faces += min(grid[i][j-1], grid[i][j]) 17 | return 6 * cubes - 2 * faces -------------------------------------------------------------------------------- /solutions/0914-X-of-a-Kind-in-a-Deck-of-Cards/0914.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import collections 3 | import math 4 | 5 | class Solution: 6 | def hasGroupsSizeX(self, deck: List[int]) -> bool: 7 | # Counter统计出来是一个字典 8 | c = list(collections.Counter(deck).values()) 9 | res = c[0] 10 | # 求所有数的最大公约数 11 | for x in c: 12 | res = math.gcd(res, x) 13 | return res > 1 14 | 15 | if __name__ == "__main__": 16 | deck = [1,2,3,4,4,3,2,1] 17 | print(Solution().hasGroupsSizeX(deck)) -------------------------------------------------------------------------------- /solutions/0994-Rotting-Oranges/0994.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def orangesRotting(self, grid: List[List[int]]) -> int: 5 | n, m = len(grid), len(grid[0]) 6 | fresh = 0 7 | q = [] 8 | 9 | # count fresh oranges and enqueue rotten oranges 10 | for i in range(n): 11 | for j in range(m): 12 | if grid[i][j] == 1: 13 | fresh += 1 14 | elif grid[i][j] == 2: 15 | q.append((i, j)) 16 | 17 | if fresh == 0: 18 | return 0 19 | dirs = [(0, 1), (0, -1), (-1, 0), (1, 0)] 20 | minute = 0 21 | 22 | # bfs 23 | while q: 24 | if fresh == 0: 25 | return minute 26 | 27 | size = len(q) 28 | for i in range(size): 29 | x, y = q.pop(0) 30 | for d in dirs: 31 | nx, ny = x + d[0], y + d[1] 32 | if nx < 0 or nx >= n or ny < 0 or ny >= m or grid[nx][ny] != 1: 33 | continue 34 | grid[nx][ny] = 2 35 | q.append((nx, ny)) 36 | fresh -= 1 37 | minute += 1 38 | 39 | if fresh != 0: 40 | return -1 41 | 42 | if __name__ == "__main__": 43 | grid = [[2,1,1],[1,1,0],[0,1,1]] 44 | print(Solution().orangesRotting(grid)) -------------------------------------------------------------------------------- /solutions/1013-Partition-Array-Into-Three-Parts-With-Equal-Sum/1013.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def canThreePartsEqualSum(self, A: List[int]) -> bool: 5 | sum = 0 6 | for x in A: 7 | sum += x 8 | # 和不能被3整除,肯定不符合 9 | if sum % 3: 10 | return False 11 | 12 | left, right = 0, len(A)-1 13 | leftSum, rightSum = A[left], A[right] 14 | 15 | # left + 1 < right: 防止将数组只分成两部分,中间部分至少要有一个元素 16 | while left + 1 < right: 17 | # 左右都等于sum/3,中间肯定等于sum/3 18 | if leftSum == sum/3 and rightSum == sum/3: 19 | return True 20 | if leftSum != sum/3: 21 | left += 1 22 | leftSum += A[left] 23 | if rightSum != sum/3: 24 | right -= 1 25 | rightSum += A[right] 26 | return False 27 | 28 | if __name__ == "__main__": 29 | A = [0,2,1,-6,6,-7,9,1,2,0,1] 30 | print(Solution().canThreePartsEqualSum(A)) -------------------------------------------------------------------------------- /solutions/1038-Binary-Search-Tree-to-Greater-Sum-Tree/1038.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | class Solution: 8 | def bstToGst(self, root: TreeNode) -> TreeNode: 9 | def dfs(root): 10 | nonlocal sumval 11 | if root: 12 | dfs(root.right) 13 | sumval += root.val 14 | root.val = sumval # 将BST转化成累加树 15 | dfs(root.left) 16 | 17 | sumval = 0 18 | dfs(root) 19 | return root -------------------------------------------------------------------------------- /solutions/1071-Greatest-Common-Divisor-of-Strings/1071.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def gcdOfStrings(self, str1: str, str2: str) -> str: 3 | m, n = len(str1), len(str2) 4 | 5 | # solution one 6 | i, j = 0, 0 7 | while i < m or j < n: 8 | if str1[i % m] != str2[j % n]: 9 | return "" 10 | i += 1 11 | j += 1 12 | 13 | # 求最大公约数 14 | def gcd(a, b): 15 | return a if b == 0 else gcd(b, a % b) 16 | 17 | return str1[:gcd(m, n)] 18 | 19 | # solution two 20 | if str1 + str2 != str2 + str1: 21 | return "" 22 | 23 | # 求最大公约数 24 | def gcd(a, b): 25 | return a if b == 0 else gcd(b, a % b) 26 | 27 | return str1[:gcd(m, n)] 28 | 29 | if __name__ == "__main__": 30 | str1 = "ABCABC" 31 | str2 = "ABC" 32 | print(Solution().gcdOfStrings(str1, str2)) -------------------------------------------------------------------------------- /solutions/1091-Shortest-Path-in-Binary-Matrix/1091.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def shortestPathBinaryMatrix(self, grid: List[List[int]]) -> int: 5 | if grid[0][0] == 1 or grid[-1][-1] == 1: # top-left is not empty or bottom-right is not empty 6 | return -1 7 | 8 | # eight directions: → ← ↓ ↑ ↗ ↙ ↖ ↘ 9 | directions = [[1, 0], [-1, 0], [0, -1], [0, 1], [1, 1], [1, -1], [-1, 1], [-1, -1]] 10 | 11 | queue = [(0, 0, 1)] # location, cnt 12 | n = len(grid) 13 | 14 | # BFS 15 | while len(queue): 16 | x0, y0, cnt = queue.pop(0) # pop (location, cnt) 17 | if x0 == n - 1 and y0 == n - 1: # already arrive at bottom-right 18 | return cnt 19 | 20 | # eight directions 21 | for i, j in directions: 22 | x, y = x0 + i, y0 + j 23 | # (x, y) is in the grid and grid[x][y] = 0, also means: grid[x][y] is not visited 24 | if 0 <= x < n and 0 <= y < n and not grid[x][y]: 25 | queue.append((x, y, cnt + 1)) 26 | grid[x][y] = 1 # visited 27 | 28 | return -1 29 | 30 | if __name__ == "__main__": 31 | grid = [[0,0,0],[1,1,0],[1,1,0]] 32 | print(Solution().shortestPathBinaryMatrix(grid)) -------------------------------------------------------------------------------- /solutions/1103-Distribute-Candies-to-People/1103.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def distributeCandies(self, candies: int, num_people: int) -> List[int]: 5 | res = [0] * num_people 6 | step = 0 7 | while candies > 0: 8 | res[step % num_people] += min(candies, step + 1) 9 | step += 1 # next person 10 | candies -= step # the remaining candies 11 | return res 12 | 13 | if __name__ == "__main__": 14 | candies = 7 15 | num_people = 4 16 | print(Solution().distributeCandies(candies, num_people)) -------------------------------------------------------------------------------- /solutions/1160-Find-Words-That-Can-Be-Formed-by-Characters/1160.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def countCharacters(self, words: List[str], chars: str) -> int: 5 | # solution one 6 | import collections 7 | res = 0 8 | cnt = collections.Counter(chars) 9 | for word in words: 10 | c = collections.Counter(word) 11 | if all([c[i] <= cnt[i] for i in c]): 12 | res += len(word) 13 | return res 14 | 15 | # solution two 16 | res = 0 17 | for word in words: 18 | n = len(word) 19 | cnt = 0 20 | for i in word: 21 | # word 中字符 i 个数 <= chars 中字符 i 个数 22 | if word.count(i) <= chars.count(i): 23 | cnt += 1 24 | else: 25 | break 26 | # word 可以由 chars 拼出 27 | if cnt == n: 28 | res += cnt 29 | return res 30 | 31 | if __name__ == "__main__": 32 | words = ["cat","bt","hat","tree"] 33 | chars = "atach" 34 | print(Solution().countCharacters(words, chars)) -------------------------------------------------------------------------------- /solutions/1283-find-the-smallest-divisor-given-a-threshold/1283.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def smallestDivisor(self, nums: List[int], threshold: int) -> int: 3 | left, right = 1, max(nums) 4 | 5 | def getSum(nums: List[int], mid: int) -> int: 6 | tmp_sum = 0 7 | for num in nums: 8 | tmp_sum += (num + mid - 1) // mid 9 | return tmp_sum 10 | 11 | while left < right: 12 | mid = (left + right) >> 1 13 | tmp_sum = getSum(nums, mid) 14 | if tmp_sum <= threshold: 15 | right = mid 16 | else: 17 | left = mid + 1 18 | return left -------------------------------------------------------------------------------- /solutions/1358-Number-of-Substrings-Containing-All-Three-Characters/1358.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def numberOfSubstrings(self, s: str) -> int: 3 | if len(s) <= 2: 4 | return 0 5 | length = len(s) 6 | left, right = 0, 2 7 | ans = 0 8 | while left < length - 2: 9 | window = s[left: right + 1] # [left, right + 1) 10 | if 'a' in window and 'b' in window and 'c' in window: 11 | ans += length - right # if s[left: right + 1] satisfies, then s[left: length] also satisfies 12 | left += 1 # move left 13 | else: 14 | right += 1 # move right 15 | if right == length: # s[left: length] does not satisfy, so s[left + x: length] also does not satisfy 16 | break 17 | return ans 18 | 19 | if __name__ == "__main__": 20 | s = "abcabc" 21 | print(Solution().numberOfSubstrings(s)) -------------------------------------------------------------------------------- /solutions/1362-Closest-Divisors/1362.py: -------------------------------------------------------------------------------- 1 | import math 2 | from typing import List 3 | 4 | class Solution: 5 | def closestDivisors(self, num: int) -> List[int]: 6 | num1, num2 = num + 1, num + 2 7 | ans1 = self.crack(num1) 8 | ans2 = self.crack(num2) 9 | res = [] 10 | if abs(ans1 - int(num1 / ans1)) < abs(ans2 - int(num2 / ans2)): # int 11 | res.append(ans1) 12 | res.append(int(num1 / ans1)) 13 | return res 14 | else: 15 | res.append(ans2) 16 | res.append(int(num2 / ans2)) 17 | return res 18 | 19 | # calculate factor 20 | def crack(self, integer): 21 | factor1, factor2 = 1, integer 22 | for i in range(1, int(math.sqrt(integer)) + 1): # range: [1, sqrt(x) + 1) 23 | if int(integer / i) == integer / i: # i is factor 24 | if integer / i - i < factor2 - factor1: 25 | factor1, factor2 = i, integer / i 26 | return factor1 27 | 28 | if __name__ == "__main__": 29 | num = 123 30 | print(Solution().closestDivisors(num)) -------------------------------------------------------------------------------- /solutions/1365-How-Many-Numbers-Are-Smaller-Than-the-Current-Number/1365.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def smallerNumbersThanCurrent(self, nums: List[int]) -> List[int]: 5 | n = len(nums) 6 | ans = [] 7 | for i in range(n): 8 | cnt = 0 9 | for j in range(n): 10 | if nums[j] < nums[i]: 11 | cnt += 1 12 | ans.append(cnt) 13 | return ans 14 | 15 | if __name__ == "__main__": 16 | nums = [8,1,2,2,3] 17 | print(Solution().smallerNumbersThanCurrent(nums)) -------------------------------------------------------------------------------- /solutions/1366-Rank-Teams-by-Votes/1366.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def rankTeams(self, votes: List[str]) -> str: 5 | n = len(votes[0]) 6 | # create score[26][n+1] 7 | score = [[0 for i in range(n+1)] for x in range(26)] 8 | for vote in votes: 9 | for i, v in enumerate(vote): 10 | score[ord(v) - ord("A")][i] += 1 11 | score[ord(v) - ord("A")][-1] = ord("Z") - ord(v) + 1 # A:26 B:25 ··· sort based on it 12 | score.sort(reverse=True) 13 | ans = "" 14 | for i in range(26): 15 | if score[i][-1] != 0: 16 | ans += chr(26 - score[i][-1] + 65) # int to char 17 | return ans 18 | 19 | if __name__ == "__main__": 20 | votes = ["ABC","ACB","ABC","ACB","ACB"] 21 | # votes = ["M","M","M","M"] 22 | print(Solution().rankTeams(votes)) -------------------------------------------------------------------------------- /solutions/1367-Linked-List-in-Binary-Tree/1367.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.next = None 6 | 7 | # Definition for a binary tree node. 8 | # class TreeNode: 9 | # def __init__(self, x): 10 | # self.val = x 11 | # self.left = None 12 | # self.right = None 13 | 14 | class Solution: 15 | def isSubPath(self, head: ListNode, root: TreeNode) -> bool: 16 | if head == None: 17 | return True 18 | if root == None: 19 | return False 20 | # judge root, then judge root.left and root.right 21 | return self.isSub(head, root) or self.isSubPath(head, root.left) or self.isSubPath(head, root.right) 22 | 23 | def isSub(self, head, node): 24 | # list is over 25 | if head == None: 26 | return True 27 | # list is not over and tree is over 28 | if node == None: 29 | return False 30 | # not equal 31 | if not head.val == node.val: 32 | return False 33 | # equal, then left and right 34 | return self.isSub(head.next, node.left) or self.isSub(head.next, node.right) -------------------------------------------------------------------------------- /solutions/1370-Increasing-Decreasing-String/1370.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def sortString(self, s: str) -> str: 3 | if not s: 4 | return '' 5 | 6 | s = list(s) 7 | res = [] 8 | while s: 9 | # increasing: 递增 10 | temp_list = list(set(s)) # set可以去重 11 | temp_list.sort(key=lambda c: ord(c)) # ord():转化ASCII字符为相应的数字 12 | for i in temp_list: 13 | res.append(i) 14 | s.remove(i) 15 | 16 | # decreasing: 递减 17 | temp_list = list(set(s)) 18 | temp_list.sort(key=lambda c: ord(c), reverse=True) 19 | for i in temp_list: 20 | res.append(i) 21 | s.remove(i) 22 | return ''.join(res) 23 | 24 | if __name__ == "__main__": 25 | s = "aaaabbbbcccc" 26 | print(Solution().sortString(s)) -------------------------------------------------------------------------------- /solutions/1372-Longest-ZigZag-Path-in-a-Binary-Tree/1372.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def longestZigZag(self, root: TreeNode) -> int: 10 | if root == None: 11 | return 0 12 | self.max_ = 0 13 | self.dfs(root, 0, 0) 14 | return self.max_ 15 | 16 | def dfs(self, root, prev, depth): 17 | self.max_ = max(depth, self.max_) 18 | 19 | if root.left: 20 | # left->left 21 | if prev == 0: 22 | self.dfs(root.left, 0, 1) 23 | # left->right 24 | else: 25 | self.dfs(root.left, 0, depth + 1) 26 | if root.right: 27 | # right->right 28 | if prev == 1: 29 | self.dfs(root.right, 1, 1) 30 | # right->left 31 | else: 32 | self.dfs(root.right, 1, depth + 1) -------------------------------------------------------------------------------- /solutions/1374-Generate-a-String-With-Characters-That-Have-Odd-Counts/1374.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def generateTheString(self, n: int) -> str: 3 | res = [] 4 | if n % 2 == 0: 5 | for i in range(n-1): 6 | res.append('a') 7 | res.append('b') 8 | else: 9 | for i in range(n): 10 | res.append('a') 11 | return ''.join(res) 12 | 13 | if __name__ == "__main__": 14 | n = 4 15 | print(Solution().generateTheString(n)) -------------------------------------------------------------------------------- /solutions/1375-Bulb-Switcher-III/1375.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def numTimesAllBlue(self, light: List[int]) -> int: 5 | n = len(light) 6 | flag = [False] * (n+1) 7 | cnt_blue, cnt_light = 0, 0 8 | max_i = 0 9 | for i in range(n): 10 | flag[light[i]] = True # turn on bulb开灯 11 | cnt_light += 1 12 | max_i = max(max_i, light[i]) 13 | # 已开灯数量 = 当前记录的最大编号:灯变蓝计数 + 1 14 | if cnt_light == max_i: 15 | cnt_blue += 1 16 | return cnt_blue 17 | 18 | if __name__ == "__main__": 19 | light = [1,2,3,4,5,6] 20 | print(Solution().numTimesAllBlue(light)) -------------------------------------------------------------------------------- /solutions/1376-Time-Needed-to-Inform-All-Employees/1376.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def numOfMinutes(self, n: int, headID: int, manager: List[int], informTime: List[int]) -> int: 5 | res = 0 6 | for i in range(len(manager)): 7 | # 剪枝 8 | if informTime[i] == 0: 9 | temp = 0 10 | index = i 11 | # 自底向上遍历 12 | while index != -1: 13 | temp += informTime[index] 14 | index = manager[index] 15 | res = max(res, temp) 16 | return res 17 | 18 | if __name__ == "__main__": 19 | n = 6 20 | headID = 2 21 | manager = [2,2,-1,2,2,2] 22 | informTime = [0,0,1,0,0,0] 23 | print(Solution().numOfMinutes(n, headID, manager, informTime)) -------------------------------------------------------------------------------- /solutions/1380-Lucky-Numbers-in-a-Matrix/1380.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def luckyNumbers (self, matrix: List[List[int]]) -> List[int]: 5 | # solution one 6 | m, n = len(matrix), len(matrix[0]) 7 | flag = 0 8 | res = [] 9 | for i in range(m): 10 | min_ = max_ = matrix[i][0] 11 | for j in range(n): 12 | if matrix[i][j] < min_: 13 | flag = j 14 | min_ = matrix[i][j] 15 | max_ = min_ 16 | for x in range(m): 17 | if matrix[x][flag] > max_: 18 | break 19 | elif x == m - 1: 20 | res.append(max_) 21 | return res 22 | 23 | # solution two 24 | min_ = {min(rows) for rows in matrix} 25 | max_ = {max(columns) for columns in zip(*matrix)} # zip(*) 对矩阵进行转置,即找出每一列中的最大值 26 | return list(min_ & max_) 27 | 28 | if __name__ == "__main__": 29 | matrix = [[1,10,4,2],[9,3,8,7],[15,16,17,12]] 30 | print(Solution().luckyNumbers (matrix)) -------------------------------------------------------------------------------- /solutions/1381-Design-a-Stack-With-Increment-Operation/1381.py: -------------------------------------------------------------------------------- 1 | class CustomStack: 2 | 3 | def __init__(self, maxSize: int): 4 | self.size = 0 5 | self.maxSize = maxSize 6 | self.customStack = [] 7 | 8 | def push(self, x: int) -> None: 9 | if self.size < self.maxSize: 10 | self.customStack.append(x) 11 | self.size += 1 12 | 13 | def pop(self) -> int: 14 | if self.size == 0: 15 | return -1 16 | temp = self.customStack[self.size - 1] 17 | # 要把栈顶元素弹出去,即删除栈顶元素 18 | del self.customStack[self.size - 1] 19 | self.size -= 1 20 | return temp 21 | 22 | def increment(self, k: int, val: int) -> None: 23 | for i in range(min(k, self.size)): 24 | self.customStack[i] += val 25 | 26 | 27 | # Your CustomStack object will be instantiated and called as such: 28 | # obj = CustomStack(maxSize) 29 | # obj.push(x) 30 | # param_2 = obj.pop() 31 | # obj.increment(k,val) -------------------------------------------------------------------------------- /solutions/1382-Balance-a-Binary-Search-Tree/1382.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | from typing import List 9 | 10 | class Solution: 11 | def balanceBST(self, root: TreeNode) -> TreeNode: 12 | if not root: 13 | return 14 | return self.build(self.dfs(root)) 15 | 16 | # 二叉搜索树转数组 17 | def dfs(self, root): 18 | if not root: 19 | return [] 20 | return self.dfs(root.left) + [root.val] + self.dfs(root.right) 21 | 22 | # 数组二分构建平衡二叉树 23 | def build(self, nums: List[int]) -> TreeNode: 24 | if not nums: 25 | return None 26 | mid = len(nums) // 2 27 | node = TreeNode(nums[mid]) 28 | 29 | left = nums[:mid] 30 | right = nums[mid+1:] 31 | 32 | node.left = self.build(left) 33 | node.right = self.build(right) 34 | 35 | return node -------------------------------------------------------------------------------- /solutions/1385-Find-the-Distance-Value-Between-Two-Arrays/1385.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def findTheDistanceValue(self, arr1: List[int], arr2: List[int], d: int) -> int: 5 | # solution one: 暴力 6 | res = 0 7 | for x in arr1: 8 | cnt = 0 9 | for y in arr2: 10 | if abs(x-y) <= d: 11 | break 12 | else: 13 | cnt += 1 14 | if cnt == len(arr2): 15 | res += 1 16 | return res 17 | 18 | # solution two: 一行代码 19 | return sum(all(abs(a1 - a2) > d for a2 in arr2) for a1 in arr1) 20 | 21 | if __name__ == "__main__": 22 | arr1 = [-803,715,-224,909,121,-296,872,807,715,407,94,-8,572,90,-520,-867,485,-918,-827,-728,-653,-659,865,102,-564,-452,554,-320,229,36,722,-478,-247,-307,-304,-767,-404,-519,776,933,236,596,954,464] 23 | arr2 = [817,1,-723,187,128,577,-787,-344,-920,-168,-851,-222,773,614,-699,696,-744,-302,-766,259,203,601,896,-226,-844,168,126,-542,159,-833,950,-454,-253,824,-395,155,94,894,-766,-63,836,-433,-780,611,-907,695,-395,-975,256,373,-971,-813,-154,-765,691,812,617,-919,-616,-510,608,201,-138,-669,-764,-77,-658,394,-506,-675,523,730,-790,-109,865,975,-226,651,987,111,862,675,-398,126,-482,457,-24,-356,-795,-575,335,-350,-919,-945,-979,611] 24 | d = 37 25 | print(Solution().findTheDistanceValue(arr1, arr2, d)) -------------------------------------------------------------------------------- /solutions/1387-Sort-Integers-by-The-Power-Value/1387.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def getKth(self, lo: int, hi: int, k: int) -> int: 3 | nums, weight = [], [] 4 | for x in range(lo, hi + 1): 5 | nums.append(x) 6 | weight.append(self.step(x)) 7 | # 将两个列表合并成字典 8 | dic = dict(zip(nums, weight)) 9 | 10 | # 先根据权重排序,再根据数值排序 11 | res = sorted(dic.items(), key=lambda x: (x[1],x[0])) 12 | return res[k-1][0] 13 | 14 | def step(self, x): 15 | cnt = 0 16 | if x == 1: 17 | return cnt 18 | while x != 1: 19 | if x % 2: 20 | x = 3 * x + 1 21 | else: 22 | x = x / 2 23 | cnt += 1 24 | return cnt 25 | 26 | if __name__ == "__main__": 27 | lo = 12 28 | hi = 15 29 | k = 2 30 | print(Solution().getKth(lo, hi, k)) -------------------------------------------------------------------------------- /solutions/1389-Create-Target-Array-in-the-Given-Order/1389.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def createTargetArray(self, nums: List[int], index: List[int]) -> List[int]: 5 | target = [] 6 | for i in range(len(index)): 7 | target.insert(index[i], nums[i]) # insert(位置, 值) 8 | return target 9 | 10 | if __name__ == "__main__": 11 | nums = [0,1,2,3,4] 12 | index = [0,1,2,2,1] 13 | print(Solution().createTargetArray(nums, index)) -------------------------------------------------------------------------------- /solutions/1390-Four-Divisors/1390.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def sumFourDivisors(self, nums: List[int]) -> int: 5 | sum = 0 6 | for x in nums: 7 | if x == 1 or x == 2 or x == 3: 8 | continue 9 | num = 2 10 | temp = [1, x] 11 | # 计算因数 12 | while num ** 2 <= x: # 用 num^2 <= x 比 num <= sqrt(x) 好 13 | if len(temp) > 4: 14 | break 15 | if not x % num: 16 | if num not in temp: 17 | temp.append(num) 18 | if int(x/num) not in temp: 19 | temp.append(int(x/num)) 20 | num += 1 21 | # print(temp) 22 | if len(temp) == 4: 23 | for _ in temp: 24 | # print(_) 25 | sum += _ 26 | return int(sum) 27 | 28 | if __name__ == "__main__": 29 | nums = [21,4,7] 30 | print(Solution().sumFourDivisors(nums)) -------------------------------------------------------------------------------- /solutions/1394-Find-Lucky-Integer-in-an-Array/1394.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import collections 3 | 4 | class Solution: 5 | def findLucky(self, arr: List[int]) -> int: 6 | cnt = collections.Counter(arr) 7 | # 先按频次排序,再按数值大小排序 8 | res = sorted(cnt.items(), key=lambda x:(x[1],x[0]), reverse=True) 9 | for i in range(len(res)): 10 | # 频次等于数值大小 11 | if res[i][0] == res[i][1]: 12 | return res[i][0] 13 | return -1 14 | 15 | if __name__ == "__main__": 16 | arr = [2,2,3] 17 | print(Solution().findLucky(arr)) -------------------------------------------------------------------------------- /solutions/1395-Count-Number-of-Teams/1395.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def numTeams(self, rating: List[int]) -> int: 5 | n = len(rating) 6 | count = 0 7 | for i in range(n-2): 8 | for j in range(i+1, n-1): 9 | for k in range(j+1, n): 10 | if rating[i] < rating[j]: 11 | if rating[j] < rating[k]: 12 | count += 1 13 | elif rating[i] > rating[j]: 14 | if rating[j] > rating[k]: 15 | count += 1 16 | return count 17 | 18 | if __name__ == "__main__": 19 | rating = [2,5,3,4,1] 20 | print(Solution().numTeams(rating)) -------------------------------------------------------------------------------- /solutions/1396-Design-Underground-System/1396.py: -------------------------------------------------------------------------------- 1 | class UndergroundSystem: 2 | 3 | def __init__(self): 4 | self.enterstation = {} 5 | self.leavestation = {} 6 | 7 | def checkIn(self, id: int, stationName: str, t: int) -> None: 8 | if stationName not in self.enterstation: 9 | self.enterstation[stationName] = [[id, t]] 10 | else: 11 | self.enterstation[stationName].append([id, t]) 12 | 13 | def checkOut(self, id: int, stationName: str, t: int) -> None: 14 | if stationName not in self.leavestation: 15 | self.leavestation[stationName] = [[id, t]] 16 | else: 17 | self.leavestation[stationName].append([id, t]) 18 | 19 | def getAverageTime(self, startStation: str, endStation: str) -> float: 20 | res = [] 21 | start = self.enterstation[startStation] 22 | end = self.leavestation[endStation] 23 | for i in start: 24 | for j in end: 25 | # id相同 26 | if i[0] == j[0]: 27 | res.append(abs(j[1] - i[1])) 28 | return float(sum(res) / len(res)) 29 | 30 | 31 | # Your UndergroundSystem object will be instantiated and called as such: 32 | # obj = UndergroundSystem() 33 | # obj.checkIn(id,stationName,t) 34 | # obj.checkOut(id,stationName,t) 35 | # param_3 = obj.getAverageTime(startStation,endStation) -------------------------------------------------------------------------------- /solutions/1408-String-Matching-in-an-Array/1408.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import copy 3 | 4 | class Solution: 5 | def stringMatching(self, words: List[str]) -> List[str]: 6 | n = len(words) 7 | res = [] 8 | for i in range(n): 9 | temp = copy.deepcopy(words) 10 | temp.remove(words[i]) 11 | 12 | for j in range(n - 1): 13 | if words[i] in temp[j]: 14 | res.append(words[i]) 15 | return list(set(res)) 16 | 17 | if __name__ == "__main__": 18 | words = ["mass","as","hero","superhero"] 19 | # words = ["leetcoder","leetcode","od","hamlet","am"] 20 | print(Solution().stringMatching(words)) -------------------------------------------------------------------------------- /solutions/1409-Queries-on-a-Permutation-With-Key/1409.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def processQueries(self, queries: List[int], m: int) -> List[int]: 5 | p = [x for x in range(1, m + 1)] 6 | res = [] 7 | 8 | for x in queries: 9 | temp = p.index(x) 10 | num = p[temp] 11 | res.append(temp) 12 | p.remove(p[temp]) 13 | p.insert(0, num) 14 | return res 15 | 16 | if __name__ == "__main__": 17 | queries = [3,1,2,1] 18 | m = 5 19 | queries = [4,1,2,2] 20 | m = 4 21 | queries = [7,5,5,8,3] 22 | m = 8 23 | print(Solution().processQueries(queries, m)) -------------------------------------------------------------------------------- /solutions/1410-HTML-Entity-Parser/1410.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def entityParser(self, text: str) -> str: 3 | text = text.replace(""",'"') 4 | text = text.replace("'","'") 5 | text = text.replace(">",'>') 6 | text = text.replace("<",'<') 7 | text = text.replace("⁄",'/') 8 | text = text.replace("&","&") 9 | return text -------------------------------------------------------------------------------- /solutions/1413-Minimum-Value-to-Get-Positive-Step-by-Step-Sum/1413.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def minStartValue(self, nums: List[int]) -> int: 5 | n = len(nums) 6 | temp = [0 for x in range(n)] 7 | for i in range(n): 8 | temp[i] = sum(nums[:i+1]) 9 | if min(temp) >= 1: 10 | return 1 11 | else: 12 | return (abs(min(temp)) + 1) 13 | 14 | if __name__ == "__main__": 15 | nums = [-3,2,-3,4,2] 16 | nums = [1,-2,-3] 17 | nums = [1, 2] 18 | print(Solution().minStartValue(nums)) -------------------------------------------------------------------------------- /solutions/1414-Find-the-Minimum-Number-of-Fibonacci-Numbers-Whose-Sum-Is-K/1414.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findMinFibonacciNumbers(self, k: int) -> int: 3 | # FibonacciNumbers 4 | def fib(num): 5 | a, b = 0, 1 6 | res = [] 7 | while b <= num: 8 | res.append(b) 9 | a, b = b, a + b 10 | return res 11 | 12 | num = fib(k) 13 | cnt = 0 14 | while k: 15 | if k >= num[-1]: 16 | k -= num[-1] 17 | cnt += 1 18 | else: 19 | num.pop() 20 | return cnt 21 | 22 | if __name__ == "__main__": 23 | k = 19 24 | print(Solution().findMinFibonacciNumbers(k)) -------------------------------------------------------------------------------- /solutions/1415-The-k-th-Lexicographical-String-of-All-Happy-Strings-of-Length-n/1415.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def getHappyString(self, n: int, k: int) -> str: 3 | res = [] 4 | happy = ['a', 'b', 'c'] 5 | 6 | def dfs(curr, temp): 7 | # 剪枝,后面的不需要了 8 | if len(res) == k: 9 | return 10 | # 长度为 n,满足条件 11 | if len(curr) == n: 12 | res.append(curr) 13 | return 14 | # 长度不到就从 happy 里再选字符 15 | for x in temp: 16 | temp = [] 17 | # 选择跟前一个字符不同的字符 18 | for c in happy: 19 | if c != x: 20 | temp.append(c) 21 | # temp = [c for c in happy if c != x] 22 | # print(temp) 23 | dfs(curr + x, temp) 24 | 25 | dfs('', happy) 26 | # print(len(res)) 27 | return res[-1] if len(res) == k else '' 28 | 29 | if __name__ == "__main__": 30 | n = 3 31 | k = 9 32 | print(Solution().getHappyString(n, k)) -------------------------------------------------------------------------------- /solutions/1417-Reformat-The-String/1417.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def reformat(self, s: str) -> str: 3 | n = len(s) 4 | s = list(s) 5 | # print(s) 6 | num, ss = [], [] 7 | for i in range(n): 8 | # 字符 9 | if 'a' <= s[i] <= 'z': 10 | ss.append(s[i]) 11 | # 数字 12 | else: 13 | num.append(s[i]) 14 | # 当字符数组长度和数字数组长度相差大于1,肯定不满足 15 | if abs(len(num) - len(ss)) > 1: 16 | return "" 17 | else: 18 | res = [] 19 | # 数字多,先数字 20 | if len(num) > len(ss): 21 | for i in range(len(ss)): 22 | res.append(num[i]) 23 | res.append(ss[i]) 24 | res.append(num[-1]) 25 | # 字符多,先字符 26 | elif len(num) < len(ss): 27 | for i in range(len(num)): 28 | res.append(ss[i]) 29 | res.append(num[i]) 30 | res.append(ss[-1]) 31 | # 一样多 32 | else: 33 | for i in range(len(ss)): 34 | res.append(num[i]) 35 | res.append(ss[i]) 36 | # 最后要将列表转化为字符串 37 | return ''.join(res) 38 | 39 | if __name__ == "__main__": 40 | s = "a0b1c2" 41 | print(Solution().reformat(s)) -------------------------------------------------------------------------------- /solutions/Interview-01.06-compress-string-lcci/0106-LeetCode-solution.md: -------------------------------------------------------------------------------- 1 | > LeetCode 面试题 01.06. 字符串压缩【Easy】【Python】【双指针】 2 | 3 | ### 问题 4 | 5 | [力扣](https://leetcode-cn.com/problems/compress-string-lcci/) 6 | 7 | 字符串压缩。利用字符重复出现的次数,编写一种方法,实现基本的字符串压缩功能。比如,字符串aabcccccaaa会变为a2b1c5a3。若“压缩”后的字符串没有变短,则返回原先的字符串。你可以假设字符串中只包含大小写英文字母(a至z)。 8 | 9 | **示例1:** 10 | 11 | ``` 12 | 输入:"aabcccccaaa" 13 | 输出:"a2b1c5a3" 14 | ``` 15 | 16 | **示例2:** 17 | 18 | ``` 19 | 输入:"abbccd" 20 | 输出:"abbccd" 21 | 解释:"abbccd"压缩后为"a1b2c2d1",比原字符串长度更长。 22 | ``` 23 | 24 | **提示:** 25 | 26 | 1. 字符串长度在[0, 50000]范围内。 27 | 28 | ### 思路 29 | 30 | **双指针** 31 | 32 | ``` 33 | 每次统计相同字符个数,加入到 res 中。 34 | 最后比较一下压缩后的长度和原字符串长度,输出短的那个。 35 | ``` 36 | 37 | ##### Python3代码 38 | 39 | ```python 40 | class Solution: 41 | def compressString(self, S: str) -> str: 42 | n = len(S) 43 | res = '' 44 | i = 0 45 | while i < n: 46 | j = i 47 | while j < n and S[j] == S[i]: 48 | j += 1 49 | res += S[i] + str(j - i) 50 | i = j 51 | 52 | if len(res) < n: 53 | return res 54 | else: 55 | return S 56 | ``` 57 | 58 | ### 代码地址 59 | 60 | [GitHub链接](https://github.com/Wonz5130/LeetCode-Solutions/blob/master/solutions/Interview-01.06-compress-string-lcci/0106.py) -------------------------------------------------------------------------------- /solutions/Interview-01.06-compress-string-lcci/0106.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def compressString(self, S: str) -> str: 3 | n = len(S) 4 | res = '' 5 | i = 0 6 | while i < n: 7 | j = i 8 | while j < n and S[j] == S[i]: 9 | j += 1 10 | res += S[i] + str(j - i) 11 | i = j 12 | 13 | if len(res) < n: 14 | return res 15 | else: 16 | return S 17 | 18 | if __name__ == "__main__": 19 | S = "aabcccccaaa" 20 | print(Solution().compressString(S)) -------------------------------------------------------------------------------- /solutions/Interview-01.07-rotate-matrix-lcci/0107.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def rotate(self, matrix: List[List[int]]) -> None: 3 | """ 4 | Do not return anything, modify matrix in-place instead. 5 | """ 6 | n = len(matrix) 7 | # 先上下镜面翻转 8 | for i in range(n // 2): 9 | for j in range(n): 10 | matrix[i][j], matrix[n - 1 - i][j] = matrix[n - 1 - i][j], matrix[i][j] 11 | 12 | # 再主对角线翻转 13 | for i in range(n): 14 | for j in range(i): 15 | matrix[j][i], matrix[i][j] = matrix[i][j], matrix[j][i] -------------------------------------------------------------------------------- /solutions/Interview-03-shu-zu-zhong-zhong-fu-de-shu-zi-lcof/03.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def findRepeatNumber(self, nums: List[int]) -> int: 5 | # solution one: 哈希表 6 | n = len(nums) 7 | flag = [False for i in range(n)] 8 | for i in range(n): 9 | if flag[nums[i]] == False: 10 | flag[nums[i]] = True 11 | else: 12 | return nums[i] 13 | return -1 14 | 15 | # solution two: 排序 16 | nums.sort() 17 | pre = nums[0] 18 | for i in range(1, len(nums)): 19 | if pre == nums[i]: 20 | return nums[i] 21 | else: 22 | pre = nums[i] 23 | return -1 24 | 25 | # solution three: 两个萝卜一个坑 26 | n = len(nums) 27 | for i in range(n): 28 | if nums[i] == i: 29 | continue 30 | # 有重复 31 | elif nums[nums[i]] == nums[i]: 32 | return nums[i] 33 | # 交换 34 | else: 35 | nums[nums[i]], nums[i] = nums[i], nums[nums[i]] 36 | return -1 37 | 38 | if __name__ == "__main__": 39 | nums = [2, 3, 1, 0, 2, 5, 3] 40 | print(Solution().findRepeatNumber(nums)) -------------------------------------------------------------------------------- /solutions/Interview-04-er-wei-shu-zu-zhong-de-cha-zhao-lcof/04.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool: 5 | # solution one: 暴力 6 | # 特判 7 | if matrix == []: 8 | return False 9 | 10 | n, m = len(matrix), len(matrix[0]) 11 | for i in range(n): 12 | for j in range(m): 13 | if matrix[i][j] == target: 14 | return True 15 | elif matrix[i][j] > target: 16 | break 17 | return False 18 | 19 | # solution two: 左下角标志数法 20 | i, j = len(matrix) - 1, 0 21 | while i >= 0 and j < len(matrix[0]): 22 | if matrix[i][j] == target: 23 | return True 24 | elif matrix[i][j] > target: 25 | i -= 1 26 | else: 27 | j += 1 28 | return False 29 | -------------------------------------------------------------------------------- /solutions/Interview-04.02-Minimum-Height-Tree-LCCI/04-02-LeetCode-solution.md: -------------------------------------------------------------------------------- 1 | > LeetCode 面试题 04.02. 最小高度树【Easy】【Python】【二叉树】 2 | 3 | ## 问题 4 | 5 | [力扣](https://leetcode-cn.com/problems/minimum-height-tree-lcci/) 6 | 7 | 给定一个有序整数数组,元素各不相同且按升序排列,编写一个算法,创建一棵高度最小的二叉搜索树。 8 | 9 | **示例:** 10 | 11 | ``` 12 | 给定有序数组: [-10,-3,0,5,9], 13 | 14 | 一个可能的答案是:[0,-3,9,-10,null,5],它可以表示下面这个高度平衡二叉搜索树: 15 | 16 | 0 17 | / \ 18 | -3 9 19 | / / 20 | -10 5 21 | ``` 22 | 23 | ## 思路 24 | 25 | **递归** 26 | 27 | ``` 28 | 二叉搜索树根节点一定是有序数组的中位数:长度为奇数则取唯一中位数,长度为偶数则取右中位数。 29 | 递归终止条件:有序数组为空 30 | ``` 31 | 32 | ## 代码 33 | 34 | ### Python3 35 | 36 | ```python 37 | # Definition for a binary tree node. 38 | # class TreeNode: 39 | # def __init__(self, x): 40 | # self.val = x 41 | # self.left = None 42 | # self.right = None 43 | 44 | class Solution: 45 | def sortedArrayToBST(self, nums: List[int]) -> TreeNode: 46 | if not nums: 47 | return None 48 | 49 | mid = len(nums) // 2 50 | root = TreeNode(nums[mid]) 51 | root.left = self.sortedArrayToBST(nums[:mid]) 52 | root.right = self.sortedArrayToBST(nums[mid + 1:]) 53 | 54 | return root 55 | ``` 56 | 57 | ## 链接 58 | 59 | [GitHub](https://github.com/Wonz5130/LeetCode-Solutions/tree/master/solutions/Interview-04.02-Minimum-Height-Tree-LCCI) -------------------------------------------------------------------------------- /solutions/Interview-04.02-Minimum-Height-Tree-LCCI/0402.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def sortedArrayToBST(self, nums: List[int]) -> TreeNode: 10 | if not nums: 11 | return None 12 | 13 | mid = len(nums) // 2 14 | root = TreeNode(nums[mid]) 15 | root.left = self.sortedArrayToBST(nums[:mid]) 16 | root.right = self.sortedArrayToBST(nums[mid + 1:]) 17 | 18 | return root -------------------------------------------------------------------------------- /solutions/Interview-04.03-List-of-Depth-LCCI/0403.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | # Definition for singly-linked list. 9 | # class ListNode: 10 | # def __init__(self, x): 11 | # self.val = x 12 | # self.next = None 13 | 14 | class Solution: 15 | def listOfDepth(self, tree: TreeNode) -> List[ListNode]: 16 | import collections 17 | 18 | if not tree: 19 | return [] 20 | 21 | queue = collections.deque() 22 | queue.append(tree) 23 | res = [] 24 | # BFS 25 | while queue: 26 | n = len(queue) 27 | for i in range(n): 28 | node = queue.popleft() 29 | if node.left: 30 | queue.append(node.left) 31 | if node.right: 32 | queue.append(node.right) 33 | # 当前层的第一个节点 34 | if i == 0: 35 | # 头节点 36 | head = ListNode(node.val) 37 | tmp = head 38 | else: 39 | tmp.next = ListNode(node.val) 40 | tmp = tmp.next 41 | # 这里加入res的是head 42 | res.append(head) 43 | return res -------------------------------------------------------------------------------- /solutions/Interview-04.04-Check-Balance-LCCI/04-04-LeetCode-solution.md: -------------------------------------------------------------------------------- 1 | > LeetCode 面试题 04.04. 检查平衡性【Easy】【Python】【二叉树】 2 | 3 | ## 问题 4 | 5 | [力扣](https://leetcode-cn.com/problems/check-balance-lcci/) 6 | 7 | 实现一个函数,检查二叉树是否平衡。在这个问题中,平衡树的定义如下:任意一个节点,其两棵子树的高度差不超过 1。 8 | 9 | **示例 1:** 10 | 11 | ``` 12 | 给定二叉树 [3,9,20,null,null,15,7] 13 | 3 14 | / \ 15 | 9 20 16 | / \ 17 | 15 7 18 | 返回 true 。 19 | ``` 20 | 21 | **示例 2:** 22 | 23 | ``` 24 | 给定二叉树 [1,2,2,3,3,null,null,4,4] 25 | 1 26 | / \ 27 | 2 2 28 | / \ 29 | 3 3 30 | / \ 31 | 4 4 32 | 返回 false 。 33 | ``` 34 | 35 | ## 思路 36 | 37 | **递归** 38 | 39 | ``` 40 | 不止根节点左右高度差小于等于1,左右子树也要满足平衡 41 | ``` 42 | 43 | ## 代码 44 | 45 | ### Python3 46 | 47 | ```python 48 | # Definition for a binary tree node. 49 | # class TreeNode: 50 | # def __init__(self, x): 51 | # self.val = x 52 | # self.left = None 53 | # self.right = None 54 | 55 | class Solution: 56 | def isBalanced(self, root: TreeNode) -> bool: 57 | if not root: 58 | return True 59 | 60 | # 计算树的高度 61 | def height(root): 62 | if not root: 63 | return 0 64 | return max(height(root.left), height(root.right)) + 1 65 | 66 | # 不止根节点左右高度差小于等于1,左右子树也要满足平衡 67 | return abs(height(root.left) - height(root.right)) <= 1 and self.isBalanced(root.left) and self.isBalanced(root.right) 68 | ``` 69 | 70 | ## 链接 71 | 72 | [GitHub](https://github.com/Wonz5130/LeetCode-Solutions/tree/master/solutions/Interview-04.04-Check-Balance-LCCI) -------------------------------------------------------------------------------- /solutions/Interview-04.04-Check-Balance-LCCI/0404.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def isBalanced(self, root: TreeNode) -> bool: 10 | if not root: 11 | return True 12 | 13 | # 计算树的高度 14 | def height(root): 15 | if not root: 16 | return 0 17 | return max(height(root.left), height(root.right)) + 1 18 | 19 | # 不止根节点左右高度差小于等于1,左右子树也要满足平衡 20 | return abs(height(root.left) - height(root.right)) <= 1 and self.isBalanced(root.left) and self.isBalanced(root.right) -------------------------------------------------------------------------------- /solutions/Interview-04.05-Legal-Binary-Search-Tree-LCCI/04-05-LeetCode-solution.md: -------------------------------------------------------------------------------- 1 | > LeetCode 面试题 04.05. 合法二叉搜索树【Medium】【Python】【二叉树】 2 | 3 | ## 问题 4 | 5 | [力扣](https://leetcode-cn.com/problems/legal-binary-search-tree-lcci/) 6 | 7 | 实现一个函数,检查一棵二叉树是否为二叉搜索树。 8 | 9 | **示例 1:** 10 | 11 | ``` 12 | 输入: 13 | 2 14 | / \ 15 | 1 3 16 | 输出: true 17 | ``` 18 | 19 | **示例 2:** 20 | 21 | ``` 22 | 输入: 23 | 5 24 | / \ 25 | 1 4 26 | / \ 27 | 3 6 28 | 输出: false 29 | 解释: 输入为: [5,1,4,null,null,3,6]。 30 | 根节点的值为 5 ,但是其右子节点值为 4 。 31 | ``` 32 | 33 | ## 思路 34 | 35 | **递归** 36 | 37 | ``` 38 | 二叉搜索树:根节点值大于左子树节点最大值,小于右子树节点最小值。 39 | 左右子树也要满足二叉搜索树性质。 40 | ``` 41 | 42 | ## 代码 43 | 44 | ### Python3 45 | 46 | ```python 47 | # Definition for a binary tree node. 48 | # class TreeNode: 49 | # def __init__(self, x): 50 | # self.val = x 51 | # self.left = None 52 | # self.right = None 53 | 54 | class Solution: 55 | def isValidBST(self, root: TreeNode) -> bool: 56 | return self.isValid(root, None, None) 57 | 58 | # 辅助函数 59 | def isValid(self, root: TreeNode, min_: TreeNode, max_: TreeNode): 60 | if not root: 61 | return True 62 | if min_ != None and root.val <= min_.val: 63 | return False 64 | if max_ != None and root.val >= max_.val: 65 | return False 66 | return self.isValid(root.left, min_, root) and self.isValid(root.right, root, max_) 67 | ``` 68 | 69 | ## 链接 70 | 71 | [GitHub](https://github.com/Wonz5130/LeetCode-Solutions/tree/master/solutions/Interview-04.05-Legal-Binary-Search-Tree-LCCI) -------------------------------------------------------------------------------- /solutions/Interview-04.05-Legal-Binary-Search-Tree-LCCI/0405.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def isValidBST(self, root: TreeNode) -> bool: 10 | return self.isValid(root, None, None) 11 | 12 | # 辅助函数 13 | def isValid(self, root: TreeNode, min_: TreeNode, max_: TreeNode): 14 | if not root: 15 | return True 16 | if min_ != None and root.val <= min_.val: 17 | return False 18 | if max_ != None and root.val >= max_.val: 19 | return False 20 | return self.isValid(root.left, min_, root) and self.isValid(root.right, root, max_) -------------------------------------------------------------------------------- /solutions/Interview-04.06-Successor-LCCI/0406.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def inorderSuccessor(self, root: TreeNode, p: TreeNode) -> TreeNode: 10 | if not root: 11 | return None 12 | 13 | # p >= root,后继节点在右子树 14 | if root.val <= p.val: 15 | return self.inorderSuccessor(root.right, p) 16 | else: 17 | # 左子树不为空 18 | if self.inorderSuccessor(root.left, p): 19 | return self.inorderSuccessor(root.left, p) 20 | # 左子树为空,当前节点就是后继节点 21 | else: 22 | return root -------------------------------------------------------------------------------- /solutions/Interview-04.08-First-Common-Ancestor-LCCI/0408.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode: 10 | if not root or root == p or root == q: 11 | return root 12 | 13 | left = self.lowestCommonAncestor(root.left, p, q) 14 | right = self.lowestCommonAncestor(root.right, p, q) 15 | 16 | # 左右子树都为空 17 | if not left and not right: 18 | return None 19 | # 右子树为空 20 | elif left and not right: 21 | return left 22 | # 左子树为空 23 | elif not left and right: 24 | return right 25 | # 左右子树都不为空 26 | else: 27 | return root -------------------------------------------------------------------------------- /solutions/Interview-04.10-check-subtree-lcci/0410.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def checkSubTree(self, t1: TreeNode, t2: TreeNode) -> bool: 10 | if t1 == None: 11 | return False 12 | if t2 == None: 13 | return True 14 | # find the root of t2 in t1 15 | return self.dfs(t1, t2) or self.checkSubTree(t1.left , t2) or self.checkSubTree(t1.right, t2) 16 | 17 | def dfs(self, t1, t2): 18 | # t2 is over 19 | if t2 == None: 20 | return True 21 | # t2 is not over and t1 is over 22 | elif t2 != None and t1 == None: 23 | return False 24 | # not equal 25 | elif t2.val != t1.val: 26 | return False 27 | # equal, then search left and right 28 | else: 29 | return self.dfs(t1.left, t2.left) and self.dfs(t1.right, t2.right) # 注意这里是and -------------------------------------------------------------------------------- /solutions/Interview-04.12-Paths-with-Sum-LCCI/0412.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def pathSum(self, root: TreeNode, sum: int) -> int: 10 | if not root: 11 | return 0 12 | return self.dfs(root, sum) + self.pathSum(root.left, sum) + self.pathSum(root.right, sum) 13 | 14 | def dfs(self, root, sum): 15 | # 要特判为空,否则下面 sum == root.val 会报错 16 | if not root: 17 | return 0 18 | 19 | res = 0 20 | if sum == root.val: 21 | res += 1 22 | res += self.dfs(root.left, sum - root.val) 23 | res += self.dfs(root.right, sum - root.val) 24 | return res -------------------------------------------------------------------------------- /solutions/Interview-05-ti-huan-kong-ge-lcof/05-LeetCode-solution.md: -------------------------------------------------------------------------------- 1 | > LeetCode 面试题05. 替换空格【剑指Offer】【Easy】【Python】【字符串】 2 | 3 | ### 问题 4 | 5 | [力扣](https://leetcode-cn.com/problems/ti-huan-kong-ge-lcof/) 6 | 7 | 请实现一个函数,把字符串 s 中的每个空格替换成"%20"。 8 | 9 | **示例 1:** 10 | 11 | ``` 12 | 输入:s = "We are happy." 13 | 输出:"We%20are%20happy." 14 | ``` 15 | 16 | **限制:** 17 | 18 | `0 <= s 的长度 <= 10000` 19 | 20 | ### 思路 21 | 22 | ##### 解法一 23 | 24 | **字符串遍历** 25 | 26 | **时间复杂度:** O(n),n 为字符串长度。 27 | 28 | ##### Python3代码 29 | 30 | ```python 31 | class Solution: 32 | def replaceSpace(self, s: str) -> str: 33 | # solution one 34 | res = '' 35 | for c in s: 36 | if c == ' ': 37 | res += '%20' 38 | else: 39 | res += c 40 | return res 41 | ``` 42 | 43 | ##### 解法二 44 | 45 | **字符串遍历** 46 | 47 | **时间复杂度:** O(n),n 为字符串长度。 48 | 49 | ##### Python3代码 50 | 51 | ```python 52 | class Solution: 53 | def replaceSpace(self, s: str) -> str: 54 | # solution two 55 | return ''.join(('%20' if c ==' ' else c for c in s)) 56 | ``` 57 | 58 | ##### 解法三 59 | 60 | **replace函数** 61 | 62 | ##### Python3代码 63 | 64 | ```python 65 | class Solution: 66 | def replaceSpace(self, s: str) -> str: 67 | # solution three 68 | return s.replace(' ', '%20') 69 | ``` 70 | 71 | ### 代码地址 72 | 73 | [GitHub链接](https://github.com/Wonz5130/LeetCode-Solutions/blob/master/solutions/Interview-05-ti-huan-kong-ge-lcof/05.py) -------------------------------------------------------------------------------- /solutions/Interview-05-ti-huan-kong-ge-lcof/05.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def replaceSpace(self, s: str) -> str: 3 | # solution one 4 | res = '' 5 | for c in s: 6 | if c == ' ': 7 | res += '%20' 8 | else: 9 | res += c 10 | return res 11 | # solution two 12 | return ''.join(('%20' if c ==' ' else c for c in s)) 13 | # solution three 14 | return s.replace(' ', '%20') -------------------------------------------------------------------------------- /solutions/Interview-06-cong-wei-dao-tou-da-yin-lian-biao-lcof/06.go: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * type ListNode struct { 4 | * Val int 5 | * Next *ListNode 6 | * } 7 | */ 8 | func reversePrint(head *ListNode) []int { 9 | 10 | } -------------------------------------------------------------------------------- /solutions/Interview-06-cong-wei-dao-tou-da-yin-lian-biao-lcof/06.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.next = None 6 | 7 | class Solution: 8 | def reversePrint(self, head: ListNode) -> List[int]: 9 | # solution one: reverse 10 | res = [] 11 | while head: 12 | res.append(head.val) 13 | head = head.next 14 | res.reverse() 15 | return res 16 | 17 | # solution two: 栈 18 | stack = [] 19 | while head: # push 20 | stack.append(head.val) 21 | head = head.next 22 | res = [] 23 | while stack: # pop 24 | res.append(stack.pop()) 25 | return res 26 | 27 | # solution three: 递归 28 | return self.reversePrint(head.next) + [head.val] if head else [] -------------------------------------------------------------------------------- /solutions/Interview-07-zhong-jian-er-cha-shu-lcof/07.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode: 10 | if not preorder: 11 | return None 12 | root = TreeNode(preorder[0]) 13 | 14 | # 根在中序遍历中的索引 15 | i = inorder.index(root.val) 16 | # left: preorder[1] ~ preorder[i], inorder[0] ~ inorder[i-1] 17 | root.left = self.buildTree(preorder[1:i+1], inorder[:i]) 18 | # right: preorder[i+1] ~ preorder[-1], inorder[i+1] ~ inorder[-1] 19 | root.right = self.buildTree(preorder[i+1:], inorder[i+1:]) 20 | 21 | return root -------------------------------------------------------------------------------- /solutions/Interview-09-yong-liang-ge-zhan-shi-xian-dui-lie-lcof/09.py: -------------------------------------------------------------------------------- 1 | class CQueue: 2 | 3 | def __init__(self): 4 | self.A, self.B = [], [] 5 | 6 | def appendTail(self, value: int) -> None: 7 | self.A.append(value) 8 | 9 | def deleteHead(self) -> int: 10 | # B中还有倒序的元素,直接弹出 11 | if self.B: 12 | return self.B.pop() 13 | # A已空 14 | if not self.A: 15 | return -1 16 | # A中元素全部转到B中,实现倒序 17 | while self.A: 18 | self.B.append(self.A.pop()) 19 | return self.B.pop() 20 | 21 | 22 | # Your CQueue object will be instantiated and called as such: 23 | # obj = CQueue() 24 | # obj.appendTail(value) 25 | # param_2 = obj.deleteHead() -------------------------------------------------------------------------------- /solutions/Interview-10-fei-bo-na-qi-shu-lie-lcof/10-1.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def fib(self, n: int) -> int: 3 | dp_0, dp_1 = 0, 1 4 | for _ in range(n): 5 | dp_0, dp_1 = dp_1, dp_0 + dp_1 6 | return dp_0 % 1000000007 7 | 8 | # # 超时 9 | # if n == 0: 10 | # return 0 11 | # if n == 1: 12 | # return 1 13 | # return (self.fib(n - 1) + self.fib(n - 2)) % 1000000007 -------------------------------------------------------------------------------- /solutions/Interview-10-fei-bo-na-qi-shu-lie-lcof/10-2.go: -------------------------------------------------------------------------------- 1 | func fib(n int) int { 2 | var mod int = 1e9 + 7 3 | if n < 2 { 4 | return n 5 | } 6 | p, q, sum := 0, 0, 1 7 | for i := 2; i <= n; i++ { 8 | p = q 9 | q = sum 10 | sum = (p + q) % mod 11 | } 12 | return sum 13 | } -------------------------------------------------------------------------------- /solutions/Interview-10-qing-wa-tiao-tai-jie-wen-ti-lcof/10-2.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def numWays(self, n: int) -> int: 3 | # 初始条件和斐波那契数列有区别 4 | dp_0, dp_1 = 1, 1 5 | for _ in range(n): 6 | dp_0, dp_1 = dp_1, dp_0 + dp_1 7 | return dp_0 % 1000000007 -------------------------------------------------------------------------------- /solutions/Interview-10-qing-wa-tiao-tai-jie-wen-ti-lcof/10-LeetCode-solution.md: -------------------------------------------------------------------------------- 1 | > LeetCode 面试题10- II. 青蛙跳台阶问题【剑指Offer】【Easy】【Python】【动态规划】 2 | 3 | ### 问题 4 | 5 | [力扣](https://leetcode-cn.com/problems/qing-wa-tiao-tai-jie-wen-ti-lcof/) 6 | 7 | 一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。 8 | 9 | 答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。 10 | 11 | **示例 1:** 12 | 13 | ``` 14 | 输入:n = 2 15 | 输出:2 16 | ``` 17 | 18 | **示例 2:** 19 | 20 | ``` 21 | 输入:n = 7 22 | 输出:21 23 | ``` 24 | 25 | **提示:** 26 | 27 | * `0 <= n <= 100` 28 | 29 | 注意:本题与主站 [70 题](https://leetcode-cn.com/problems/climbing-stairs/) 相同。 30 | 31 | ### 思路 32 | 33 | **动态规划** 34 | 35 | ``` 36 | 初始条件和斐波那契数列有点区别:dp_0 = 1,dp_1 = 1。 37 | 38 | fib(n) = fib(n - 1) + fib(n - 2) 39 | 注意,fib(n)会越界,所以最好是: 40 | fib(n) % 1000000007 = (fib(n - 1) % 1000000007 + fib(n - 2) % 1000000007) % 1000000007 41 | 42 | 但是因为 Python 中整形数字的大小限制取决计算机的内存(可理解为无限大),因此可不考虑大数越界问题。 43 | ``` 44 | 45 | **时间复杂度:** O(n) 46 | **空间复杂度:** O(1) 47 | 48 | ##### Python3代码 49 | 50 | ```python 51 | class Solution: 52 | def numWays(self, n: int) -> int: 53 | # 初始条件和斐波那契数列有区别 54 | dp_0, dp_1 = 1, 1 55 | for _ in range(n): 56 | dp_0, dp_1 = dp_1, dp_0 + dp_1 57 | return dp_0 % 1000000007 58 | ``` 59 | 60 | ### GitHub链接 61 | 62 | [Python](https://github.com/Wonz5130/LeetCode-Solutions/blob/master/solutions/Interview-10-qing-wa-tiao-tai-jie-wen-ti-lcof/10-2.py) -------------------------------------------------------------------------------- /solutions/Interview-10.01-Sorted-Merge-LCCI/1001.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def merge(self, A: List[int], m: int, B: List[int], n: int) -> None: 5 | """ 6 | Do not return anything, modify A in-place instead. 7 | """ 8 | # # solution one: sort 9 | # A[m:] = B 10 | # A.sort() 11 | 12 | # solution two: two point 13 | if n == 0: # B = [] 14 | return 15 | i, j, k = m - 1, n - 1, m + n - 1 16 | while i > -1 and j > -1: # > -1, if m = 0 or n = 0, then i = -1 or j = -1 17 | if A[i] <= B[j]: 18 | A[k] = B[j] 19 | k -= 1 20 | j -= 1 21 | else: 22 | A[k] = A[i] 23 | k -= 1 24 | i -= 1 25 | if j > -1: 26 | A[:j + 1] = B[:j + 1] # A = [], B = [1] 27 | 28 | if __name__ == "__main__": 29 | A = [1,2,3,0,0,0] 30 | B = [2,5,6] 31 | m, n = 3, 3 32 | Solution().merge(A, m, B, n) 33 | print(A) -------------------------------------------------------------------------------- /solutions/Interview-11-xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof/11-LeetCode-solution.md: -------------------------------------------------------------------------------- 1 | > LeetCode 剑指 Offer 11. 旋转数组的最小数字【Easy】【Python】【二分查找】 2 | 3 | ## 问题 4 | 5 | [力扣](https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof/) 6 | 7 | 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。 8 | 9 | **示例 1:** 10 | 11 | ``` 12 | 输入:[3,4,5,1,2] 13 | 输出:1 14 | ``` 15 | 16 | **示例 2:** 17 | 18 | ``` 19 | 输入:[2,2,2,0,1] 20 | 输出:0 21 | ``` 22 | 23 | 24 | 注意:本题与主站 154 题相同:https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array-ii/ 25 | 26 | ## 思路 27 | 28 | **二分查找** 29 | 30 | ## 代码 31 | 32 | ### Python3 33 | 34 | ```python 35 | class Solution: 36 | def minArray(self, numbers: List[int]) -> int: 37 | left = 0 38 | right = len(numbers) - 1 39 | # 注意这里和labuladong模板有区别,循环是left numbers[right]: 48 | left = mid + 1 49 | # 因为包含重复,所以缩小右边界 50 | # 这里不能和上面合并,而要单独判断,举个例子:[3,3,1,3],不能判断出在左边还是右边 51 | else: 52 | right -= 1 53 | return numbers[left] 54 | ``` 55 | 56 | ## 链接 57 | 58 | [GitHub](https://github.com/Wonz5130/LeetCode-Solutions/tree/master/solutions/Interview-11-xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof) -------------------------------------------------------------------------------- /solutions/Interview-11-xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof/11.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def minArray(self, numbers: List[int]) -> int: 3 | left = 0 4 | right = len(numbers) - 1 5 | # 注意这里和labuladong模板有区别,循环是left numbers[right]: 14 | left = mid + 1 15 | # 因为包含重复,所以缩小右边界 16 | # 这里不能和上面合并,而要单独判断,举个例子:[3,3,1,3],不能判断出在左边还是右边 17 | else: 18 | right -= 1 19 | return numbers[left] -------------------------------------------------------------------------------- /solutions/Interview-13-ji-qi-ren-de-yun-dong-fan-wei-lcof/13.py: -------------------------------------------------------------------------------- 1 | import collections 2 | 3 | class Solution: 4 | def movingCount(self, m: int, n: int, k: int) -> int: 5 | visited = set() 6 | q = collections.deque() 7 | q.append((0, 0)) 8 | while q: 9 | x, y = q.popleft() 10 | if (x, y) not in visited and self.sum_rc(x, y) <= k: 11 | visited.add((x, y)) 12 | for dx, dy in [(1, 0), (0, 1)]: 13 | if 0 <= x + dx < m and 0 <= y + dy < n: 14 | q.append((x + dx, y + dy)) 15 | return len(visited) 16 | 17 | # 计算数位和 18 | def sum_rc(self, row, col): 19 | temp = 0 20 | while row > 0: 21 | temp += row % 10 22 | row //= 10 23 | while col > 0: 24 | temp += col % 10 25 | col //= 10 26 | return temp -------------------------------------------------------------------------------- /solutions/Interview-15-er-jin-zhi-zhong-1de-ge-shu-lcof/15.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def hammingWeight(self, n: int) -> int: 3 | # solution one 4 | res = 0 5 | while n: 6 | res += n & 1 7 | n >>= 1 8 | return res 9 | 10 | # solution two 11 | res = 0 12 | while n: 13 | res += 1 14 | n &= n - 1 15 | return res -------------------------------------------------------------------------------- /solutions/Interview-17-da-yin-cong-1dao-zui-da-de-nwei-shu-lcof/17-LeetCode-solution.md: -------------------------------------------------------------------------------- 1 | > LeetCode 面试题17. 打印从1到最大的n位数【剑指Offer】【Easy】【Python】【遍历】 2 | 3 | ### 问题 4 | 5 | [力扣](https://leetcode-cn.com/problems/da-yin-cong-1dao-zui-da-de-nwei-shu-lcof/) 6 | 7 | 输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。 8 | 9 | **示例 1:** 10 | 11 | ``` 12 | 输入: n = 1 13 | 输出: [1,2,3,4,5,6,7,8,9] 14 | ``` 15 | 16 | 17 | 说明: 18 | 19 | * 用返回一个整数列表来代替打印 20 | * n 为正整数 21 | 22 | ### 思路 23 | 24 | ##### Python3代码 25 | 26 | ```python 27 | class Solution: 28 | def printNumbers(self, n: int) -> List[int]: 29 | res = [] 30 | for i in range(1, 10**n): 31 | res.append(i) 32 | return res 33 | 34 | # 一行代码 35 | return list(range(1, 10**n)) 36 | ``` 37 | 38 | ### GitHub链接 39 | 40 | [Python](https://github.com/Wonz5130/LeetCode-Solutions/blob/master/solutions/Interview-17-da-yin-cong-1dao-zui-da-de-nwei-shu-lcof/17.py) -------------------------------------------------------------------------------- /solutions/Interview-17-da-yin-cong-1dao-zui-da-de-nwei-shu-lcof/17.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def printNumbers(self, n: int) -> List[int]: 3 | res = [] 4 | for i in range(1, 10**n): 5 | res.append(i) 6 | return res 7 | 8 | # 一行代码 9 | return list(range(1, 10**n)) -------------------------------------------------------------------------------- /solutions/Interview-17.12-BiNode-LCCI/17-12-LeetCode-solution.md: -------------------------------------------------------------------------------- 1 | > LeetCode 面试题 17.12. BiNode【Easy】【Python】【二叉树】 2 | 3 | ## 问题 4 | 5 | [力扣](https://leetcode-cn.com/problems/binode-lcci/) 6 | 7 | 二叉树数据结构TreeNode可用来表示单向链表(其中left置空,right为下一个链表节点)。实现一个方法,把二叉搜索树转换为单向链表,要求依然符合二叉搜索树的性质,转换操作应是原址的,也就是在原始的二叉搜索树上直接修改。 8 | 9 | 返回转换后的单向链表的头节点。 10 | 11 | 注意:本题相对原题稍作改动 12 | 13 | **示例:** 14 | 15 | ``` 16 | 输入: [4,2,5,1,3,null,6,0] 17 | 输出: [0,null,1,null,2,null,3,null,4,null,5,null,6] 18 | ``` 19 | 20 | **提示:** 21 | 22 | - 节点数量不会超过 100000。 23 | 24 | ## 思路 25 | 26 | **DFS** 27 | 28 | ``` 29 | 中序遍历 30 | ``` 31 | 32 | ## 代码 33 | 34 | ### Python3 35 | 36 | ```python 37 | # Definition for a binary tree node. 38 | # class TreeNode: 39 | # def __init__(self, x): 40 | # self.val = x 41 | # self.left = None 42 | # self.right = None 43 | 44 | class Solution: 45 | def convertBiNode(self, root: TreeNode) -> TreeNode: 46 | def dfs(root): 47 | pre = cur = root 48 | if root: 49 | if root.left: 50 | pre, cur = dfs(root.left) 51 | # 左子树的下一个链表节点是当前root节点 52 | cur.right = root 53 | # 修改当前指针 54 | cur = root 55 | root.left = None 56 | if root.right: 57 | root.right, cur = dfs(root.right) 58 | return pre, cur 59 | 60 | return dfs(root)[0] 61 | ``` 62 | 63 | ## 链接 64 | 65 | [GitHub](https://github.com/Wonz5130/LeetCode-Solutions/tree/master/solutions/Interview-17.12-BiNode-LCCI) -------------------------------------------------------------------------------- /solutions/Interview-17.12-BiNode-LCCI/1712.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def convertBiNode(self, root: TreeNode) -> TreeNode: 10 | def dfs(root): 11 | pre = cur = root 12 | if root: 13 | if root.left: 14 | pre, cur = dfs(root.left) 15 | # 左子树的下一个链表节点是当前root节点 16 | cur.right = root 17 | # 修改当前指针 18 | cur = root 19 | root.left = None 20 | if root.right: 21 | root.right, cur = dfs(root.right) 22 | return pre, cur 23 | 24 | return dfs(root)[0] -------------------------------------------------------------------------------- /solutions/Interview-17.16-The-Masseuse-LCCI/1716.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def massage(self, nums: List[int]) -> int: 3 | dp = [0] * (len(nums) + 2) 4 | res = 0 5 | # dp[0] = dp[1] = 0, dp[i] 对应 nums[i - 2] 6 | for i in range(2, len(nums) + 2): 7 | dp[i] = max(dp[i-1], dp[i-2] + nums[i-2]) 8 | res = max(res, dp[i]) 9 | return res -------------------------------------------------------------------------------- /solutions/Interview-26-shu-de-zi-jie-gou-lcof/26.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def isSubStructure(self, A: TreeNode, B: TreeNode) -> bool: 10 | if not A or not B: 11 | return False 12 | return self.dfs(A, B) or self.isSubStructure(A.left, B) or self.isSubStructure(A.right, B) 13 | 14 | 15 | def dfs(self, A: TreeNode, B:TreeNode): 16 | if not B: 17 | return True 18 | if not A: 19 | return False 20 | if not A.val == B.val: 21 | return False 22 | # A树的根与B树的根相等 23 | return self.dfs(A.left, B.left) and self.dfs(A.right, B.right) # 注意这里是 and -------------------------------------------------------------------------------- /solutions/Interview-27-er-cha-shu-de-jing-xiang-lcof/27.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def mirrorTree(self, root: TreeNode) -> TreeNode: 10 | if not root: 11 | return None 12 | # 叶子节点,直接返回自己 13 | if not root.left and not root.right: 14 | return root 15 | 16 | # 交换非叶子节点的左右两棵子树 17 | root.left, root.right = root.right, root.left 18 | if root.left: 19 | self.mirrorTree(root.left) 20 | if root.right: 21 | self.mirrorTree(root.right) 22 | return root -------------------------------------------------------------------------------- /solutions/Interview-28-dui-cheng-de-er-cha-shu-lcof/28.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def isSymmetric(self, root: TreeNode) -> bool: 10 | def recur(L, R): 11 | # 左右子树都为空 12 | if not L and not R: 13 | return True 14 | # 有一个不为空 15 | if not L or not R or L.val != R.val: 16 | return False 17 | # L的左子树和R的右子树,L的右子树和R的左子树 18 | return recur(L.left, R.right) and recur(L.right, R.left) 19 | 20 | # 特判:root为空 21 | if not root: 22 | return True 23 | return recur(root.left, root.right) -------------------------------------------------------------------------------- /solutions/Interview-32-cong-shang-dao-xia-da-yin-er-cha-shu-ii-lcof/32-2.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def levelOrder(self, root: TreeNode) -> List[List[int]]: 10 | import collections 11 | if not root: 12 | return [] 13 | 14 | res, q = [], collections.deque() 15 | q.append(root) 16 | while q: 17 | # 输出是二维数组 18 | temp = [] 19 | for x in range(len(q)): 20 | node = q.popleft() 21 | temp.append(node.val) 22 | if node.left: 23 | q.append(node.left) 24 | if node.right: 25 | q.append(node.right) 26 | res.append(temp) 27 | return res -------------------------------------------------------------------------------- /solutions/Interview-32-cong-shang-dao-xia-da-yin-er-cha-shu-iii-lcof/32-3.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def levelOrder(self, root: TreeNode) -> List[List[int]]: 10 | import collections 11 | if not root: 12 | return [] 13 | 14 | res, q = [], collections.deque() 15 | # 做奇偶判断 16 | flag = False 17 | q.append(root) 18 | while q: 19 | # 输出是二维数组 20 | temp = [] 21 | flag = not flag 22 | for x in range(len(q)): 23 | node = q.popleft() 24 | # 尾插 25 | if flag: 26 | temp.append(node.val) 27 | # 头插 28 | else: 29 | temp.insert(0, node.val) 30 | if node.left: 31 | q.append(node.left) 32 | if node.right: 33 | q.append(node.right) 34 | res.append(temp) 35 | return res -------------------------------------------------------------------------------- /solutions/Interview-32-cong-shang-dao-xia-da-yin-er-cha-shu-lcof/32.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def levelOrder(self, root: TreeNode) -> List[int]: 10 | import collections 11 | if not root: 12 | return [] 13 | 14 | res, q = [], collections.deque() 15 | q.append(root) 16 | while q: 17 | node = q.popleft() # O(1) 18 | res.append(node.val) 19 | if node.left: 20 | q.append(node.left) 21 | if node.right: 22 | q.append(node.right) 23 | return res -------------------------------------------------------------------------------- /solutions/Interview-33-er-cha-sou-suo-shu-de-hou-xu-bian-li-xu-lie-lcof/33.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def verifyPostorder(self, postorder: List[int]) -> bool: 5 | def recur(i, j): 6 | # 根节点小于等于1个 7 | if i >= j: 8 | return True 9 | l = i 10 | # 左子树 11 | while postorder[l] < postorder[j]: 12 | l += 1 13 | # 找到第一个大于根节点的节点,记为 m 14 | m = l 15 | # 右子树 16 | while postorder[l] > postorder[j]: 17 | l += 1 18 | # postorder[j]是根 19 | return l == j and recur(i, m - 1) and recur(m, j - 1) 20 | 21 | return recur(0, len(postorder) - 1) -------------------------------------------------------------------------------- /solutions/Interview-34-er-cha-shu-zhong-he-wei-mou-yi-zhi-de-lu-jing-lcof/34.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]: 10 | res, path = [], [] 11 | 12 | # 先序遍历:根左右 13 | def recur(root, target): 14 | if not root: 15 | return 16 | 17 | path.append(root.val) 18 | target -= root.val 19 | # 找到路径 20 | if target == 0 and not root.left and not root.right: 21 | res.append(list(path)) # 复制了一个 path 加入到 res 中,这样修改 path 不影响 res 22 | recur(root.left, target) 23 | recur(root.right, target) 24 | # 向上回溯,需要删除当前节点 25 | path.pop() 26 | 27 | recur(root, sum) 28 | return res -------------------------------------------------------------------------------- /solutions/Interview-36-er-cha-sou-suo-shu-yu-shuang-xiang-lian-biao-lcof/36.py: -------------------------------------------------------------------------------- 1 | """ 2 | # Definition for a Node. 3 | class Node: 4 | def __init__(self, val, left=None, right=None): 5 | self.val = val 6 | self.left = left 7 | self.right = right 8 | """ 9 | class Solution: 10 | def treeToDoublyList(self, root: 'Node') -> 'Node': 11 | def dfs(cur): 12 | if not cur: 13 | return 14 | # 递归左子树 15 | dfs(cur.left) 16 | # 修改节点引用 17 | if self.pre: 18 | self.pre.right, cur.left = cur, self.pre 19 | # 记录头节点 20 | else: 21 | self.head = cur 22 | # 保存 cur 23 | self.pre = cur 24 | # 递归右子树 25 | dfs(cur.right) 26 | 27 | # 特例处理:root为空 28 | if not root: 29 | return 30 | # 空节点 31 | self.pre = None 32 | # 转为双向链表 33 | dfs(root) 34 | # 构建循环链表 35 | self.head.left, self.pre.right = self.pre, self.head 36 | return self.head -------------------------------------------------------------------------------- /solutions/Interview-53-que-shi-de-shu-zi-lcof/53-2-LeetCode-solution.md: -------------------------------------------------------------------------------- 1 | > LeetCode 剑指 Offer 53 - II. 0~n-1中缺失的数字【Easy】【Python】【二分查找】 2 | 3 | ## 问题 4 | 5 | [力扣](https://leetcode-cn.com/problems/que-shi-de-shu-zi-lcof/) 6 | 7 | 一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。 8 | 9 | **示例 1:** 10 | 11 | ``` 12 | 输入: [0,1,3] 13 | 输出: 2 14 | ``` 15 | 16 | **示例 2:** 17 | 18 | ``` 19 | 输入: [0,1,2,3,4,5,6,7,9] 20 | 输出: 8 21 | ``` 22 | 23 | **限制:** 24 | 25 | - 1 <= 数组长度 <= 10000 26 | 27 | ## 思路 28 | 29 | **二分查找** 30 | 31 | ## 代码 32 | 33 | ### Python3 34 | 35 | ```python 36 | class Solution: 37 | def missingNumber(self, nums: List[int]) -> int: 38 | left = 0 39 | right = len(nums) - 1 40 | while left <= right: 41 | mid = left + (right - left) // 2 42 | if nums[mid] == mid: 43 | left = mid + 1 44 | else: 45 | right = mid - 1 46 | # 返回left 47 | return left 48 | ``` 49 | 50 | ## 链接 51 | 52 | [GitHub](https://github.com/Wonz5130/LeetCode-Solutions/tree/master/solutions/Interview-53-que-shi-de-shu-zi-lcof) -------------------------------------------------------------------------------- /solutions/Interview-53-que-shi-de-shu-zi-lcof/53-2.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def missingNumber(self, nums: List[int]) -> int: 3 | left = 0 4 | right = len(nums) - 1 5 | while left <= right: 6 | mid = left + (right - left) // 2 7 | if nums[mid] == mid: 8 | left = mid + 1 9 | else: 10 | right = mid - 1 11 | # 返回left 12 | return left -------------------------------------------------------------------------------- /solutions/Interview-53-zai-pai-xu-shu-zu-zhong-cha-zhao-shu-zi-lcof/53-1.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def search(self, nums: List[int], target: int) -> int: 3 | left = 0 4 | right = len(nums) - 1 5 | # 求右边界 6 | while left <= right: 7 | mid = left + (right - left) // 2 8 | if nums[mid] <= target: 9 | left = mid + 1 10 | elif nums[mid] > target: 11 | right = mid - 1 12 | R = right 13 | 14 | # 如果R越界或者R位置的值不等于target,说明不存在target,可以直接返回0 15 | if R < 0 or nums[R] != target: 16 | return 0 17 | left = 0 18 | # 缩小区间,直接在[0,R]中寻找左边界 19 | right = R 20 | # 求左边界 21 | while left <= right: 22 | mid = left + (right - left) // 2 23 | if nums[mid] >= target: 24 | right = mid - 1 25 | elif nums[mid] < target: 26 | left = mid + 1 27 | L = left 28 | return R - L + 1 -------------------------------------------------------------------------------- /solutions/Interview-54-er-cha-sou-suo-shu-de-di-kda-jie-dian-lcof/54.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def kthLargest(self, root: TreeNode, k: int) -> int: 10 | def dfs(root): 11 | if not root: 12 | return 13 | # 中序遍历倒序 14 | dfs(root.right) 15 | if self.k == 0: 16 | return 17 | self.k -= 1 18 | if self.k == 0: 19 | self.res = root.val 20 | dfs(root.left) 21 | 22 | self.k = k 23 | dfs(root) 24 | return self.res -------------------------------------------------------------------------------- /solutions/Interview-55-er-cha-shu-de-shen-du-lcof/55.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def maxDepth(self, root: TreeNode) -> int: 10 | # solution one: DFS 11 | if not root: 12 | return 0 13 | return max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1 14 | 15 | # solution two: BFS 16 | if not root: 17 | return 0 18 | q, res = [root], 0 19 | # 当q为空时跳出 20 | while q: 21 | tmp = [] 22 | for node in q: 23 | if node.left: 24 | tmp.append(node.left) 25 | if node.right: 26 | tmp.append(node.right) 27 | q = tmp 28 | res += 1 29 | return res -------------------------------------------------------------------------------- /solutions/Interview-55-ping-heng-er-cha-shu-lcof/55.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def isBalanced(self, root: TreeNode) -> bool: 10 | # solution one: 后序+剪枝 11 | def recur(root): 12 | if not root: 13 | return 0 14 | left = recur(root.left) 15 | if left == -1: 16 | return -1 17 | right = recur(root.right) 18 | if right == -1: 19 | return -1 20 | # 左右子树深度差 <= 1,符合平衡二叉树 21 | return max(left, right) + 1 if abs(left - right) <= 1 else -1 22 | 23 | # 若 recur(root) != -1,说明平衡 24 | return recur(root) != -1 25 | 26 | # solution two: 前序+判断深度 27 | # 特判:root 为空 28 | if not root: 29 | return True 30 | # 当前子树是否平衡 31 | # 当前子树的左子树是否平衡 32 | # 当前子树的右子树是否平衡 33 | return abs(self.depth(root.left) - self.depth(root.right)) <= 1 and \ 34 | self.isBalanced(root.left) and self.isBalanced(root.right) 35 | 36 | # 计算深度 37 | def depth(self, root): 38 | if not root: 39 | return 0 40 | return max(self.depth(root.left), self.depth(root.right)) + 1 41 | -------------------------------------------------------------------------------- /solutions/Interview-59-II/5902.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | 3 | class MaxQueue: 4 | 5 | def __init__(self): 6 | self.que = deque() 7 | self.sort_que = deque() 8 | 9 | def max_value(self) -> int: 10 | return self.sort_que[0] if self.sort_que else -1 11 | 12 | def push_back(self, value: int) -> None: 13 | self.que.append(value) 14 | # sort_que: non-increasing 非递增 15 | while self.sort_que and self.sort_que[-1] < value: 16 | self.sort_que.pop() 17 | self.sort_que.append(value) 18 | 19 | def pop_front(self) -> int: 20 | if not self.que: 21 | return -1 22 | res = self.que.popleft() # popleft(): O(1), pop(i): O(n) 23 | if res == self.sort_que[0]: 24 | self.sort_que.popleft() 25 | return res 26 | 27 | # Your MaxQueue object will be instantiated and called as such: 28 | # obj = MaxQueue() 29 | # param_1 = obj.max_value() 30 | # obj.push_back(value) 31 | # param_3 = obj.pop_front() -------------------------------------------------------------------------------- /solutions/Interview-62-yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof/62-LeetCode-solution.md: -------------------------------------------------------------------------------- 1 | > LeetCode 面试题62. 圆圈中最后剩下的数字【剑指Offer】【Easy】【Python】【数学】 2 | 3 | ### 问题 4 | 5 | [力扣](https://leetcode-cn.com/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof/) 6 | 7 | 0,1,,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。 8 | 9 | 例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。 10 | 11 | **示例 1:** 12 | 13 | ``` 14 | 输入: n = 5, m = 3 15 | 输出: 3 16 | ``` 17 | 18 | **示例 2:** 19 | 20 | ``` 21 | 输入: n = 10, m = 17 22 | 输出: 2 23 | ``` 24 | 25 | **限制:** 26 | 27 | - `1 <= n <= 10^5` 28 | - `1 <= m <= 10^6` 29 | 30 | ### 思路 31 | 32 | **数学** 33 | 34 | ``` 35 | 今天笔试正好考了类似的题目,其实就是约瑟夫环。 36 | 直接给出递推公式: 37 | ``` 38 | 39 | $$ 40 | f(n,m) = \begin{cases} 41 | 0,\quad n = 1 \\ 42 | [f(n-1,m)+m]\%n,\quad n > 1 43 | \end{cases} 44 | $$ 45 | 46 | ##### Python3代码 47 | 48 | ```python 49 | class Solution: 50 | def lastRemaining(self, n: int, m: int) -> int: 51 | if n < 1 or m < 1: 52 | return None 53 | 54 | last = 0 55 | # 最后一轮只剩两个人,倒过来推 56 | for i in range(2, n + 1): 57 | last = (last + m) % i 58 | return last 59 | ``` 60 | 61 | ### GitHub链接 62 | 63 | [Python](https://github.com/Wonz5130/LeetCode-Solutions/blob/master/solutions/Interview-62-yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof/62.py) -------------------------------------------------------------------------------- /solutions/Interview-62-yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof/62.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def lastRemaining(self, n: int, m: int) -> int: 3 | if n < 1 or m < 1: 4 | return None 5 | 6 | last = 0 7 | # 最后一轮只剩两个人,倒过来推 8 | for i in range(2, n + 1): 9 | last = (last + m) % i 10 | return last -------------------------------------------------------------------------------- /solutions/Interview-68-er-cha-shu-de-zui-jin-gong-gong-zu-xian-lcof/68-2.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode: 10 | if not root or root == p or root == q: 11 | return root 12 | 13 | left = self.lowestCommonAncestor(root.left, p, q) 14 | right = self.lowestCommonAncestor(root.right, p, q) 15 | # 左右子树都为空 16 | if not left and not right: 17 | return None 18 | # 左子树为空 19 | elif not left and right: 20 | return right 21 | # 右子树为空 22 | elif left and not right: 23 | return left 24 | # 左右子树都不为空 25 | return root -------------------------------------------------------------------------------- /solutions/Interview-68-er-cha-sou-suo-shu-de-zui-jin-gong-gong-zu-xian-lcof/68-1.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': 10 | # 全在左子树 11 | if root.val > p.val and root.val > q.val: 12 | return self.lowestCommonAncestor(root.left, p, q) 13 | # 全在右子树 14 | elif root.val < p.val and root.val < q.val: 15 | return self.lowestCommonAncestor(root.right, p, q) 16 | return root -------------------------------------------------------------------------------- /solutions/LCP06-na-ying-bi/06.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def minCount(self, coins: List[int]) -> int: 3 | cnt = 0 4 | for x in coins: 5 | if x % 2: 6 | cnt += (x // 2 + 1) 7 | else: 8 | cnt += x // 2 9 | return cnt -------------------------------------------------------------------------------- /solutions/LCP07-chuan-di-xin-xi/07.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def numWays(self, n: int, relation: List[List[int]], k: int) -> int: 5 | self.res = 0 6 | 7 | graph = [[[None] for x in range(n)] for x in range(n)] 8 | for i in range(len(relation)): 9 | graph[relation[i][0]][relation[i][1]] = 1 10 | 11 | def dfs(start, step): 12 | if step > k: 13 | return 14 | # 经过 k 轮传到 n-1 15 | if step == k and start == n - 1: 16 | self.res += 1 17 | return 18 | for i in range(n): 19 | # 有下一个可传 20 | if graph[start][i] == 1: 21 | dfs(i, step + 1) 22 | 23 | dfs(0, 0) 24 | return self.res 25 | 26 | if __name__ == "__main__": 27 | n = 5 28 | relation = [[0,2],[2,1],[3,4],[2,3],[1,4],[2,0],[0,4]] 29 | k = 3 30 | print(Solution().numWays(n, relation, k)) -------------------------------------------------------------------------------- /solutions/LCP08-ju-qing-hong-fa-shi-jian/08.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | class Solution: 4 | def getTriggerTime(self, increase: List[List[int]], requirements: List[List[int]]) -> List[int]: 5 | n = len(requirements) 6 | res = [-1 for x in range(n)] 7 | 8 | # 累加 increase 9 | increase = [[0, 0, 0]] + increase 10 | for i in range(len(increase) - 1): 11 | for j in range(3): 12 | increase[i + 1][j] += increase[i][j] 13 | 14 | # 二分 15 | for i in range(len(requirements)): 16 | left, right = 0, len(increase) - 1 17 | while left <= right: # 注意条件:<= 18 | mid = (left + right) // 2 19 | if increase[mid][0] >= requirements[i][0] and increase[mid][1] >= requirements[i][1] and increase[mid][2] >= requirements[i][2]: 20 | res[i] = mid 21 | right = mid - 1 22 | else: 23 | left = mid + 1 24 | 25 | return res 26 | 27 | if __name__ == "__main__": 28 | increase = [[2,8,4],[2,5,0],[10,9,8]] 29 | # increase = [[1,1,1]] 30 | requirements = [[2,11,3],[15,10,7],[9,17,12],[8,1,14]] 31 | # requirements = [[0,0,0]] 32 | print(Solution().getTriggerTime(increase, requirements)) --------------------------------------------------------------------------------