├── .github
└── assets
│ ├── 02ml-binary_logistic_loss.png
│ ├── 02ml-confusion.png
│ ├── 02ml-deployment.png
│ ├── 02ml-feature_store.png
│ ├── 02ml-llm-rag.png
│ ├── 02ml-llm-resource.png
│ ├── 02ml-retraining.png
│ ├── 02ml-rlhf.png
│ ├── 02ml-sd.png
│ ├── 02ml-tree.png
│ ├── 02ml-xgboost.jpg
│ ├── 03ml-ad-pipe2.png
│ ├── 03ml-ad-sys.png
│ ├── 03ml-adclick-ad.png
│ ├── 03ml-adclick-pipe.png
│ ├── 03ml-adclick-user.png
│ ├── 03ml-audio.png
│ ├── 03ml-content-encoding.png
│ ├── 03ml-content-fewshot.png
│ ├── 03ml-content-pipe.png
│ ├── 03ml-friend-edge.png
│ ├── 03ml-friend-pipe.png
│ ├── 03ml-friend-rank.png
│ ├── 03ml-loan-feature.png
│ ├── 03ml-loan-feature2.png
│ ├── 03ml-loan-inference.png
│ ├── 03ml-loan-train.png
│ ├── 03ml-qa-all.png
│ ├── 03ml-qa-event.png
│ ├── 03ml-qa-kbqa.png
│ ├── 03ml-qa-kbqa2.png
│ ├── 03ml-qa-pipe.png
│ ├── 03ml-rag.jpeg
│ ├── 03ml-reco-cases.png
│ ├── 03ml-reco-metrics.png
│ ├── 03ml-reco-other.png
│ ├── 03ml-reco-otto-sirus.png
│ ├── 03ml-reco-rank.png
│ ├── 03ml-reco-recall-model.png
│ ├── 03ml-reco-recall.png
│ ├── 03ml-reco-user.png
│ ├── 03ml-reco.png
│ ├── 03ml-retrieval.png
│ ├── 03ml-search-engine-pipe.png
│ ├── 03ml-search-engine-pipe2.png
│ ├── 03ml-sentiment-pipe.png
│ ├── 03ml-twitter-reco.png
│ ├── 03ml-vsearch-loss.png
│ ├── 03ml-vsearch-pipe.png
│ ├── 03ml-vsearch-pipe2.png
│ ├── 03ml-vsearch-text.png
│ ├── 03ml-vsearch-video.png
│ ├── 03ml-youtube-reco-rank-cross.png
│ ├── 03ml-youtube-reco-rank-model.png
│ ├── 03ml-youtube-reco-rank-user.png
│ ├── 03ml-youtube-reco-rank-video.png
│ ├── 03ml-youtube-reco-rank.png
│ ├── 03ml-youtube-reco-retrieval-model.png
│ ├── 03ml-youtube-reco-retrieval-twotower.png
│ ├── 03ml-youtube-reco-retrieval.png
│ ├── 03ml-youtube-reco-structure.png
│ ├── pair document.png
│ ├── query embedding.png
│ └── text.png
├── .gitignore
├── 01_leetcode
├── 00_array
│ ├── 179. Largest Number.md
│ ├── 215. Kth Largest Element.md
│ ├── 2348. Number of Zero-Filled Subarrays.md
│ ├── 31. Next Permutation.md
│ ├── 59. Spiral Matrix II.md
│ ├── 605. Can Place Flowers.md
│ ├── 665. Non-decreasing Array.md
│ ├── 912. Sort an Array.md
│ ├── 977. Squares of a Sorted Array.md
│ └── README.md
├── 00_binary_search
│ ├── 1011. Capacity To Ship Packages Within D Days.md
│ ├── 1044. Longest Duplicate Substring.md
│ ├── 1060. Missing Element in Sorted Array.md
│ ├── 1062. Longest Repeating Substring.md
│ ├── 1095. Find in Mountain Array.md
│ ├── 1300. Sum of Mutated Array Closest to Target.md
│ ├── 162. Find Peak Element.md
│ ├── 1891. Cutting Ribbons.md
│ ├── 2055. Plates Between Candles.md
│ ├── 240. Search a 2D Matrix II.md
│ ├── 278. First Bad Version.md
│ ├── 33. Search in Rotated Sorted Array.md
│ ├── 34. Find First and Last Position of Element in Sorted Array.md
│ ├── 4. Median of Two Sorted Arrays.md
│ ├── 410. Split Array Largest Sum.md
│ ├── 528. Random Pick with Weight.md
│ ├── 540. Single Element in a Sorted Array.md
│ ├── 644. Maximum Average Subarray II.md
│ ├── 69. Sqrt(x).md
│ ├── 704. Binary Search.md
│ ├── 74. Search a 2D Matrix.md
│ ├── 81. Search in Rotated Sorted Array II.md
│ └── README.md
├── 01_two_pointers
│ ├── 1004. Max Consecutive Ones III.md
│ ├── 11. Container With Most Water.md
│ ├── 125. Valid Palindrome.md
│ ├── 1456. Maximum Number of Vowels in a Substring of Given Length.md
│ ├── 15. 3Sum.md
│ ├── 16. 3Sum Closest.md
│ ├── 1658. Minimum Operations to Reduce X to Zero.md
│ ├── 167. Two Sum II - Input array is sorted.md
│ ├── 18. 4Sum.md
│ ├── 209. Minimum Size Subarray Sum.md
│ ├── 26. Remove Duplicate Numbers in Array.md
│ ├── 277. Find the Celebrity.md
│ ├── 283. Move Zeroes.md
│ ├── 3. Longest Substring Without Repeating Characters.md
│ ├── 340. Longest Substring with At Most K Distinct Characters.md
│ ├── 395. Longest Substring with At Least K Repeating Characters.md
│ ├── 409. Longest Palindrome.md
│ ├── 42. Trapping Rain Water.md
│ ├── 424. Longest Repeating Character Replacement.md
│ ├── 454. 4Sum II.md
│ ├── 5. Longest Palindromic Substring.md
│ ├── 647. Palindromic Substrings.md
│ ├── 75. Sort Colors.md
│ ├── 76. Minimum Window Substring.md
│ ├── 88. Merge Sorted Arrays.md
│ └── README.md
├── 02_linked_list
│ ├── 141. Linked List Cycle.md
│ ├── 142. Linked List Cycle II.md
│ ├── 148. Sort List.md
│ ├── 160. Intersection of Two Linked Lists.md
│ ├── 19. Remove Nth Node From End of List.md
│ ├── 203. Remove Linked List Elements.md
│ ├── 206. Reverse Linked List.md
│ ├── 24. Swap Nodes in Pairs.md
│ ├── 328. Odd Even Linked List.md
│ ├── 707. Design Linked List.md
│ ├── 876. Middle of the Linked List.md
│ ├── 92. Reverse Linked List II.md
│ └── README.md
├── 03_hash
│ ├── 1. Two Sum.md
│ ├── 128. Longest Consecutive Sequence.md
│ ├── 146. LRU Cache.md
│ ├── 299. Bulls and Cows.md
│ ├── 348. Design Tic-Tac-Toe.md
│ ├── 350. Intersection of Two Arrays II.md
│ ├── 380. Insert Delete GetRandom O(1).md
│ ├── 49. Group Anagrams.md
│ ├── 706. Design HashMap.md
│ ├── 73. Set Matrix Zeroes.md
│ └── README.md
├── 04_string
│ ├── 151. Reverse Words in a String.md
│ ├── 186. Reverse Words in a String II.md
│ ├── 205. Isomorphic Strings.md
│ ├── 242. Valid Anagram.md
│ ├── 28. Find the Index of the First Occurrence in a String.md
│ ├── 647. Palindromic Substrings.md
│ ├── 696. Count Binary Substrings.md
│ └── README.md
├── 05_stack_queue
│ ├── 1209. Remove All Adjacent Duplicates in String II.md
│ ├── 1249. Minimum Remove to Make Valid Parentheses.md
│ ├── 1429. First Unique Number.md
│ ├── 1472. Design Browser History.md
│ ├── 150. Evaluate Reverse Polish Notation.md
│ ├── 155. Min Stack.md
│ ├── 20. Valid Parentheses.md
│ ├── 224. Basic Calculator.md
│ ├── 225. Implement Stack using Queues.md
│ ├── 232. Implement Queue using Stacks.md
│ ├── 239. Sliding Window Maximum.md
│ ├── 281. Zigzag Iterator.md
│ ├── 346. Moving Average from Data Stream.md
│ ├── 362. Design Hit Counter.md
│ ├── 503. Next Greater Element II.md
│ ├── 54. Spiral Matrix.md
│ ├── 735. Asteroid Collision.md
│ ├── 736. Parse Lisp Expression.md
│ ├── 739. Daily Temperatures.md
│ ├── 84. Largest Rectangle in Histogram.md
│ ├── 85. Maximum Rectangle.md
│ ├── 901. Online Stock Span.md
│ ├── 907. Sum of Subarray Minimums.md
│ └── README.md
├── 06_heap
│ ├── 1086. High Five.md
│ ├── 1438. Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit.md
│ ├── 1705. Maximum Number of Eaten Apples.md
│ ├── 1845. Seat Reservation Manager.md
│ ├── 23. Merge K Sorted Lists.md
│ ├── 2542. Maximum Subsequence Score.md
│ ├── 264. Ugly Number II.md
│ ├── 295. Find Median from Data Stream.md
│ ├── 347. Top K Frequent Elements.md
│ ├── 378. Kth Smallest Element in a Sorted Matrix.md
│ ├── 692. Top K Frequent Words.md
│ ├── 767. Reorganize String.md
│ ├── 895. Maximum Frequency Stack.md
│ ├── 973. K Closest Points.md
│ └── README.md
├── 07_dfs
│ ├── 101. Symmetric Tree.md
│ ├── 104. Maximum Depth of Binary Tree.md
│ ├── 105. Construct Binary Tree from Preorder and Inorder Traversal.md
│ ├── 108. Convert Sorted Array to Binary Search Tree.md
│ ├── 1087. Brace Expansion.md
│ ├── 1110. Delete Nodes And Return Forest.md
│ ├── 113. Path Sum II .md
│ ├── 124. Binary Tree Maximum Path Sum.md
│ ├── 126. Word Ladder II.md
│ ├── 1274. Number of Ships in a Rectangle.md
│ ├── 131. Palindrome Partitioning.md
│ ├── 1376. Time Needed to Inform All Employees.md
│ ├── 139. Word Break.md
│ ├── 1485. Clone Binary Tree With Random Pointer.md
│ ├── 17. Letter Combinations of a Phone Number.md
│ ├── 212. Word Search II.md
│ ├── 22. Generate Parentheses.md
│ ├── 226. Invert Binary Tree.md
│ ├── 230. Kth Smallest element in a BST.md
│ ├── 235. Lowest Common Ancestor of a Binary Search Tree.md
│ ├── 236. Lowest Common Ancestor of a Binary Tree.md
│ ├── 270. Closest Binary Search Tree Value.md
│ ├── 285. Inorder Successor in BST.md
│ ├── 291. Word Pattern II.md
│ ├── 301. Remove Invalid Parentheses.md
│ ├── 329. Longest Increasing Path in a Matrix.md
│ ├── 333. Largest BST Subtree.md
│ ├── 341. Flatten Nested List Iterator.md
│ ├── 37. Sodoku Solver.md
│ ├── 377. Combination Sum IV.md
│ ├── 39. Combination Sum.md
│ ├── 394. Decode String.md
│ ├── 399. Evaluate Division.md
│ ├── 403. Frog Jump.md
│ ├── 450. Delete Node in a BST.md
│ ├── 46. Permutation.md
│ ├── 472. Concatenated Words.md
│ ├── 491. Non-decreasing Subsequences.md
│ ├── 51. N-Queens.md
│ ├── 526. Beautiful Arrangement.md
│ ├── 543. Diameter of Binary Tree.md
│ ├── 572. Subtree of Another Tree.md
│ ├── 669. Trim a Binary Search Tree.md
│ ├── 694. Number of Distinct Islands.md
│ ├── 695. Max Area of Island.md
│ ├── 698. Partition to K Equal Sum Subsets.md
│ ├── 700. Search in a Binary Search Tree.md
│ ├── 77. Combinations.md
│ ├── 78. Subsets.md
│ ├── 79. Word Search.md
│ ├── 797. All Paths From Source to Target.md
│ ├── 856. Score of Parentheses.md
│ ├── 863. All Nodes Distance K in Binary Tree.md
│ ├── 93. Restore IP Addresses.md
│ ├── 938. Range Sum of BST.md
│ ├── 951. Flip Equivalent Binary Trees.md
│ ├── 98. Validate Binary Search Tree.md
│ ├── 987. Vertical Order Traversal of a Binary Tree.md
│ └── README.md
├── 08_bfs
│ ├── 102. Binary Tree Level Order Traversal.md
│ ├── 103. Binary Tree Zigzag Level Order Traversal.md
│ ├── 1091. Shortest Path in Binary Matrix.md
│ ├── 127. Word Ladder.md
│ ├── 1293. Shortest Path in a Grid with Obstacles Elimination.md
│ ├── 130. Surrounded Regions.md
│ ├── 133. Clone Graph.md
│ ├── 1514. Path with Maximum Probability.md
│ ├── 200. Number of Islands.md
│ ├── 207. Course Schedule.md
│ ├── 210. Course Schedule II.md
│ ├── 269. Alien Dictionary.md
│ ├── 297. Serialize and Deserialize Binary Tree.md
│ ├── 310. Minimum Height Trees.md
│ ├── 314. Binary Tree Vertical Order Traversal.md
│ ├── 323. Connected Component in Undirected Graph.md
│ ├── 366. Find Leaves of Binary Tree.md
│ ├── 417. Pacific Atlantic Water Flow.md
│ ├── 444. Sequence Reconstruction.md
│ ├── 490. The Maze.md
│ ├── 542. 01 Matrix.md
│ ├── 752. Open the Lock.md
│ ├── 785. Is Graph Bipartite?.md
│ ├── 787. Cheapest Flights Within K Stops.md
│ ├── 815. Bus Routes.md
│ ├── 934. Shortest Bridge.md
│ ├── 994. Rotting Oranges.md
│ └── README.md
├── 09_dynamic_program
│ ├── 10. Regular Expression Matching.md
│ ├── 1043. Partition Array for Maximum Sum.md
│ ├── 1048. Longest String Chain.md
│ ├── 1062. Longest Repeating Substring.md
│ ├── 1140. Stone Game II.md
│ ├── 1143. Longest Common Subsequence.md
│ ├── 115. Distinct Subsequences.md
│ ├── 121. Best Time to Buy and Sell Stock.md
│ ├── 1216. Valid Palindrome III.md
│ ├── 1235. Maximum Profit in Job Scheduling.md
│ ├── 1277. Count Square Submatrices with All Ones.md
│ ├── 132. Palindrome Partitioning II.md
│ ├── 1335. Minimum Difficulty of a Job Schedule.md
│ ├── 174. Dungeon Game.md
│ ├── 198. House Robber.md
│ ├── 213. House Robber II.md
│ ├── 221. Maximal Square.md
│ ├── 256. Paint House.md
│ ├── 300. Longest Increasing Subsequence.md
│ ├── 312. Burst Balloons.md
│ ├── 32. Longest Valid Parentheses.md
│ ├── 322. Coin Change.md
│ ├── 354. Russian Doll Envelopes.md
│ ├── 368. Largest Divisible Subset.md
│ ├── 377. Combination Sum IV.md
│ ├── 403. Frog Jump.md
│ ├── 44. Wildcard Matching.md
│ ├── 465. Optimal Account Balancing.md
│ ├── 472. Concatenated Words.md
│ ├── 518. Coin Change II.md
│ ├── 62. Unique Paths.md
│ ├── 639. Decode Ways II.md
│ ├── 64. Minimum Path Sum.md
│ ├── 674. Longest Continuous Increasing Subsequence.md
│ ├── 70. Climbing Stairs.md
│ ├── 712. Minimum ASCII Delete Sum for Two Strings.md
│ ├── 718. Maximum Length of Repeated Subarray.md
│ ├── 72. Edit Distance.md
│ ├── 740. Delete and Earn.md
│ ├── 87. Scramble String.md
│ ├── 91. Decode Ways.md
│ ├── 926. Flip String to Monotone Increasing.md
│ ├── 97. Interleaving String.md
│ └── README.md
├── 10_greedy
│ ├── 1005. Maximize Sum Of Array After K Negations.md
│ ├── 134. Gas Station.md
│ ├── 135. Candy.md
│ ├── 376. Wiggle Subsequence.md
│ ├── 406. Queue Reconstruction by Height.md
│ ├── 452. Minimum Number of Arrows to Burst Balloons.md
│ ├── 55. Jump Game.md
│ ├── 56. Merge Intervals.md
│ ├── 621. Task Scheduler.md
│ ├── 738. Monotone Increasing Digits.md
│ ├── 763. Partition Labels.md
│ └── README.md
├── 11_prefix_sum
│ ├── 1031. Maximum Sum of Two Non-Overlapping Subarrays.md
│ ├── 1423. Maximum Points You Can Obtain from Cards.md
│ ├── 304. Range Sum Query 2D - Immutable.md
│ ├── 523. Continuous Subarray Sum.md
│ ├── 53. Maximum Subarray.md
│ └── README.md
├── 12_union_find
│ ├── 305. Number of Islands II.md
│ ├── 547. Number of Provinces.md
│ ├── 684. Redundant Connection.md
│ ├── 721. Accounts Merge.md
│ ├── 737. Sentence Similarity II.md
│ └── README.md
├── 13_trie
│ ├── 1166. Design File System.md
│ ├── 1268. Search Suggestions System.md
│ ├── 208. Implement Trie.md
│ ├── 211. Design Add and Search Words Data Structure.md
│ ├── 642. Design Search Autocomplete System.md
│ └── README.md
├── 14_sweep_line
│ ├── 1094. Car Pooling.md
│ ├── 218. The Skyline Problem.md
│ ├── 253. Meeting Room II.md
│ ├── 759. Employee Free Time.md
│ └── README.md
├── 15_tree_map
│ ├── 318. Count of Smaller Numbers After Self.md
│ ├── 480. Sliding Window Median.md
│ ├── 729. My Calendar I.md
│ ├── 846. Hand of Straights.md
│ ├── 981. Time Based Key-Value Store.md
│ └── README.md
├── 16_math
│ ├── 1227. Airplane Seat Assignment Probability.md
│ ├── 1570. Dot Product of Two Sparse Vectors.md
│ ├── 204. Count Primes.md
│ ├── 29. Divide Two Integers.md
│ ├── 311. Sparse Matrix Multiplication.md
│ ├── 382. Linked List Random Node.md
│ ├── 398. Random Pick Index.md
│ ├── 50. Pow(x, n).md
│ └── README.md
├── 17_design
│ ├── 1116. Print Zero Even Odd.md
│ ├── 1236. Web Crawler.md
│ ├── 1244. Design A Leaderboard.md
│ ├── 1396. Design Underground System.md
│ ├── 1603. Design Parking System.md
│ ├── 353. Design Snake Game.md
│ ├── 355. Design Twitter.md
│ ├── 359. Logger Rate Limiter.md
│ ├── 379. Design Phone Directory.md
│ ├── 588. Design In-Memory File System.md
│ └── README.md
├── 18_segment_tree
│ └── 307. Range Sum Query - Mutable.md
├── 99_SQL
│ └── README.md
└── README.md
├── 02_ml
├── 00_ml_math.md
├── 01_metrics.md
├── 02_linear_regression.md
├── 03_logistic_regression.md
├── 04_tree.md
├── 05_deep_learning.md
├── 06_svm.md
├── 07_knn.md
├── 08_unsuperwised.md
├── 09_k_means.md
├── 10_reinforcement.md
├── 11_nlp.md
├── 12_llm.md
├── 13_vision.md
├── 14_multimodal.md
├── 15_distributed_ml.md
├── 16_anomaly.md
├── 17_recommendation.md
├── 18_interpretability.md
├── 19_multi_task.md
├── 20_mlops.md
├── 21_feature_engineering.md
├── 22_online_learning.md
├── 23_hardware.md
├── 97_product_sense.md
├── 98_project.md
├── 99_ml_coding.md
└── README.md
├── 03_system
├── 01_ood
│ ├── README.md
│ ├── lift.md
│ ├── parking_lot.md
│ └── unix_file.md
├── 02_system
│ ├── README.md
│ ├── ad_click_aggregator.md
│ ├── big data.md
│ ├── chat_system.md
│ ├── crawler.md
│ ├── database.md
│ ├── distributed_cache.md
│ ├── eta.md
│ ├── job_scheduler.md
│ ├── log_system.md
│ ├── payment_system.md
│ ├── rate_limiter.md
│ ├── tinyurl.md
│ ├── top_k.md
│ ├── twitter.md
│ ├── webhood.md
│ └── youtube.md
├── 03_ml
│ ├── README.md
│ ├── ad_click.md
│ ├── agent.md
│ ├── coupon_deliver.md
│ ├── deduplicate_detection.md
│ ├── fraud_detection.md
│ ├── friend_recommedation.md
│ ├── harmful_content_detection.md
│ ├── knowledge_graph_qa.md
│ ├── loan_decision.md
│ ├── news_feed.md
│ ├── object_detection.md
│ ├── poi_recommendation.md
│ ├── qa.md
│ ├── rag.md
│ ├── recommendation.md
│ ├── search_box.md
│ ├── search_engine.md
│ ├── sentiment_analysis.md
│ ├── text_generation.md
│ ├── twitter_recommendation.md
│ ├── video_recommendation.md
│ └── video_search.md
└── README.md
├── 04_bq
├── 01_leadership_principles.md
├── 02_examples.md
└── README.md
├── 05_case
├── 01_pre_interview.md
├── 02_cheat_sheet.md
├── 03_post_interview.md
└── README.md
├── README.md
└── SUMMARY.md
/.github/assets/02ml-binary_logistic_loss.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/02ml-binary_logistic_loss.png
--------------------------------------------------------------------------------
/.github/assets/02ml-confusion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/02ml-confusion.png
--------------------------------------------------------------------------------
/.github/assets/02ml-deployment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/02ml-deployment.png
--------------------------------------------------------------------------------
/.github/assets/02ml-feature_store.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/02ml-feature_store.png
--------------------------------------------------------------------------------
/.github/assets/02ml-llm-rag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/02ml-llm-rag.png
--------------------------------------------------------------------------------
/.github/assets/02ml-llm-resource.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/02ml-llm-resource.png
--------------------------------------------------------------------------------
/.github/assets/02ml-retraining.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/02ml-retraining.png
--------------------------------------------------------------------------------
/.github/assets/02ml-rlhf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/02ml-rlhf.png
--------------------------------------------------------------------------------
/.github/assets/02ml-sd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/02ml-sd.png
--------------------------------------------------------------------------------
/.github/assets/02ml-tree.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/02ml-tree.png
--------------------------------------------------------------------------------
/.github/assets/02ml-xgboost.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/02ml-xgboost.jpg
--------------------------------------------------------------------------------
/.github/assets/03ml-ad-pipe2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-ad-pipe2.png
--------------------------------------------------------------------------------
/.github/assets/03ml-ad-sys.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-ad-sys.png
--------------------------------------------------------------------------------
/.github/assets/03ml-adclick-ad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-adclick-ad.png
--------------------------------------------------------------------------------
/.github/assets/03ml-adclick-pipe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-adclick-pipe.png
--------------------------------------------------------------------------------
/.github/assets/03ml-adclick-user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-adclick-user.png
--------------------------------------------------------------------------------
/.github/assets/03ml-audio.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-audio.png
--------------------------------------------------------------------------------
/.github/assets/03ml-content-encoding.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-content-encoding.png
--------------------------------------------------------------------------------
/.github/assets/03ml-content-fewshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-content-fewshot.png
--------------------------------------------------------------------------------
/.github/assets/03ml-content-pipe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-content-pipe.png
--------------------------------------------------------------------------------
/.github/assets/03ml-friend-edge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-friend-edge.png
--------------------------------------------------------------------------------
/.github/assets/03ml-friend-pipe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-friend-pipe.png
--------------------------------------------------------------------------------
/.github/assets/03ml-friend-rank.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-friend-rank.png
--------------------------------------------------------------------------------
/.github/assets/03ml-loan-feature.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-loan-feature.png
--------------------------------------------------------------------------------
/.github/assets/03ml-loan-feature2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-loan-feature2.png
--------------------------------------------------------------------------------
/.github/assets/03ml-loan-inference.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-loan-inference.png
--------------------------------------------------------------------------------
/.github/assets/03ml-loan-train.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-loan-train.png
--------------------------------------------------------------------------------
/.github/assets/03ml-qa-all.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-qa-all.png
--------------------------------------------------------------------------------
/.github/assets/03ml-qa-event.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-qa-event.png
--------------------------------------------------------------------------------
/.github/assets/03ml-qa-kbqa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-qa-kbqa.png
--------------------------------------------------------------------------------
/.github/assets/03ml-qa-kbqa2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-qa-kbqa2.png
--------------------------------------------------------------------------------
/.github/assets/03ml-qa-pipe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-qa-pipe.png
--------------------------------------------------------------------------------
/.github/assets/03ml-rag.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-rag.jpeg
--------------------------------------------------------------------------------
/.github/assets/03ml-reco-cases.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-reco-cases.png
--------------------------------------------------------------------------------
/.github/assets/03ml-reco-metrics.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-reco-metrics.png
--------------------------------------------------------------------------------
/.github/assets/03ml-reco-other.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-reco-other.png
--------------------------------------------------------------------------------
/.github/assets/03ml-reco-otto-sirus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-reco-otto-sirus.png
--------------------------------------------------------------------------------
/.github/assets/03ml-reco-rank.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-reco-rank.png
--------------------------------------------------------------------------------
/.github/assets/03ml-reco-recall-model.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-reco-recall-model.png
--------------------------------------------------------------------------------
/.github/assets/03ml-reco-recall.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-reco-recall.png
--------------------------------------------------------------------------------
/.github/assets/03ml-reco-user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-reco-user.png
--------------------------------------------------------------------------------
/.github/assets/03ml-reco.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-reco.png
--------------------------------------------------------------------------------
/.github/assets/03ml-retrieval.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-retrieval.png
--------------------------------------------------------------------------------
/.github/assets/03ml-search-engine-pipe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-search-engine-pipe.png
--------------------------------------------------------------------------------
/.github/assets/03ml-search-engine-pipe2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-search-engine-pipe2.png
--------------------------------------------------------------------------------
/.github/assets/03ml-sentiment-pipe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-sentiment-pipe.png
--------------------------------------------------------------------------------
/.github/assets/03ml-twitter-reco.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-twitter-reco.png
--------------------------------------------------------------------------------
/.github/assets/03ml-vsearch-loss.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-vsearch-loss.png
--------------------------------------------------------------------------------
/.github/assets/03ml-vsearch-pipe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-vsearch-pipe.png
--------------------------------------------------------------------------------
/.github/assets/03ml-vsearch-pipe2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-vsearch-pipe2.png
--------------------------------------------------------------------------------
/.github/assets/03ml-vsearch-text.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-vsearch-text.png
--------------------------------------------------------------------------------
/.github/assets/03ml-vsearch-video.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-vsearch-video.png
--------------------------------------------------------------------------------
/.github/assets/03ml-youtube-reco-rank-cross.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-youtube-reco-rank-cross.png
--------------------------------------------------------------------------------
/.github/assets/03ml-youtube-reco-rank-model.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-youtube-reco-rank-model.png
--------------------------------------------------------------------------------
/.github/assets/03ml-youtube-reco-rank-user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-youtube-reco-rank-user.png
--------------------------------------------------------------------------------
/.github/assets/03ml-youtube-reco-rank-video.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-youtube-reco-rank-video.png
--------------------------------------------------------------------------------
/.github/assets/03ml-youtube-reco-rank.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-youtube-reco-rank.png
--------------------------------------------------------------------------------
/.github/assets/03ml-youtube-reco-retrieval-model.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-youtube-reco-retrieval-model.png
--------------------------------------------------------------------------------
/.github/assets/03ml-youtube-reco-retrieval-twotower.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-youtube-reco-retrieval-twotower.png
--------------------------------------------------------------------------------
/.github/assets/03ml-youtube-reco-retrieval.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-youtube-reco-retrieval.png
--------------------------------------------------------------------------------
/.github/assets/03ml-youtube-reco-structure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/03ml-youtube-reco-structure.png
--------------------------------------------------------------------------------
/.github/assets/pair document.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/pair document.png
--------------------------------------------------------------------------------
/.github/assets/query embedding.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/query embedding.png
--------------------------------------------------------------------------------
/.github/assets/text.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LongxingTan/Machine-learning-interview/047ac3d0a81a0a5901383ce4a5ed0807e56c1f1e/.github/assets/text.png
--------------------------------------------------------------------------------
/01_leetcode/00_array/179. Largest Number.md:
--------------------------------------------------------------------------------
1 | # 179. Largest Number
2 |
3 | [https://leetcode.com/problems/largest-number/](https://leetcode.com/problems/largest-number/)
4 |
5 | ## solution
6 |
7 | - 自定义排序key: 两两比较 `functools.cmp_to_key`
8 |
9 | ```python
10 | import functools
11 |
12 | class Solution:
13 | def largestNumber(self, nums: List[int]) -> str:
14 | def comparator(s1, s2):
15 | if int(s1 + s2) < int(s2 + s1):
16 | return -1
17 | if int(s1 + s2) > int(s2 + s1):
18 | return 1
19 | return 0
20 |
21 | nums = [str(i) for i in nums]
22 | nums = sorted(nums, key = functools.cmp_to_key(comparator), reverse=True)
23 | ans = '0' if nums[0] == '0' else ''.join(nums)
24 | return ans
25 | ```
26 |
27 | 时间复杂度:O(sort)
28 | 空间复杂度:O(n)
29 |
--------------------------------------------------------------------------------
/01_leetcode/00_array/605. Can Place Flowers.md:
--------------------------------------------------------------------------------
1 | # 605. Can Place Flowers
2 |
3 | [https://leetcode.com/problems/can-place-flowers/](https://leetcode.com/problems/can-place-flowers/)
4 |
5 | ## solution
6 |
7 | ```python
8 | # 1. 为减少边界条件判断,前后各增加一块空地。注意循环的边界
9 | # 2. 为剪枝,从n开始倒计时
10 |
11 | class Solution:
12 | def canPlaceFlowers(self, flowerbed: List[int], n: int) -> bool:
13 | flowerbed = [0] + flowerbed + [0]
14 | res = 0
15 | for i in range(1, len(flowerbed) - 1):
16 | if flowerbed[i] == 0 and flowerbed[i-1] == 0 and flowerbed[i+1] == 0:
17 | res += 1
18 | flowerbed[i] = 1
19 | return n <= res
20 | ```
21 |
22 | 时间复杂度:O(n)
23 | 空间复杂度:O(1)
24 |
--------------------------------------------------------------------------------
/01_leetcode/00_array/977. Squares of a Sorted Array.md:
--------------------------------------------------------------------------------
1 | # 977. Squares of a Sorted Array
2 |
3 | [https://leetcode.com/problems/squares-of-a-sorted-array/](https://leetcode.com/problems/squares-of-a-sorted-array/)
4 |
5 | ## solution
6 |
7 | - 直接法
8 |
9 | ```python
10 | class Solution:
11 | def sortedSquares(self, nums: List[int]) -> List[int]:
12 | nums = [i*i for i in nums]
13 | return sorted(nums)
14 | ```
15 |
16 | 时间复杂度:O(nlog(n))
17 | 空间复杂度:O(n)
18 |
19 | - 双指针
20 |
21 | ```python
22 | class Solution:
23 | def sortedSquares(self, nums: List[int]) -> List[int]:
24 | l = 0
25 | r = len(nums) - 1
26 | res = []
27 | while r >= l: # 注意小于等于
28 | r2 = nums[r] ** 2
29 | l2 = nums[l] ** 2
30 | if r2 > l2:
31 | res.append(r2)
32 | r -= 1
33 | else:
34 | res.append(l2)
35 | l += 1
36 | return res[::-1]
37 | ```
38 |
39 | 时间复杂度:O(n)
40 | 空间复杂度:O(n)
41 |
--------------------------------------------------------------------------------
/01_leetcode/00_binary_search/1044. Longest Duplicate Substring.md:
--------------------------------------------------------------------------------
1 | # 1044. Longest Duplicate Substring
2 |
3 | [https://leetcode.com/problems/longest-duplicate-substring/description/](https://leetcode.com/problems/longest-duplicate-substring/description/)
4 |
5 | ## solution
6 |
7 | ```python
8 | # Binary search: "banana", the answer must between 0 to 5, we can guess 3 at the first time.
9 | # We will check every possible substring with length 3 to see if we can find any duplicate.
10 |
11 | class Solution:
12 | def longestDupSubstring(self, s: str) -> str:
13 | def has_duplicate(length):
14 | seen = set()
15 | for i in range(n - length + 1):
16 | substring = s[i : i + length]
17 | if substring in seen:
18 | return substring
19 | seen.add(substring)
20 | return ''
21 |
22 | n = len(s)
23 | left, right = 0, n
24 | longest_dup = ''
25 |
26 | while left < right:
27 | mid = (left + right + 1) // 2
28 | current_dup = has_duplicate(mid)
29 | longest_dup = current_dup or longest_dup
30 | if current_dup:
31 | left = mid
32 | else:
33 | right = mid - 1
34 |
35 | return longest_dup
36 | ```
37 |
38 | 时间复杂度:O(n^2log(n))
39 | 空间复杂度:O(n^2)
40 |
--------------------------------------------------------------------------------
/01_leetcode/00_binary_search/1060. Missing Element in Sorted Array.md:
--------------------------------------------------------------------------------
1 | # 1060. Missing Element in Sorted Array
2 |
3 | [https://leetcode.com/problems/missing-element-in-sorted-array/](https://leetcode.com/problems/missing-element-in-sorted-array/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def missingElement(self, nums: List[int], k: int) -> int:
10 | minn = nums[0]
11 |
12 | left = 0
13 | right = len(nums) - 1
14 | while left < right:
15 | mid = left + (right - left + 1) // 2
16 |
17 | if nums[mid] >= minn + k + mid:
18 | right = mid - 1
19 | else:
20 | left = mid
21 | return minn + left + k
22 | ```
23 |
24 | 时间复杂度:O()
25 | 空间复杂度:O()
26 |
27 | ## follow up
28 |
29 | [658. Find K Closest Elements](https://leetcode.com/problems/find-k-closest-elements/description/)
30 |
31 | ```python
32 | # 找到起点
33 |
34 | ```
35 |
--------------------------------------------------------------------------------
/01_leetcode/00_binary_search/1062. Longest Repeating Substring.md:
--------------------------------------------------------------------------------
1 | # 1062. Longest Repeating Substring
2 |
3 | [https://leetcode.com/problems/longest-repeating-substring/](https://leetcode.com/problems/longest-repeating-substring/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def longestRepeatingSubstring(self, s: str) -> int:
10 | n = len(s)
11 | dp_table = [[0] * n for _ in range(n)]
12 |
13 | max_length = 0
14 | for i in range(n):
15 | for j in range(i + 1, n):
16 | if s[i] == s[j]:
17 | dp_table[i][j] = dp_table[i - 1][j - 1] + 1 if i else 1
18 | max_length = max(max_length, dp_table[i][j])
19 |
20 | return max_length
21 | ```
22 |
23 | 时间复杂度:O()
24 | 空间复杂度:O()
25 |
--------------------------------------------------------------------------------
/01_leetcode/00_binary_search/1300. Sum of Mutated Array Closest to Target.md:
--------------------------------------------------------------------------------
1 | # 1300. Sum of Mutated Array Closest to Target
2 |
3 | [https://leetcode.com/problems/sum-of-mutated-array-closest-to-target/](https://leetcode.com/problems/sum-of-mutated-array-closest-to-target/)
4 |
5 | ## solution
6 |
7 | - prefix + binary search
8 |
9 | ```python
10 | class Solution:
11 | def findBestValue(self, arr: List[int], target: int) -> int:
12 | arr.sort()
13 | low, high = 0, arr[-1]
14 | memo = {}
15 | while low <= high:
16 | mid = low + (high - low) // 2
17 |
18 | count = 0
19 | for i in range(len(arr)):
20 | if arr[i] > mid:
21 | count += mid * (len(arr) - i)
22 | break
23 | else:
24 | count += arr[i]
25 |
26 | if count == target:
27 | return mid
28 |
29 | if count < target:
30 | low = mid + 1
31 | else:
32 | high = mid - 1
33 |
34 | memo[mid] = abs(count - target)
35 | return min(sorted(zip(memo.values(), memo.keys())))[1]
36 | ```
37 |
38 | 时间复杂度:O()
39 | 空间复杂度:O()
40 |
--------------------------------------------------------------------------------
/01_leetcode/00_binary_search/1891. Cutting Ribbons.md:
--------------------------------------------------------------------------------
1 | # 1891. Cutting Ribbons
2 |
3 | [https://leetcode.com/problems/cutting-ribbons/](https://leetcode.com/problems/cutting-ribbons/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def maxLength(self, ribbons: List[int], k: int) -> int:
10 | left = 0
11 | right = max(ribbons)
12 |
13 | while left < right:
14 | mid = (left + right + 1) // 2
15 | count = sum(ribbon // mid for ribbon in ribbons)
16 | if count >= k:
17 | left = mid
18 | else:
19 | right = mid - 1
20 |
21 | return left
22 | ```
23 |
24 | 时间复杂度:O()
25 | 空间复杂度:O()
26 |
--------------------------------------------------------------------------------
/01_leetcode/00_binary_search/2055. Plates Between Candles.md:
--------------------------------------------------------------------------------
1 | # 2055. Plates Between Candles
2 |
3 | [https://leetcode.com/problems/plates-between-candles/description/](https://leetcode.com/problems/plates-between-candles/description/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def platesBetweenCandles(self, s: str, queries: list[list[int]]) -> list[int]:
10 | ans = []
11 | indices = [i for i, c in enumerate(s) if c == '|'] # indices of '|'
12 |
13 | for left, right in queries:
14 | l = bisect.bisect_left(indices, left)
15 | r = bisect.bisect_right(indices, right) - 1
16 | if l < r:
17 | lengthBetweenCandles = indices[r] - indices[l] + 1
18 | numCandles = r - l + 1
19 | # 这里用indices计算中间的数量非常巧妙
20 | ans.append(lengthBetweenCandles - numCandles)
21 | else:
22 | ans.append(0)
23 | return ans
24 | ```
25 |
--------------------------------------------------------------------------------
/01_leetcode/00_binary_search/240. Search a 2D Matrix II.md:
--------------------------------------------------------------------------------
1 | # 240. Search a 2D Matrix II
2 |
3 | [https://leetcode.com/problems/search-a-2d-matrix-ii/](https://leetcode.com/problems/search-a-2d-matrix-ii/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
10 | m = len(matrix)
11 | n = len(matrix[0])
12 |
13 | i = 0
14 | j = n - 1
15 |
16 | while i < m and j >= 0:
17 | if matrix[i][j] > target:
18 | j -= 1
19 | elif matrix[i][j] < target:
20 | i += 1
21 | else:
22 | return True
23 | return False
24 | ```
25 |
26 | 时间复杂度:O(m+n)
27 | 空间复杂度:O(1)
28 |
--------------------------------------------------------------------------------
/01_leetcode/00_binary_search/278. First Bad Version.md:
--------------------------------------------------------------------------------
1 | # 278. First Bad Version
2 |
3 | [https://leetcode.com/problems/first-bad-version/](https://leetcode.com/problems/first-bad-version/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def firstBadVersion(self, n: int) -> int:
10 | return self.bs(1, n)
11 |
12 | def bs(self, l, r):
13 | while r > l:
14 | mid = l + (r - l) // 2
15 | if isBadVersion(mid):
16 | r = mid
17 | else:
18 | l = mid + 1
19 | return l
20 | ```
21 |
22 | 时间复杂度:O(log(n))
23 | 空间复杂度:O(1)
24 |
--------------------------------------------------------------------------------
/01_leetcode/00_binary_search/528. Random Pick with Weight.md:
--------------------------------------------------------------------------------
1 | # 528. Random Pick with Weight
2 |
3 | [https://leetcode.com/problems/random-pick-with-weight/](https://leetcode.com/problems/random-pick-with-weight/)
4 |
5 | ## solution
6 |
7 | ```python
8 | # 先构造一个累加的概率数组(prefix sum),然后用二分查找
9 | class Solution:
10 | def __init__(self, w):
11 | self.w = list(itertools.accumulate(w))
12 |
13 | def pickIndex(self):
14 | rand = random.randint(1, self.w[-1]) # 注意是1 ~ prefix sum的范围
15 | return bisect.bisect_left(self.w, rand)
16 | ```
17 |
18 | 时间复杂度:O(n) / O(log(n))
19 | 空间复杂度:O(n)
20 |
21 | ```python
22 | class Solution:
23 | def __init__(self, w: List[int]):
24 | self.accumulate_list = [w[0]]
25 | for i in range(1, len(w)):
26 | self.accumulate_list.append(self.accumulate_list[-1] + w[i])
27 |
28 | def pickIndex(self) -> int:
29 | # 注意rand从1开始选,但下面的l作为index仍然从0开始
30 | rand = random.randint(1, self.accumulate_list[-1])
31 |
32 | l = 0
33 | r = len(self.accumulate_list)
34 |
35 | while l < r:
36 | mid = l + (r - l) // 2
37 | if self.accumulate_list[mid] < rand:
38 | l = mid + 1
39 | else: # 第一个比rand大的index,等于时也shrink右边界
40 | r = mid
41 | return l
42 | ```
43 |
--------------------------------------------------------------------------------
/01_leetcode/00_binary_search/540. Single Element in a Sorted Array.md:
--------------------------------------------------------------------------------
1 | # 540. Single Element in a Sorted Array
2 |
3 | [https://leetcode.com/problems/single-element-in-a-sorted-array/](https://leetcode.com/problems/single-element-in-a-sorted-array/)
4 |
5 | ## solution
6 |
7 | - 有序数组查找问题,一般想到二分。和邻居比较来判断位于左右哪边.
8 | - 单独出现的元素其左边有偶数个元素,因此其下标index 为偶数
9 | - mid为偶数,如果 mid与mid+1值相等,则l=mid+2; 如果mid与mid+1不等,则r=mid
10 | - mid为奇数,mid-1变为偶数
11 |
12 | ```python
13 | class Solution:
14 | def singleNonDuplicate(self, nums: List[int]) -> int:
15 | l = 0
16 | r = len(nums) - 1
17 |
18 | while l < r:
19 | mid = l + (r - l) // 2
20 | if mid % 2 == 1:
21 | mid -= 1
22 |
23 | if nums[mid] == nums[mid+1]:
24 | l = mid + 2
25 | else:
26 | r = mid
27 | return nums[l]
28 | ```
29 |
30 | 时间复杂度:O(log(n))
31 | 空间复杂度:O(1)
32 |
--------------------------------------------------------------------------------
/01_leetcode/00_binary_search/644. Maximum Average Subarray II.md:
--------------------------------------------------------------------------------
1 | # 644. Maximum Average Subarray II
2 |
3 | [https://leetcode.com/problems/maximum-average-subarray-ii/](https://leetcode.com/problems/maximum-average-subarray-ii/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def findMaxAverage(self, nums: List[int], k: int) -> float:
10 | l = min(nums)
11 | r = max(nums)
12 |
13 | while l < r:
14 | mid = l + (r - l) // 2
15 | if self.check(nums, mid, k):
16 | l = mid
17 | else:
18 | r = mid
19 | return l
20 |
21 | def check(self, nums, mid, k):
22 | # Returns True if there's a subarray, where its length >= k and its average sum >= m
23 | summ = 0
24 | prev_sum = 0
25 | min_prev_sum = 0
26 | for i, num in enumerate(nums):
27 | summ += num - mid
28 | if i >= k:
29 | prev_sum += nums[i - k] - mid
30 | min_prev_sum = min(min_prev_sum, prev_sum)
31 | if i + 1 >= k and summ >= min_prev_sum:
32 | return True
33 | return False
34 | ```
35 |
36 | 时间复杂度:O()
37 | 空间复杂度:O()
38 |
--------------------------------------------------------------------------------
/01_leetcode/00_binary_search/69. Sqrt(x).md:
--------------------------------------------------------------------------------
1 | # 69. Sqrt(x)
2 |
3 | [https://leetcode.com/problems/sqrtx/](https://leetcode.com/problems/sqrtx/)
4 |
5 | ## solution
6 |
7 | - 二分法
8 | - 由于输入与输出都是整数,因此小数被truncated
9 |
10 | ```python
11 | class Solution:
12 | def mySqrt(self, x: int) -> int:
13 | # 左闭右闭
14 | l = 0
15 | r = x # 注意和列表差异,len(nums)-1, 但sqrt当x=0或1时要包含
16 | while l <= r:
17 | mid = l + (r - l) // 2
18 | if mid * mid == x:
19 | return mid
20 | elif mid * mid < x:
21 | l = mid + 1
22 | else:
23 | r = mid - 1
24 | return r # 注意输出, 可以输出l-1或输出r
25 | ```
26 |
27 | 时间复杂度:O(log(x))
28 | 空间复杂度:O(1)
29 |
30 | - 牛顿法
31 |
32 | ```python
33 |
34 | ```
35 |
36 | 时间复杂度:O()
37 | 空间复杂度:O()
38 |
--------------------------------------------------------------------------------
/01_leetcode/00_binary_search/81. Search in Rotated Sorted Array II.md:
--------------------------------------------------------------------------------
1 | # 81. Search in Rotated Sorted Array II
2 |
3 | [https://leetcode.com/problems/search-in-rotated-sorted-array-ii/](https://leetcode.com/problems/search-in-rotated-sorted-array-ii/)
4 |
5 | ## solution
6 |
7 | - 存在重复值
8 | - 返回的值是否存在
9 |
10 | ```python
11 | class Solution:
12 | def search(self, nums: List[int], target: int) -> bool:
13 | if not nums:
14 | return False
15 |
16 | l = 0
17 | r = len(nums) - 1
18 |
19 | while l <= r:
20 | mid = l + (r - l) // 2
21 | if nums[mid] == target:
22 | return True
23 |
24 | if nums[mid] == nums[l]: # Fail to estimate which side is sorted, if的这一环节一开始没想到
25 | l += 1 # In worst case here: O(n)
26 |
27 | elif nums[mid] > nums[l]:
28 | if nums[mid] > target >= nums[l]:
29 | r = mid - 1
30 | else:
31 | l = mid + 1
32 | else:
33 | if nums[mid] < target <= nums[r]:
34 | l = mid + 1
35 | else:
36 | r = mid - 1
37 | return False
38 | ```
39 |
40 | 时间复杂度:O(n)
41 | 空间复杂度:O(1)
42 |
--------------------------------------------------------------------------------
/01_leetcode/01_two_pointers/1004. Max Consecutive Ones III.md:
--------------------------------------------------------------------------------
1 | # 1004 Max Consecutive Ones III
2 |
3 | [https://leetcode.com/problems/max-consecutive-ones-iii/](https://leetcode.com/problems/max-consecutive-ones-iii/)
4 |
5 | ## solution
6 |
7 | - 滑动窗口中的window里不超过k个0的最长子串
8 |
9 | ```python
10 | class Solution:
11 | def longestOnes(self, nums: List[int], k: int) -> int:
12 | l = 0
13 | counter = collections.defaultdict(int)
14 | res = 0
15 |
16 | for r in range(len(nums)):
17 | counter[nums[r]] += 1
18 | while counter[0] > k:
19 | counter[nums[l]] -= 1
20 | l += 1
21 |
22 | res = max(res, r - l + 1)
23 | return res
24 | ```
25 |
26 | 时间复杂度:O(n)
27 | 空间复杂度:O(1)
28 |
29 | ## follow up
30 |
31 | [\*487. Max Consecutive Ones II](https://leetcode.com/problems/max-consecutive-ones-ii/description/)
32 |
33 | ```python
34 |
35 | ```
36 |
--------------------------------------------------------------------------------
/01_leetcode/01_two_pointers/11. Container With Most Water.md:
--------------------------------------------------------------------------------
1 | # 11. Container With Most Water
2 |
3 | [https://leetcode.com/problems/container-with-most-water/](https://leetcode.com/problems/container-with-most-water/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def maxArea(self, height: List[int]) -> int:
10 | l = 0
11 | r = len(height) - 1
12 | res = 0
13 | while l < r:
14 | res = max(res, min(height[l], height[r]) * (r - l))
15 | if height[l] < height[r]:
16 | l += 1
17 | elif height[l] > height[r]:
18 | r -= 1
19 | else:
20 | l += 1
21 | r -= 1
22 | return res
23 | ```
24 |
25 | 时间复杂度:O(1)
26 | 空间复杂度:O(1)
27 |
--------------------------------------------------------------------------------
/01_leetcode/01_two_pointers/125. Valid Palindrome.md:
--------------------------------------------------------------------------------
1 | # 125. Valid Palindrome
2 |
3 | [https://leetcode.com/problems/valid-palindrome/](https://leetcode.com/problems/valid-palindrome/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def isPalindrome(self, s: str) -> bool:
10 | s = s.lower()
11 | s = [i for i in s if i.isalnum()] # isdigit, isalpha, isalnum(alphanumeric)
12 | return s[::-1] == s
13 | ```
14 |
15 | 时间复杂度:O()
16 | 空间复杂度:O()
17 |
18 | ## follow up
19 |
20 | - 怎么处理特殊符号/regex
21 |
22 | [回文类](../01_two_pointers/5.%20Longest%20Palindromic%20Substring.md)
23 |
--------------------------------------------------------------------------------
/01_leetcode/01_two_pointers/16. 3Sum Closest.md:
--------------------------------------------------------------------------------
1 | # 16. 3Sum Closest
2 |
3 | [https://leetcode.com/problems/3sum-closest/](https://leetcode.com/problems/3sum-closest/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def threeSumClosest(self, nums: List[int], target: int) -> int:
10 | nums.sort()
11 | cloest_sum = float('inf')
12 | cloest_dis = float('inf')
13 |
14 | for i in range(len(nums) - 2):
15 | l = i + 1
16 | r = len(nums) - 1
17 |
18 | while l < r:
19 | total_sum = nums[i] + nums[l] + nums[r]
20 | if abs(total_sum - target) < cloest_dis:
21 | cloest_dis = abs(total_sum - target)
22 | cloest_sum = total_sum
23 |
24 | if total_sum == target:
25 | l += 1
26 | r -= 1
27 | elif total_sum > target:
28 | r -= 1
29 | else:
30 | l += 1
31 | return cloest_sum
32 | ```
33 |
34 | 时间复杂度:O(n^2)
35 | 空间复杂度:O()
36 |
37 | ## follow up
38 |
39 | [259. 3Sum Smaller](https://leetcode.com/problems/3sum-smaller/)
40 |
--------------------------------------------------------------------------------
/01_leetcode/01_two_pointers/1658. Minimum Operations to Reduce X to Zero.md:
--------------------------------------------------------------------------------
1 | # 1658 Minimum Operations to Reduce X to Zero
2 |
3 | [https://leetcode.com/problems/minimum-operations-to-reduce-x-to-zero/](https://leetcode.com/problems/minimum-operations-to-reduce-x-to-zero/)
4 |
5 | ## solution
6 |
7 | - 任务转化为求等于(sum-x)的最长子串,等于时更新结果
8 |
9 | ```python
10 | class Solution:
11 | def minOperations(self, nums: List[int], x: int) -> int:
12 | target = sum(nums) - x
13 |
14 | l = 0
15 | prefix_sum = 0
16 | res = 0
17 | found = False
18 | for r, num in enumerate(nums):
19 | prefix_sum += num
20 |
21 | while l <= r and prefix_sum > target:
22 | prefix_sum -= nums[l]
23 | l += 1
24 |
25 | if prefix_sum == target:
26 | found = True
27 | res = max(res, r - l + 1)
28 |
29 | return len(nums) - res if found else -1
30 | ```
31 |
32 | 时间复杂度:O(n)
33 | 空间复杂度:O(1)
34 |
--------------------------------------------------------------------------------
/01_leetcode/01_two_pointers/167. Two Sum II - Input array is sorted.md:
--------------------------------------------------------------------------------
1 | # 167. Two Sum II - Input array is sorted
2 |
3 | [https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/](https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/)
4 |
5 | ## solution
6 |
7 | - 注意两个index不一定连续
8 |
9 | ```python
10 | class Solution:
11 | def twoSum(self, numbers: List[int], target: int) -> List[int]:
12 | l = 0
13 | r = len(numbers) - 1
14 | while l < r:
15 | s = numbers[l] + numbers[r]
16 | if s == target:
17 | return [l+1, r+1]
18 | elif s < target:
19 | l += 1
20 | else:
21 | r -= 1
22 | ```
23 |
24 | 时间复杂度:O()
25 | 空间复杂度:O()
26 |
--------------------------------------------------------------------------------
/01_leetcode/01_two_pointers/18. 4Sum.md:
--------------------------------------------------------------------------------
1 | # 18. 4Sum
2 |
3 | [https://leetcode.com/problems/4sum/description/](https://leetcode.com/problems/4sum/description/)
4 |
5 | ## solution
6 |
7 | - 如何分别对四个指针去重:i,j,l,r
8 |
9 | ```python
10 | class Solution:
11 | def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
12 | if len(nums) < 4:
13 | return []
14 |
15 | nums.sort()
16 | res = []
17 |
18 | for i in range(0, len(nums)):
19 | if i > 0 and nums[i] == nums[i-1]:
20 | continue
21 | for j in range(i+1, len(nums)):
22 | if j > i+1 and nums[j] == nums[j-1]:
23 | continue
24 |
25 | l = j + 1
26 | r = len(nums) - 1
27 |
28 | while l < r:
29 | total_sum = nums[i] + nums[j] + nums[l] + nums[r]
30 | if total_sum == target:
31 | res.append([nums[i], nums[j], nums[l], nums[r]])
32 | l += 1
33 | r -= 1
34 |
35 | while l < r and nums[l] == nums[l-1]:
36 | l += 1 # 这里的去重不是continue
37 | while l < r and nums[r] == nums[r+1]:
38 | r -= 1
39 | elif total_sum > target:
40 | r -= 1
41 | else:
42 | l += 1
43 | return res
44 | ```
45 |
46 | 时间复杂度:O(n^3)
47 | 空间复杂度:O(1)
48 |
--------------------------------------------------------------------------------
/01_leetcode/01_two_pointers/277. Find the Celebrity.md:
--------------------------------------------------------------------------------
1 | # 277. Find the Celebrity
2 |
3 | [https://leetcode.com/problems/find-the-celebrity/](https://leetcode.com/problems/find-the-celebrity/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def findCelebrity(self, n: int) -> int:
10 | candidate = 0
11 | for i in range(1, n):
12 | # If the candidate knows person i, then switch candidate to i
13 | if knows(candidate, i):
14 | candidate = i
15 |
16 | for i in range(n):
17 | if candidate != i:
18 | if knows(candidate, i) or not knows(i, candidate):
19 | return -1
20 | return candidate
21 | ```
22 |
23 | 时间复杂度:O(n)
24 | 空间复杂度:O(1)
25 |
--------------------------------------------------------------------------------
/01_leetcode/01_two_pointers/340. Longest Substring with At Most K Distinct Characters.md:
--------------------------------------------------------------------------------
1 | # 340. Longest Substring with At Most K Distinct Characters
2 |
3 | [https://leetcode.com/problems/longest-substring-with-at-most-k-distinct-characters/](https://leetcode.com/problems/longest-substring-with-at-most-k-distinct-characters/)
4 |
5 | ## solution
6 |
7 | - 至多包含 K 个不同字符的最长子串
8 |
9 | ```python
10 | from collections import Counter
11 |
12 | class Solution:
13 | def lengthOfLongestSubstringKDistinct(self, s: str, k: int) -> int:
14 | char_count = Counter()
15 |
16 | max_length = start_index = 0
17 | for i, char in enumerate(s):
18 | char_count[char] += 1
19 |
20 | while len(char_count) > k:
21 | char_count[s[start_index]] -= 1
22 |
23 | if char_count[s[start_index]] == 0:
24 | del char_count[s[start_index]]
25 |
26 | start_index += 1
27 |
28 | max_length = max(max_length, i - start_index + 1)
29 | return max_length
30 | ```
31 |
32 | 时间复杂度:O(n)
33 | 空间复杂度:O(k)
34 |
--------------------------------------------------------------------------------
/01_leetcode/01_two_pointers/409. Longest Palindrome.md:
--------------------------------------------------------------------------------
1 | # 409. Longest Palindrome
2 |
3 | [https://leetcode.com/problems/longest-palindrome/](https://leetcode.com/problems/longest-palindrome/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def longestPalindrome(self, s: str) -> int:
10 | ss = set()
11 | for letter in s:
12 | if letter not in ss:
13 | ss.add(letter)
14 | else:
15 | ss.remove(letter)
16 | if len(ss) != 0:
17 | return len(s) - len(ss) + 1
18 | else:
19 | return len(s)
20 | ```
21 |
22 | 时间复杂度:O()
23 | 空间复杂度:O()
24 |
--------------------------------------------------------------------------------
/01_leetcode/01_two_pointers/424. Longest Repeating Character Replacement.md:
--------------------------------------------------------------------------------
1 | # 424. Longest Repeating Character Replacement
2 |
3 | [https://leetcode.com/problems/longest-repeating-character-replacement/](https://leetcode.com/problems/longest-repeating-character-replacement/)
4 |
5 | ## solution
6 |
7 | - 转化为滑动窗口中,窗口里最多有k个其他字符的最长子串
8 |
9 | ```python
10 | class Solution:
11 | def characterReplacement(self, s: str, k: int) -> int:
12 | l = 0
13 | res = 0
14 | mydict = collections.defaultdict(int)
15 |
16 | for r in range(len(s)):
17 | mydict[s[r]] += 1
18 |
19 | while (r - l + 1) - max(mydict.values()) > k:
20 | if mydict[s[l]] > 0:
21 | mydict[s[l]] -= 1
22 | l += 1
23 |
24 | res = max(res, r - l + 1)
25 | return res
26 | ```
27 |
28 | 时间复杂度:O(n)
29 | 空间复杂度:O(1)
30 |
--------------------------------------------------------------------------------
/01_leetcode/01_two_pointers/454. 4Sum II.md:
--------------------------------------------------------------------------------
1 | # 454. 4Sum II
2 |
3 | [https://leetcode.com/problems/4sum-ii/](https://leetcode.com/problems/4sum-ii/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
10 | dict1 = {}
11 | for i in nums1:
12 | for j in nums2:
13 | if i + j in dict1:
14 | dict1[i+j] += 1
15 | else:
16 | dict1[i+j] = 1
17 |
18 | res = 0
19 | for m in nums3:
20 | for n in nums4:
21 | if -m-n in dict1:
22 | res += dict1[-m-n]
23 | return res
24 | ```
25 |
26 | 时间复杂度:O(n^2)
27 | 空间复杂度:O(n^2)
28 |
--------------------------------------------------------------------------------
/01_leetcode/01_two_pointers/75. Sort Colors.md:
--------------------------------------------------------------------------------
1 | # 75. Sort Colors
2 |
3 | [https://leetcode.com/problems/sort-colors/](https://leetcode.com/problems/sort-colors/)
4 |
5 | ## solution
6 |
7 | - three pointers, 两个在两边记录边界分割位置,一个用于循环
8 | - 一开始容易陷入思维陷阱的地方,会觉得交换后的现指针是否满足需求,但双指针只要确定好各个位置
9 |
10 | ```python
11 | class Solution:
12 | def sortColors(self, nums: List[int]) -> None:
13 | """
14 | Do not return anything, modify nums in-place instead.
15 | """
16 | cur = left = 0
17 | right = len(nums) - 1 # left记录最后一个0的位置,right记录第一个2的位置
18 | while cur <= right: # 小于等于
19 | if nums[cur] == 2:
20 | nums[cur], nums[right] = nums[right], nums[cur]
21 | right -= 1
22 | elif nums[cur] == 1:
23 | cur += 1
24 | else:
25 | nums[cur], nums[left] = nums[left], nums[cur]
26 | cur += 1
27 | left += 1
28 | ```
29 |
30 | 时间复杂度:O(n)
31 | 空间复杂度:O(1)
32 |
--------------------------------------------------------------------------------
/01_leetcode/01_two_pointers/README.md:
--------------------------------------------------------------------------------
1 | # 双指针
2 |
3 | - 同向双指针
4 | - 移除元素类
5 | - 滑动窗口
6 | - 数组类,用于正数,如果有负数采用hash/前缀和或DP.
7 | - 模式一:记录问题. 一般两个while, 或: 右指针for 左指针while收缩
8 | - 模式二:优化问题
9 | - 字符串类,用hash和计数器记录窗口内状态
10 | - 快慢指针类
11 | - 相向双指针
12 | - 模式与二分查找类似,每次明确可以只移动一个
13 |
14 | ## Reference
15 |
16 | - [Leetcode 同向双指针/滑动窗口类代码模板](https://zhuanlan.zhihu.com/p/390570255)
17 | - [双指针总结 - 邪恶总督的文章 - 知乎](https://zhuanlan.zhihu.com/p/553864541)
18 |
--------------------------------------------------------------------------------
/01_leetcode/02_linked_list/142. Linked List Cycle II.md:
--------------------------------------------------------------------------------
1 | # 142. Linked List Cycle II
2 |
3 | [https://leetcode.com/problems/linked-list-cycle-ii/](https://leetcode.com/problems/linked-list-cycle-ii/)
4 |
5 | ## solution
6 |
7 | - 链表的while循环条件
8 |
9 | ```python
10 | class Solution:
11 | def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
12 | if head is None or head.next is None:
13 | return None
14 |
15 | slow = head
16 | fast = head
17 | while fast is not None and fast.next is not None: # 注意这里的条件,先要确保有fast,才能确保有fast next
18 | slow = slow.next # 曾经在这里判断了二者不等才移动,但其实起点时二者也相等
19 | fast = fast.next.next
20 |
21 | if slow == fast:
22 | fast = head
23 |
24 | while slow != fast:
25 | slow = slow.next
26 | fast = fast.next
27 | return slow
28 | return None
29 | ```
30 |
31 | 时间复杂度:O(n)
32 | 空间复杂度:O(1)
33 |
--------------------------------------------------------------------------------
/01_leetcode/02_linked_list/160. Intersection of Two Linked Lists.md:
--------------------------------------------------------------------------------
1 | # 160. Intersection of Two Linked Lists
2 |
3 | [https://leetcode.com/problems/intersection-of-two-linked-lists/](https://leetcode.com/problems/intersection-of-two-linked-lists/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> Optional[ListNode]:
10 | l = []
11 | cur1 = headA
12 | while cur1 is not None:
13 | l.append(cur1)
14 | cur1 = cur1.next
15 |
16 | cur2 = headB
17 | while cur2 is not None:
18 | if cur2 in l:
19 | return cur2
20 | cur2 = cur2.next
21 | return None
22 | ```
23 |
24 | 时间复杂度:O()
25 | 空间复杂度:O()
26 |
27 | ```python
28 | class Solution:
29 | def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> Optional[ListNode]:
30 | stackA = ['A']
31 | stackB = ['B']
32 |
33 | while headA or headB:
34 | if headA:
35 | stackA.append(headA)
36 | headA = headA.next
37 |
38 | if headB:
39 | stackB.append(headB)
40 | headB = headB.next
41 |
42 | prev = None
43 | while stackA and stackB:
44 | nodeA = stackA.pop(-1)
45 | nodeB = stackB.pop(-1)
46 |
47 | if nodeA != nodeB:
48 | return prev
49 |
50 | prev = nodeA
51 | ```
52 |
--------------------------------------------------------------------------------
/01_leetcode/02_linked_list/328. Odd Even Linked List.md:
--------------------------------------------------------------------------------
1 | # 328. Odd Even Linked List
2 |
3 | [https://leetcode.com/problems/odd-even-linked-list/](https://leetcode.com/problems/odd-even-linked-list/)
4 |
5 | ## solution
6 |
7 | - 双指针
8 |
9 | ```python
10 | class Solution:
11 | def oddEvenList(self, head: Optional[ListNode]) -> Optional[ListNode]:
12 | if not head:
13 | return head
14 |
15 | odd = head
16 | even = head.next
17 | init_even_head = even # record the initial even
18 |
19 | while even and even.next: # 一下跨两步
20 | odd.next = even.next
21 | odd = odd.next
22 | even.next = odd.next
23 | even = even.next
24 | odd.next = init_even_head
25 | return head
26 | ```
27 |
28 | 时间复杂度:O(n)
29 | 空间复杂度:O(1)
30 |
31 | - 两段链表拼接
32 |
33 | ```python
34 | class Solution:
35 | def oddEvenList(self, head: Optional[ListNode]) -> Optional[ListNode]:
36 | if not head:
37 | return head
38 |
39 | dummy_odd = odd = ListNode(0, head)
40 | dummy_even = even = ListNode(0, head.next)
41 |
42 | while even and odd and odd.next:
43 | if odd.next:
44 | odd.next = odd.next.next
45 | if even.next:
46 | even.next = even.next.next
47 |
48 | odd = odd.next
49 | even = even.next
50 |
51 | odd.next = dummy_even.next
52 | return dummy_odd.next
53 | ```
54 |
--------------------------------------------------------------------------------
/01_leetcode/02_linked_list/876. Middle of the Linked List.md:
--------------------------------------------------------------------------------
1 | # 876. Middle of the Linked List
2 |
3 | [https://leetcode.com/problems/middle-of-the-linked-list/](https://leetcode.com/problems/middle-of-the-linked-list/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def middleNode(self, head: Optional[ListNode]) -> Optional[ListNode]:
10 | slow = fast = head
11 | while fast and fast.next:
12 | slow = slow.next
13 | fast = fast.next.next
14 | return slow
15 | ```
16 |
17 | 时间复杂度:O(n)
18 | 空间复杂度:O(1)
19 |
--------------------------------------------------------------------------------
/01_leetcode/02_linked_list/92. Reverse Linked List II.md:
--------------------------------------------------------------------------------
1 | # 92. Reverse Linked List II
2 |
3 | [https://leetcode.com/problems/reverse-linked-list-ii/](https://leetcode.com/problems/reverse-linked-list-ii/)
4 |
5 | ## solution
6 |
7 | - 迭代
8 |
9 | ```python
10 | class Solution:
11 | def reverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
12 | dummy = ListNode(val=-1, next=head)
13 |
14 | pre = dummy
15 | for _ in range(left - 1):
16 | pre = pre.next
17 |
18 | cur = pre.next
19 | for _ in range(right - left): # prev-cur-temp: 1234 -> 1324 -> 1432
20 | temp = cur.next
21 |
22 | cur.next = temp.next
23 | temp.next = pre.next # 注意这里是pre.next 而不是 cur
24 | pre.next = temp
25 | return dummy.next
26 | ```
27 |
28 | 时间复杂度:O(n)
29 | 空间复杂度:O(1)
30 |
31 | - 递归
32 |
33 | ```python
34 |
35 | ```
36 |
--------------------------------------------------------------------------------
/01_leetcode/02_linked_list/README.md:
--------------------------------------------------------------------------------
1 | # 链表
2 |
3 | ```python
4 | class ListNode():
5 | self.val = val
6 | self.next = next
7 | ```
8 |
9 | ## 基础
10 |
11 | - 单链表
12 | - 双链表
13 | - 循环链表
14 |
15 | **与列表Array的区别**
16 |
17 | - 列表Array的增和删复杂度O(n),查找O(1)
18 | - 链表List的增和删O(1),查找O(n)
19 |
20 | ## 技巧
21 |
22 | 链表反转和快慢指针几乎是所有链表类问题的基础
23 |
24 | - 头部加dummy node,便于返回整个链表头节点
25 |
26 | ```python
27 | dummy = ListNode(-1)
28 | dummy.next = head
29 | ```
30 |
31 | - 插入节点
32 |
33 | ```python
34 | new = ListNode(val=0)
35 | new.next = cur.next # 适当的先后顺序
36 | cur.next = new
37 | ```
38 |
39 | - 删除节点
40 |
41 | ```python
42 | cur.next = cur.next.next
43 | ```
44 |
--------------------------------------------------------------------------------
/01_leetcode/03_hash/1. Two Sum.md:
--------------------------------------------------------------------------------
1 | # 1. Two Sum
2 |
3 | [https://leetcode.com/problems/two-sum/description/](https://leetcode.com/problems/two-sum/description/)
4 |
5 | ## Solution
6 |
7 | - Brute Force
8 | - Use every element as an anchor and search its right element
9 |
10 | ```python
11 | class Solution:
12 | def twoSum(self, nums: List[int], target: int) -> List[int]:
13 | for i in range(len(nums)):
14 | for j in range(i+1, len(nums)):
15 | if nums[i] + nums[j] == target:
16 | return [i,j]
17 | ```
18 |
19 | 时间复杂度:O(n^2)
20 | 空间复杂度:O(1)
21 |
22 | - Hash Map
23 | - Leverage the power of hashmap and store the number and its index in the map
24 | - When the map contain target - curNum, we know the search is complete
25 |
26 | ```python
27 | class Solution:
28 | def twoSum(self, nums: List[int], target: int) -> List[int]:
29 | residual_dict = {}
30 |
31 | for i, num in enumerate(nums):
32 | if num in residual_dict:
33 | return [residual_dict[num], i]
34 | else:
35 | residual_dict[target - num] = i
36 | ```
37 |
38 | 时间复杂度:O(n)
39 | 空间复杂度:O(n)
40 |
--------------------------------------------------------------------------------
/01_leetcode/03_hash/299. Bulls and Cows.md:
--------------------------------------------------------------------------------
1 | # 299. Bulls and Cows
2 |
3 | [https://leetcode.com/problems/bulls-and-cows/](https://leetcode.com/problems/bulls-and-cows/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def getHint(self, secret: str, guess: str) -> str:
10 | a = {}
11 | b = {}
12 | for i in secret:
13 | if i in a:
14 | a[i] += 1
15 | else:
16 | a[i] = 1
17 | for i in guess:
18 | if i in b:
19 | b[i] += 1
20 | else:
21 | b[i] = 1
22 |
23 | bulls = 0
24 | for i in range(len(secret)): # Counting bulls
25 | if secret[i] == guess[i]:
26 | bulls += 1
27 | a[secret[i]] -= 1
28 | b[secret[i]] -= 1
29 | cows = 0
30 | for i in a: # Counting cows
31 | if i in b:
32 | cows += min(a[i], b[i])
33 | res = str(bulls) + "A" + str(cows) + "B"
34 | return res
35 | ```
36 |
37 | 时间复杂度:O(n)
38 | 空间复杂度:O(n)
39 |
--------------------------------------------------------------------------------
/01_leetcode/03_hash/348. Design Tic-Tac-Toe.md:
--------------------------------------------------------------------------------
1 | # 348 Design Tic-Tac-Toe
2 |
3 | [https://leetcode.com/problems/design-tic-tac-toe/](https://leetcode.com/problems/design-tic-tac-toe/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class TicTacToe(object):
9 | def __init__(self, n):
10 | self.n = n
11 | self.row = [0] * n # 记录下,每一行的和,每一列的和,两个对角线的和
12 | self.col = [0] * n
13 | self.left = 0
14 | self.right = 0
15 |
16 | def move(self, row, col, player):
17 | if player == 1:
18 | delta = 1
19 | else:
20 | delta = -1
21 |
22 | self.row[row] += delta
23 | self.col[col] += delta
24 | if row == col:
25 | self.left += delta
26 | if row == self.n - 1 - col:
27 | self.right += delta
28 |
29 | # 每一个条件判断也可以在各自加delta之后立马判断
30 | if abs(self.row[row]) == self.n or abs(self.col[col]) == self.n or abs(self.left) == self.n or abs(self.right) == self.n:
31 | return player
32 |
33 | return 0
34 | ```
35 |
36 | 时间复杂度:O()
37 | 空间复杂度:O()
38 |
39 | ## follow up
40 |
41 | [794. Valid Tic-Tac-Toe State](https://leetcode.com/problems/valid-tic-tac-toe-state/description/)
42 |
43 | ```python
44 |
45 | ```
46 |
--------------------------------------------------------------------------------
/01_leetcode/03_hash/350. Intersection of Two Arrays II.md:
--------------------------------------------------------------------------------
1 | # 350. Intersection of Two Arrays II
2 |
3 | [https://leetcode.com/problems/intersection-of-two-arrays-ii/](https://leetcode.com/problems/intersection-of-two-arrays-ii/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
10 | if len(nums1) > len(nums2):
11 | return self.intersect(nums2, nums1)
12 |
13 | cnt = collections.Counter(nums1)
14 | ans = []
15 | for x in nums2:
16 | if cnt[x] > 0:
17 | ans.append(x)
18 | cnt[x] -= 1
19 | return ans
20 | ```
21 |
22 | 时间复杂度:O(m+n)
23 | 空间复杂度:O(n)
24 |
--------------------------------------------------------------------------------
/01_leetcode/03_hash/706. Design HashMap.md:
--------------------------------------------------------------------------------
1 | # 706. Design HashMap
2 |
3 | [https://leetcode.com/problems/design-hashmap/description/](https://leetcode.com/problems/design-hashmap/description/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class MyHashMap:
9 | def __init__(self):
10 | self.size = 1000001
11 | self.data = [-1] * self.size
12 |
13 | def put(self, key: int, value: int) -> None:
14 | if 0 <= key < self.size:
15 | self.data[key] = value
16 |
17 | def get(self, key: int) -> int:
18 | if 0 <= key < self.size:
19 | return self.data[key]
20 | else:
21 | return -1
22 |
23 | def remove(self, key: int) -> None:
24 | if 0 <= key < self.size:
25 | self.data[key] = -1
26 | ```
27 |
28 | 时间复杂度:O()
29 | 空间复杂度:O()
30 |
31 | ## follow up
32 |
33 | reshard的方法
34 |
--------------------------------------------------------------------------------
/01_leetcode/03_hash/73. Set Matrix Zeroes.md:
--------------------------------------------------------------------------------
1 | # 73. Set Matrix Zeroes
2 |
3 | [https://leetcode.com/problems/set-matrix-zeroes/](https://leetcode.com/problems/set-matrix-zeroes/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def setZeroes(self, matrix: List[List[int]]) -> None:
10 | """
11 | Do not return anything, modify matrix in-place instead.
12 | """
13 | n_row = len(matrix)
14 | n_col = len(matrix[0])
15 |
16 | zero_coor = []
17 | for i in range(n_row):
18 | for j in range(n_col):
19 | if matrix[i][j] == 0:
20 | zero_coor.append([i, j])
21 |
22 | for (i, j) in zero_coor:
23 | matrix[i] = [0 for _ in range(n_col)]
24 | for x in range(n_row):
25 | matrix[x][j] = 0
26 | ```
27 |
28 | 时间复杂度:O()
29 | 空间复杂度:O()
30 |
--------------------------------------------------------------------------------
/01_leetcode/04_string/186. Reverse Words in a String II.md:
--------------------------------------------------------------------------------
1 | # 186 Reverse Words in a String II
2 |
3 | [https://leetcode.com/problems/reverse-words-in-a-string-ii/](https://leetcode.com/problems/reverse-words-in-a-string-ii/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution(object):
9 | def reverseWords(self, s):
10 | self.reverse_part(s, 0, len(s) - 1)
11 | p = 0
12 | for index in range(1, len(s)):
13 | if s[index] == ' ':
14 | self.reverse_part(s, p, index - 1)
15 | p = index + 1
16 |
17 | self.reverse_part(s, p, len(s) - 1)
18 |
19 | def reverse_part(self, s, left, right):
20 | while left < right:
21 | s[left], s[right] = s[right], s[left]
22 | left += 1
23 | right -= 1
24 | ```
25 |
26 | 时间复杂度:O(n)
27 | 空间复杂度:O(1)
28 |
--------------------------------------------------------------------------------
/01_leetcode/04_string/205. Isomorphic Strings.md:
--------------------------------------------------------------------------------
1 | # 205. Isomorphic Strings
2 |
3 | [https://leetcode.com/problems/isomorphic-strings/](https://leetcode.com/problems/isomorphic-strings/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def isIsomorphic(self, s: str, t: str) -> bool:
10 | dict = {}
11 |
12 | if len(s) != len(t):
13 | return False
14 |
15 | for i, j in zip(s, t):
16 | if i != j:
17 | if i not in dict:
18 | dict[i] = j
19 | else:
20 | if dict[i] != j:
21 | return False
22 | else:
23 | dict[i] = j
24 | return True
25 | ```
26 |
27 | 时间复杂度:O()
28 | 空间复杂度:O()
29 |
--------------------------------------------------------------------------------
/01_leetcode/04_string/242. Valid Anagram.md:
--------------------------------------------------------------------------------
1 | # 242. Valid Anagram
2 |
3 | [https://leetcode.com/problems/valid-anagram/](https://leetcode.com/problems/valid-anagram/)
4 |
5 | ## solution
6 |
7 | - hash
8 |
9 | ```python
10 | class Solution:
11 | def isAnagram(self, s: str, t: str) -> bool:
12 | if len(s) != len(t):
13 | return False
14 |
15 | counter = {}
16 | for i in s:
17 | if i in counter:
18 | counter[i] += 1
19 | else:
20 | counter[i] = 1
21 |
22 | for j in t:
23 | if j in counter:
24 | counter[j] -= 1
25 | else:
26 | return False
27 |
28 | for x, y in counter.items():
29 | if y > 0:
30 | return False
31 | return True
32 | ```
33 |
34 | 时间复杂度:O(n)
35 | 空间复杂度:O(26) -> O(1)
36 |
37 | - hash using array 26
38 |
39 | - sort
40 |
41 | ## follow up
42 |
43 | [125. Valid Palindrome](../01_two_pointers/125.%20Valid%20Palindrome.md)
44 |
45 | [438. Find All Anagrams in a String](../01_two_pointers/76.%20Minimum%20Window%20Substring.md)
46 |
--------------------------------------------------------------------------------
/01_leetcode/04_string/28. Find the Index of the First Occurrence in a String.md:
--------------------------------------------------------------------------------
1 | # 28. Find the Index of the First Occurrence in a String
2 |
3 | [https://leetcode.com/problems/find-the-index-of-the-first-occurrence-in-a-string/](https://leetcode.com/problems/find-the-index-of-the-first-occurrence-in-a-string/)
4 |
5 | ## solution
6 |
7 | - kmp匹配
8 |
9 | ```python
10 | class Solution:
11 | def strStr(self, haystack: str, needle: str) -> int:
12 | for i in range(len(haystack)):
13 | if haystack[i] == needle[0]:
14 | j = i
15 | k = 0
16 | while j < len(haystack) and k < len(needle) and haystack[j] == needle[k]:
17 | j += 1
18 | k += 1
19 | if k == len(needle):
20 | return i
21 | return -1
22 | ```
23 |
24 | 时间复杂度:O()
25 | 空间复杂度:O()
26 |
--------------------------------------------------------------------------------
/01_leetcode/04_string/647. Palindromic Substrings.md:
--------------------------------------------------------------------------------
1 | # 647. Palindromic Substrings
2 |
3 | [https://leetcode.com/problems/palindromic-substrings/](https://leetcode.com/problems/palindromic-substrings/)
4 |
5 | ## solution
6 |
7 | - 动态规划
8 |
9 | ```python
10 |
11 | ```
12 |
13 | 时间复杂度:O()
14 | 空间复杂度:O()
15 |
16 | - 双指针
17 |
18 | ```python
19 | class Solution:
20 | def countSubstrings(self, s: str) -> int:
21 | res = 0
22 | for i in range(len(s)):
23 | res += self.traversal(s, i, i)
24 | res += self.traversal(s, i, i+1)
25 | return res
26 |
27 | def traversal(self, s, l, r):
28 | this_res = 0
29 |
30 | while l >= 0 and r < len(s) and s[l] == s[r]:
31 | this_res += 1
32 | l -= 1
33 | r += 1
34 | return this_res
35 | ```
36 |
37 | 时间复杂度:O()
38 | 空间复杂度:O()
39 |
--------------------------------------------------------------------------------
/01_leetcode/04_string/696. Count Binary Substrings.md:
--------------------------------------------------------------------------------
1 | # 696. Count Binary Substrings
2 |
3 | [https://leetcode.com/problems/count-binary-substrings/](https://leetcode.com/problems/count-binary-substrings/)
4 |
5 | ## solution
6 |
7 | - 注意是连续,因此不能用hash存储个数来判断
8 | - 分别处理与前值相同、与前值不同的场景. 构思还是非常巧妙的
9 |
10 | ```python
11 | class Solution:
12 | def countBinarySubstrings(self, s: str) -> int:
13 | pre = 0 # 前一类的个数
14 | cur = 1 # 本类的个数
15 | count = 0
16 | for i in range(1, len(s)):
17 | if s[i] == s[i-1]:
18 | cur += 1
19 | else:
20 | pre = cur
21 | cur = 1
22 |
23 | if pre >= cur:
24 | count += 1
25 | return count
26 | ```
27 |
28 | 时间复杂度:O(n)
29 | 空间复杂度:O(1)
30 |
--------------------------------------------------------------------------------
/01_leetcode/04_string/README.md:
--------------------------------------------------------------------------------
1 | # 字符串
2 |
3 | - 很多字符串的解法是two pointer, 是DP(子串问题)或者DFS
4 | - LIS(最长递增子序列)
5 | - LCS(最长公共子序列、最长公共子串)
6 | - LCP(最长公共前缀)
7 | - LPS(最长回文子序列、最长回文子串)
8 | - ED(最小编辑距离,也叫 “Levenshtein 距离”)、
9 | - KMP(一种字符串匹配的高效算法)
10 | - palindrome
11 | - 可以考虑reverse string来比较
12 | - 找palindrome可以expand from center,或者DP
13 | - 用特殊符号的时候,不要用-, 以防是数字转换过来的,负数也带-
14 |
15 | - 判断非空
16 |
17 | ```python
18 | if substring:
19 | pass
20 | ```
21 |
22 | - 一个或多个空格的分割
23 |
24 | ```python
25 | string.split()
26 | ```
27 |
28 | - ASCII
29 |
30 | ```python
31 | ord('a')
32 | ```
33 |
34 | ## reference
35 |
36 | - [字符串匹配算法KMP小结](https://www.cnblogs.com/grandyang/p/6992403.html)
37 |
--------------------------------------------------------------------------------
/01_leetcode/05_stack_queue/1209. Remove All Adjacent Duplicates in String II.md:
--------------------------------------------------------------------------------
1 | # 1209. Remove All Adjacent Duplicates in String II
2 |
3 | [https://leetcode.com/problems/remove-all-adjacent-duplicates-in-string-ii/](https://leetcode.com/problems/remove-all-adjacent-duplicates-in-string-ii/)
4 |
5 | ## solution
6 |
7 | - 消消乐
8 |
9 | ```python
10 | class Solution:
11 | def removeDuplicates(self, s: str, k: int) -> str:
12 | stack = []
13 | for char in s:
14 | if stack and stack[-1][0] == char:
15 | stack[-1][1] += 1
16 | if stack [-1][1] == k:
17 | stack.pop()
18 | # 注意这里有else
19 | else:
20 | # 注意上面有修改 stack[-1][1]的值,因此只能选list,不能tuple
21 | stack.append([char, 1])
22 | return "".join(c*count for c, count in stack)
23 | ```
24 |
25 | 时间复杂度:O(n)
26 | 空间复杂度:O(n)
27 |
--------------------------------------------------------------------------------
/01_leetcode/05_stack_queue/1429. First Unique Number.md:
--------------------------------------------------------------------------------
1 | # 1429. First Unique Number
2 |
3 | [https://leetcode.com/problems/first-unique-number/](https://leetcode.com/problems/first-unique-number/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class FirstUnique:
9 | def __init__(self, nums: List[int]):
10 | self.counter = Counter(nums)
11 | self.queue = deque(nums)
12 |
13 | def showFirstUnique(self) -> int:
14 | while self.queue and self.counter[self.queue[0]] != 1:
15 | self.queue.popleft()
16 | return -1 if not self.queue else self.queue[0]
17 |
18 | def add(self, value: int) -> None:
19 | self.counter[value] += 1
20 | self.queue.append(value)
21 | ```
22 |
23 | 时间复杂度:O()
24 | 空间复杂度:O()
25 |
--------------------------------------------------------------------------------
/01_leetcode/05_stack_queue/1472. Design Browser History.md:
--------------------------------------------------------------------------------
1 | # 1472. Design Browser History
2 |
3 | [https://leetcode.com/problems/design-browser-history/](https://leetcode.com/problems/design-browser-history/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class BrowserHistory:
9 | def __init__(self, homepage: str):
10 | self.history = []
11 | self.visit(homepage)
12 |
13 | def visit(self, url: str) -> None:
14 | self.history.append(url)
15 | self.future = []
16 |
17 | def back(self, steps: int) -> str:
18 | while len(self.history) > 1 and steps > 0:
19 | self.future.append(self.history.pop())
20 | steps -= 1
21 | return self.history[-1]
22 |
23 | def forward(self, steps: int) -> str:
24 | while self.future and steps > 0:
25 | self.history.append(self.future.pop())
26 | steps -= 1
27 | return self.history[-1]
28 | ```
29 |
30 | 时间复杂度:O(steps)
31 | 空间复杂度:O(n)
32 |
--------------------------------------------------------------------------------
/01_leetcode/05_stack_queue/150. Evaluate Reverse Polish Notation.md:
--------------------------------------------------------------------------------
1 | # 150. Evaluate Reverse Polish Notation
2 |
3 | [https://leetcode.com/problems/evaluate-reverse-polish-notation/](https://leetcode.com/problems/evaluate-reverse-polish-notation/)
4 |
5 | ## solution
6 |
7 | - 注意运算顺序与栈的顺序
8 | - python中如何将字符串符号对应为运算符
9 |
10 | ```python
11 | class Solution:
12 | def evalRPN(self, tokens: List[str]) -> int:
13 | stack = []
14 | # op_map = {'+': add, '-': sub, '*': mul, '/': lambda x, y: int(x / y)}
15 |
16 | for token in tokens:
17 | if token in ['+', '-', '*', '/']:
18 | a = stack.pop(-1)
19 | b = stack.pop(-1)
20 | if token == '+':
21 | x = a + b
22 | elif token == '-':
23 | x = b - a
24 | elif token == '*':
25 | x = b * a
26 | elif token == '/':
27 | x = b / a
28 | else:
29 | raise ValueError
30 |
31 | stack.append(int(x))
32 | else:
33 | stack.append(int(token))
34 | return stack[-1]
35 | ```
36 |
37 | 时间复杂度:O(n)
38 | 空间复杂度:O(n)
39 |
--------------------------------------------------------------------------------
/01_leetcode/05_stack_queue/155. Min Stack.md:
--------------------------------------------------------------------------------
1 | # 155. Min Stack
2 |
3 | [https://leetcode.com/problems/min-stack/](https://leetcode.com/problems/min-stack/)
4 |
5 | ## solution
6 |
7 | - 维护每个数入栈时的最小值,即另一个栈min_stack. 利用其特点,当前加入时的最小值为自己或之前更早的元素,保证pop时小的不会pop出去而无法更新
8 |
9 | ```python
10 | class MinStack:
11 | def __init__(self):
12 | self.stack = []
13 | self.min_stack = []
14 |
15 | def push(self, val: int) -> None:
16 | self.stack.append(val)
17 | if not self.min_stack or val < self.min_stack[-1]:
18 | self.min_stack.append(val)
19 | else:
20 | self.min_stack.append(self.min_stack[-1])
21 |
22 | def pop(self) -> None:
23 | self.min_stack.pop()
24 | return self.stack.pop()
25 |
26 | def top(self) -> int:
27 | return self.stack[-1]
28 |
29 | def getMin(self) -> int:
30 | return self.min_stack[-1]
31 | ```
32 |
33 | 时间复杂度:O(1)
34 | 空间复杂度:O(n)
35 |
36 | ## follow up
37 |
38 | [\*716. Max Stack](https://leetcode.com/problems/max-stack/)
39 |
40 | ```python
41 |
42 | ```
43 |
44 | [622. Design Circular Queue](https://leetcode.com/problems/design-circular-queue/description/)
45 |
46 | ```python
47 | # 关键是记录head_index和count,从一段空间中确定时间的queue. 整个空间其他的还可以记录
48 |
49 | ```
50 |
--------------------------------------------------------------------------------
/01_leetcode/05_stack_queue/225. Implement Stack using Queues.md:
--------------------------------------------------------------------------------
1 | # 225. Implement Stack using Queues
2 |
3 | [https://leetcode.com/problems/implement-stack-using-queues/description/](https://leetcode.com/problems/implement-stack-using-queues/description/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class MyStack:
9 | def __init__(self):
10 | self.q1 = []
11 | self.q2 = []
12 |
13 | def push(self, x: int) -> None:
14 | self.q1.append(x)
15 |
16 | def pop(self) -> int:
17 | if self.empty():
18 | return None
19 |
20 | for i in range(len(self.q1) - 1):
21 | self.q2.append(self.q1.pop(0))
22 | self.q1, self.q2 = self.q2, self.q1
23 | return self.q2.pop(0)
24 |
25 | def top(self) -> int:
26 | if self.q1:
27 | return self.q1[-1]
28 |
29 | def empty(self) -> bool:
30 | if self.q1:
31 | return False
32 | else:
33 | return True
34 | ```
35 |
36 | 时间复杂度:O()
37 | 空间复杂度:O()
38 |
--------------------------------------------------------------------------------
/01_leetcode/05_stack_queue/232. Implement Queue using Stacks.md:
--------------------------------------------------------------------------------
1 | # 232. Implement Queue using Stacks
2 |
3 | [https://leetcode.com/problems/implement-queue-using-stacks/](https://leetcode.com/problems/implement-queue-using-stacks/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class MyQueue:
9 | def __init__(self):
10 | self.stack1 = []
11 | self.stack2 = []
12 |
13 | def push(self, x: int) -> None:
14 | self.stack1.append(x)
15 |
16 | def pop(self) -> int:
17 | if self.stack2:
18 | return self.stack2.pop()
19 | elif self.stack1:
20 | while self.stack1:
21 | self.stack2.append(self.stack1.pop(-1))
22 | return self.stack2.pop(-1)
23 | else:
24 | return
25 |
26 | def peek(self) -> int:
27 | if self.stack2:
28 | return self.stack2[-1]
29 | elif self.stack1:
30 | return self.stack1[0]
31 | else:
32 | return
33 |
34 | def empty(self) -> bool:
35 | if len(self.stack1) + len(self.stack2) > 0:
36 | return False
37 | else:
38 | return True
39 | ```
40 |
41 | 时间复杂度:O()
42 | 空间复杂度:O()
43 |
--------------------------------------------------------------------------------
/01_leetcode/05_stack_queue/281. Zigzag Iterator.md:
--------------------------------------------------------------------------------
1 | # 281. Zigzag Iterator
2 |
3 | [https://leetcode.com/problems/zigzag-iterator/](https://leetcode.com/problems/zigzag-iterator/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class ZigzagIterator:
9 | def __init__(self, v1: List[int], v2: List[int]):
10 | self.current = 0
11 | self.size = 2
12 | self.indices = [0] * self.size
13 | self.vectors = [v1, v2]
14 |
15 | def next(self) -> int:
16 | vector = self.vectors[self.current]
17 | index = self.indices[self.current]
18 | result = vector[index]
19 | self.indices[self.current] = index + 1
20 | self.current = (self.current + 1) % self.size
21 | return result
22 |
23 | def hasNext(self) -> bool:
24 | start = self.current
25 | while self.indices[self.current] == len(self.vectors[self.current]):
26 | self.current = (self.current + 1) % self.size
27 | if self.current == start:
28 | return False
29 | return True
30 | ```
31 |
32 | 时间复杂度:O()
33 | 空间复杂度:O()
34 |
--------------------------------------------------------------------------------
/01_leetcode/05_stack_queue/346. Moving Average from Data Stream.md:
--------------------------------------------------------------------------------
1 | # 346. Moving Average from Data Stream
2 |
3 | [https://leetcode.com/problems/moving-average-from-data-stream/](https://leetcode.com/problems/moving-average-from-data-stream/)
4 |
5 | ## solution
6 |
7 | - 双端队列
8 |
9 | ```python
10 | from collections import deque
11 |
12 | class MovingAverage:
13 | def __init__(self, size: int):
14 | self.size = size
15 | self.queue = deque()
16 | self.sum = 0
17 |
18 | def next(self, val: int) -> float:
19 | if len(self.queue) == self.size:
20 | left_val = self.queue.popleft()
21 | self.sum -= left_val
22 |
23 | self.queue.append(val)
24 | self.sum += val
25 | return self.sum / len(self.queue)
26 | ```
27 |
28 | 时间复杂度:O(1)
29 | 空间复杂度:O(n)
30 |
31 | - 列表
32 |
33 | ```python
34 | class MovingAverage:
35 | def __init__(self, size: int):
36 | self.size = size
37 | self.nums = []
38 | self.sum = 0
39 |
40 | def next(self, val: int) -> float:
41 | self.nums.append(val)
42 | self.sum += val
43 | if len(self.nums) > self.size:
44 | self.sum -= self.nums.pop(0)
45 | return self.sum / len(self.nums)
46 | ```
47 |
48 | 时间复杂度:O(n)
49 | 空间复杂度:O(n)
50 |
--------------------------------------------------------------------------------
/01_leetcode/05_stack_queue/503. Next Greater Element II.md:
--------------------------------------------------------------------------------
1 | # 503. Next Greater Element II
2 |
3 | [https://leetcode.com/problems/next-greater-element-ii/](https://leetcode.com/problems/next-greater-element-ii/)
4 |
5 | ## solution
6 |
7 | - 单调栈
8 | - 循环数组的应对方式
9 |
10 | ```python
11 | class Solution:
12 | def nextGreaterElements(self, nums: List[int]) -> List[int]:
13 | n = len(nums)
14 | res = [-1] * n
15 | stack = []
16 |
17 | for i in range(2 * n): # 走两轮
18 | num = nums[i % n]
19 | while stack and nums[stack[-1]] < num:
20 | index = stack.pop()
21 | res[index] = num
22 |
23 | stack.append(i % n) # option: i < n时才append
24 | return res
25 | ```
26 |
27 | 时间复杂度:O(n)
28 | 空间复杂度:O(n)
29 |
--------------------------------------------------------------------------------
/01_leetcode/05_stack_queue/735. Asteroid Collision.md:
--------------------------------------------------------------------------------
1 | # 735. Asteroid Collision
2 |
3 | [https://leetcode.com/problems/asteroid-collision/](https://leetcode.com/problems/asteroid-collision/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def asteroidCollision(self, asteroids: List[int]) -> List[int]:
10 | res = []
11 | for a in asteroids:
12 | while res and res[-1] > 0 and a < 0: # 注意一开始为负的话不会碰撞,因此遇到负的才会考虑去碰撞stack里正的
13 | if res[-1] + a < 0:
14 | res.pop()
15 | elif res[-1] + a > 0:
16 | break
17 | else:
18 | res.pop()
19 | break
20 | else:
21 | res.append(a)
22 | return res
23 | ```
24 |
25 | 时间复杂度:O(n)
26 | 空间复杂度:O(n)
27 |
--------------------------------------------------------------------------------
/01_leetcode/05_stack_queue/901. Online Stock Span.md:
--------------------------------------------------------------------------------
1 | # 901. Online Stock Span
2 |
3 | [https://leetcode.com/problems/online-stock-span/](https://leetcode.com/problems/online-stock-span/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class StockSpanner:
9 | def __init__(self):
10 | self.stack = [] # This stack will keep track of stock prices and their spans
11 |
12 | def next(self, price: int) -> int:
13 | span_count = 1
14 | while self.stack and self.stack[-1][0] <= price:
15 | span_count += self.stack.pop()[1]
16 | self.stack.append((price, span_count))
17 | return span_count
18 | ```
19 |
20 | 时间复杂度:O()
21 | 空间复杂度:O()
22 |
--------------------------------------------------------------------------------
/01_leetcode/06_heap/1086. High Five.md:
--------------------------------------------------------------------------------
1 | # 1086. High Five
2 |
3 | [https://leetcode.com/problems/high-five/](https://leetcode.com/problems/high-five/)
4 |
5 | ## solution
6 |
7 | ```python
8 |
9 | ```
10 |
11 | 时间复杂度:O()
12 | 空间复杂度:O()
13 |
--------------------------------------------------------------------------------
/01_leetcode/06_heap/1705. Maximum Number of Eaten Apples.md:
--------------------------------------------------------------------------------
1 | # 1705. Maximum Number of Eaten Apples
2 |
3 | ## solution
4 |
5 | ```python
6 |
7 | ```
8 |
9 | 时间复杂度:O()
10 | 空间复杂度:O()
11 |
--------------------------------------------------------------------------------
/01_leetcode/06_heap/1845. Seat Reservation Manager.md:
--------------------------------------------------------------------------------
1 | # 1845. Seat Reservation Manager
2 |
3 | [https://leetcode.com/problems/seat-reservation-manager/description/](https://leetcode.com/problems/seat-reservation-manager/description/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class SeatManager:
9 | def __init__(self, n: int):
10 | self.seats = [i+1 for i in range(n)]
11 |
12 | def reserve(self) -> int:
13 | return heapq.heappop(self.seats)
14 |
15 | def unreserve(self, seatNumber: int) -> None:
16 | heapq.heappush(self.seats, seatNumber)
17 | ```
18 |
19 | 时间复杂度:O(log(n))
20 | 空间复杂度:O(n)
21 |
22 | - 超时(进一步优化,如何想到用heap)
23 |
24 | ```python
25 | class SeatManager:
26 | def __init__(self, n: int):
27 | self.n = n
28 | self.seats = [0] * (n + 1)
29 |
30 | def reserve(self) -> int:
31 | for i in range(1, self.n+1):
32 | if self.seats[i] == 0:
33 | self.seats[i] = 1
34 | return i
35 |
36 | def unreserve(self, seatNumber: int) -> None:
37 | self.seats[seatNumber] = 0
38 | ```
39 |
--------------------------------------------------------------------------------
/01_leetcode/06_heap/2542. Maximum Subsequence Score.md:
--------------------------------------------------------------------------------
1 | # 2542. Maximum Subsequence Score
2 |
3 | [https://leetcode.com/problems/maximum-subsequence-score/description/](https://leetcode.com/problems/maximum-subsequence-score/description/)
4 |
5 | ## solution
6 |
7 | - 思路比较巧妙
8 |
9 | ```python
10 | class Solution:
11 | def maxScore(self, nums1: List[int], nums2: List[int], k: int) -> int:
12 | res = 0
13 | prefix = 0
14 | heap = []
15 |
16 | for x, y in sorted(list(zip(nums1, nums2)), key= lambda x: x[1], reverse=True):
17 | prefix += x
18 | heapq.heappush(heap, x)
19 | if len(heap) == k:
20 | # 已经按顺序排序了,每次到的y都是当时最小的
21 | res = max(res, prefix * y)
22 | v = heapq.heappop(heap)
23 | prefix -= v
24 | return res
25 | ```
26 |
27 | ## follow up
28 |
29 | [857. Minimum Cost to Hire K Workers](https://leetcode.com/problems/minimum-cost-to-hire-k-workers/description/)
30 |
31 | ```python
32 |
33 | ```
34 |
35 | [1383. Maximum Performance of a Team](https://leetcode.com/problems/maximum-performance-of-a-team/description/)
36 |
37 | ```python
38 |
39 | ```
40 |
--------------------------------------------------------------------------------
/01_leetcode/06_heap/692. Top K Frequent Words.md:
--------------------------------------------------------------------------------
1 | # 692. Top K Frequent Words
2 |
3 | [https://leetcode.com/problems/top-k-frequent-words/](https://leetcode.com/problems/top-k-frequent-words/)
4 |
5 | ## solution
6 |
7 | - hash
8 |
9 | ```python
10 | class Solution:
11 | def topKFrequent(self, words: List[str], k: int) -> List[str]:
12 | freq_dict = {}
13 | for word in words:
14 | if word not in freq_dict:
15 | freq_dict[word] = 0
16 | freq_dict[word] += 1
17 |
18 | freq_dict = sorted(freq_dict.items(), key=lambda x: (-x[1], x[0]), reverse=False)
19 | return [i[0] for i in freq_dict[:k]]
20 | ```
21 |
22 | 时间复杂度:O()
23 | 空间复杂度:O()
24 |
25 | - heap
26 |
27 | ```python
28 | # 注意为了更好的控制频率相同的按字典排序, 需要增加一个类: https://walkccc.me/LeetCode/problems/0692/#__tabbed_2_3
29 |
30 | class Solution:
31 | def topKFrequent(self, words: List[str], k: int) -> List[str]:
32 | mydict = {}
33 | for word in words:
34 | mydict[word] = mydict.get(word, 0) + 1
35 |
36 | heap = []
37 | for key, freq in mydict.items():
38 | heapq.heappush(heap, (-freq, key))
39 |
40 | res = []
41 | for _ in range(k):
42 | res.append(heapq.heappop(heap)[1])
43 | return res
44 | ```
45 |
46 | 时间复杂度:O()
47 | 空间复杂度:O()
48 |
49 | - Bucket Sort
50 |
51 | ```python
52 |
53 | ```
54 |
--------------------------------------------------------------------------------
/01_leetcode/06_heap/895. Maximum Frequency Stack.md:
--------------------------------------------------------------------------------
1 | # 895. Maximum Frequency Stack
2 |
3 | [https://leetcode.com/problems/maximum-frequency-stack/](https://leetcode.com/problems/maximum-frequency-stack/)
4 |
5 | ## solution
6 |
7 | ```python
8 | import collections
9 |
10 | class FreqStack:
11 | def __init__(self):
12 | self.freq_counter = collections.defaultdict(int)
13 | self.freq_key = collections.defaultdict(list)
14 | self.max_freq = 0
15 |
16 | def push(self, val: int) -> None:
17 | self.freq_counter[val] += 1
18 | self.max_freq = max(self.max_freq, self.freq_counter[val])
19 | self.freq_key[self.freq_counter[val]].append(val)
20 |
21 | def pop(self) -> int:
22 | val = self.freq_key[self.max_freq].pop()
23 | self.freq_counter[val] -= 1
24 | if not self.freq_key[self.max_freq]:
25 | self.max_freq -= 1
26 | return val
27 | ```
28 |
29 | 时间复杂度:O(1)
30 | 空间复杂度:O()
31 |
--------------------------------------------------------------------------------
/01_leetcode/06_heap/973. K Closest Points.md:
--------------------------------------------------------------------------------
1 | # 973. K Closest Points
2 |
3 | [https://leetcode.com/problems/k-closest-points-to-origin/](https://leetcode.com/problems/k-closest-points-to-origin/)
4 |
5 | ## solution
6 |
7 | - heap
8 | - 最小的k个
9 | - 大顶堆: 堆长度超过k之后, pop出去一个大的, 但python只有小顶堆只能pop出去小的,因此取负数。这样python小顶堆里留下了k个最大的,但其实是最小
10 | - 小顶堆: 所有元素入堆之后, pop出k个小的
11 |
12 | ```python
13 | class Solution:
14 | def kClosest(self, points: List[List[int]], k: int) -> List[List[int]]:
15 | heap = []
16 | for i, point in enumerate(points):
17 | dis = self._distance(point, (0, 0))
18 | # heappush: inserting an item to a heap of size k take O(logK) time
19 | heapq.heappush(heap, (-dis, i)) # 这里也可以换成(-dis, x, y)入堆
20 |
21 | if len(heap) > k:
22 | heapq.heappop(heap)
23 |
24 | res = []
25 | for dis, i in heap:
26 | res.append(points[i])
27 | return res
28 |
29 | def _distance(self, point1, point2):
30 | x1, y1 = point1
31 | x2, y2 = point2
32 | return ((x1 - x2) ** 2 + (y1 - y2) ** 2) ** 0.5
33 | ```
34 |
35 | 时间复杂度:O(nlogk)
36 | 空间复杂度:O(k)
37 |
38 | - quick select
39 |
40 | ```python
41 |
42 | ```
43 |
44 | 时间复杂度:O()
45 | 空间复杂度:O()
46 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/101. Symmetric Tree.md:
--------------------------------------------------------------------------------
1 | # 101. Symmetric Tree
2 |
3 | [https://leetcode.com/problems/symmetric-tree/](https://leetcode.com/problems/symmetric-tree/)
4 |
5 | ## solution
6 |
7 | - 关于递归的返回。注释掉的部分,会导致结果错误,甚至没有继续向下判断
8 |
9 | ```python
10 | class Solution:
11 | def isSymmetric(self, root: Optional[TreeNode]) -> bool:
12 | if root is None:
13 | return True
14 | return self.isSym(root.left, root.right)
15 |
16 | def isSym(self, l, r):
17 | if l is None and r is not None:
18 | return False
19 | elif l is not None and r is None:
20 | return False
21 | elif l is None and r is None:
22 | return True
23 |
24 | if l.val != r.val:
25 | return False
26 | # else:
27 | # return True
28 |
29 | return self.isSym(l.left, r.right) and self.isSym(l.right, r.left)
30 | ```
31 |
32 | 时间复杂度:O(n)
33 | 空间复杂度:O(h)
34 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/1087. Brace Expansion.md:
--------------------------------------------------------------------------------
1 | # 1087. Brace Expansion
2 |
3 | [https://leetcode.com/problems/brace-expansion/](https://leetcode.com/problems/brace-expansion/)
4 |
5 | ## solution
6 |
7 | ```python
8 |
9 | ```
10 |
11 | 时间复杂度:O()
12 | 空间复杂度:O()
13 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/1110. Delete Nodes And Return Forest.md:
--------------------------------------------------------------------------------
1 | # 1110. Delete Nodes And Return Forest
2 |
3 | [https://leetcode.com/problems/delete-nodes-and-return-forest/](https://leetcode.com/problems/delete-nodes-and-return-forest/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def __init__(self):
10 | self.res = []
11 |
12 | def delNodes(self, root: Optional[TreeNode], to_delete: List[int]) -> List[TreeNode]:
13 | if self.dfs(root, to_delete):
14 | self.res.append(root)
15 | return self.res
16 |
17 | def dfs(self, root, to_delete):
18 | if not root:
19 | return
20 |
21 | root.left = self.dfs(root.left, to_delete)
22 | root.right = self.dfs(root.right, to_delete)
23 |
24 | if root.val in to_delete:
25 | # 通过delete节点返回None来控制初始根节点是否需要添加。因为这里有个返回,导致左右dfs需要在其上面 -> 后序遍历
26 | if root.left:
27 | self.res.append(root.left)
28 | if root.right:
29 | self.res.append(root.right)
30 | return
31 |
32 | return root
33 | ```
34 |
35 | 时间复杂度:O(N)
36 | 空间复杂度:O(N)
37 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/1274. Number of Ships in a Rectangle.md:
--------------------------------------------------------------------------------
1 | # 1274. Number of Ships in a Rectangle
2 |
3 | [https://leetcode.com/problems/number-of-ships-in-a-rectangle/](https://leetcode.com/problems/number-of-ships-in-a-rectangle/)
4 |
5 | ## solution
6 |
7 | ```python
8 |
9 | ```
10 |
11 | 时间复杂度:O()
12 | 空间复杂度:O()
13 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/1376. Time Needed to Inform All Employees.md:
--------------------------------------------------------------------------------
1 | # 1376. Time Needed to Inform All Employees
2 |
3 | [https://leetcode.com/problems/time-needed-to-inform-all-employees/](https://leetcode.com/problems/time-needed-to-inform-all-employees/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def numOfMinutes(self, n: int, head_id: int, managers: List[int], inform_time: List[int]) -> int:
10 | def dfs(employee_id: int) -> int:
11 | max_time = 0
12 | for subordinate in graph[employee_id]:
13 | max_time = max(max_time, dfs(subordinate) + inform_time[employee_id])
14 | return max_time
15 |
16 | graph = collections.defaultdict(list)
17 | for i, mng_id in enumerate(managers):
18 | if mng_id != -1:
19 | graph[mng_id].append(i)
20 |
21 | return dfs(head_id)
22 | ```
23 |
24 | 时间复杂度:O(n)
25 | 空间复杂度:O(n)
26 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/1485. Clone Binary Tree With Random Pointer.md:
--------------------------------------------------------------------------------
1 | # 1485. Clone Binary Tree With Random Pointer
2 |
3 | [https://leetcode.com/problems/clone-binary-tree-with-random-pointer/](https://leetcode.com/problems/clone-binary-tree-with-random-pointer/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | # clone的题目也是在: 构建一棵树.
10 | # 更好的方式确实也需要保存一个map, 由于random的存在. https://algo.monster/liteproblems/1485
11 | def clone_random_tree(self, root: RandomTreeNode) -> RandomTreeNode:
12 | if not root:
13 | return None
14 |
15 | copy = RandomTreeNode(root.val, None)
16 | copy.left = self.clone_random_tree(root.left)
17 | copy.right = self.clone_random_tree(root.right)
18 | if root.random:
19 | copy.random = self.clone_random_tree(root.random)
20 | return copy
21 | ```
22 |
23 | 时间复杂度:O(n)
24 | 空间复杂度:O()
25 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/17. Letter Combinations of a Phone Number.md:
--------------------------------------------------------------------------------
1 | # 17. Letter Combinations of a Phone Number
2 |
3 | [https://leetcode.com/problems/letter-combinations-of-a-phone-number/](https://leetcode.com/problems/letter-combinations-of-a-phone-number/)
4 |
5 | ## solution
6 |
7 | - 回溯
8 |
9 | ```python
10 | class Solution:
11 | def letterCombinations(self, digits: str) -> List[str]:
12 | if not digits:
13 | return []
14 |
15 | self.maps = {
16 | "2": "abc",
17 | "3": "def",
18 | "4": "ghi",
19 | "5": "jkl",
20 | "6": "mno",
21 | "7": "pqrs",
22 | "8": "tuv",
23 | "9": "wxyz"
24 | }
25 |
26 | path = []
27 | res = []
28 | index = 0
29 | self.dfs(path, res, digits, index)
30 | return res
31 |
32 | def dfs(self, path, res, digits, index):
33 | if len(path) == len(digits): # 或者 index == len(digits)
34 | res.append("".join(path))
35 | return
36 |
37 | i = digits[index]
38 | letters = self.maps[i]
39 |
40 | for letter in letters:
41 | path.append(letter)
42 | self.dfs(path, res, digits, index+1)
43 | path.pop()
44 | ```
45 |
46 | 时间复杂度:O(4^n)
47 | 空间复杂度:O(4^n)
48 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/226. Invert Binary Tree.md:
--------------------------------------------------------------------------------
1 | # 226. Invert Binary Tree
2 |
3 | [https://leetcode.com/problems/invert-binary-tree/](https://leetcode.com/problems/invert-binary-tree/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
10 | if root is None:
11 | return None
12 |
13 | root.left, root.right = root.right, root.left
14 | self.invertTree(root.left)
15 | self.invertTree(root.right)
16 | return root
17 | ```
18 |
19 | 时间复杂度:O(n)
20 | 空间复杂度:O(h)
21 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/230. Kth Smallest element in a BST.md:
--------------------------------------------------------------------------------
1 | # 230. Kth Smallest element in a BST
2 |
3 | [https://leetcode.com/problems/kth-smallest-element-in-a-bst/description/](https://leetcode.com/problems/kth-smallest-element-in-a-bst/description/)
4 |
5 | ## solution
6 |
7 | ```python
8 | # 如果k作为参数传值,k -=1 并判断k == 0有问题,还是因为k本身是immutable
9 | class Solution:
10 | def __init__(self):
11 | self.rank = 0
12 | self.res = 0
13 |
14 | def kthSmallest(self, root: Optional[TreeNode], k: int) -> int:
15 | self.dfs(root, k)
16 | return self.res
17 |
18 | def dfs(self, root, k):
19 | if not root:
20 | return
21 |
22 | self.dfs(root.left, k)
23 |
24 | self.rank += 1
25 | if self.rank == k:
26 | self.res = root.val
27 | return
28 |
29 | self.dfs(root.right, k)
30 | ```
31 |
32 | - 注意递归过程中的返回值
33 |
34 | ```python
35 | class Solution:
36 | def __init__(self):
37 | self.res = []
38 |
39 | def kthSmallest(self, root: Optional[TreeNode], k: int) -> int:
40 | self.dfs(root, k)
41 | return self.res[-1]
42 |
43 | def dfs(self, root, k):
44 | if not root:
45 | return
46 |
47 | self.dfs(root.left, k)
48 |
49 | if len(self.res) == k:
50 | return
51 | self.res.append(root.val)
52 |
53 | self.dfs(root.right, k)
54 | ```
55 |
56 | 时间复杂度:O(n)
57 | 空间复杂度:O()
58 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/235. Lowest Common Ancestor of a Binary Search Tree.md:
--------------------------------------------------------------------------------
1 | # 235. Lowest Common Ancestor of a Binary Search Tree
2 |
3 | [https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/](https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/)
4 |
5 | ## solution
6 |
7 | - 思路是找到第一个位于p、q之间的节点。所以虽然是BST,但前序遍历
8 |
9 | ```python
10 | class Solution:
11 | def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
12 | if root.val < p.val and root.val < q.val:
13 | return self.lowestCommonAncestor(root.right, p, q) # 这种遍历一半的树写法,判断然后返回。另一种完整遍历树,左结果l和右结果r再判断
14 | elif root.val > p.val and root.val > q.val:
15 | return self.lowestCommonAncestor(root.left, p, q)
16 | else: # 这里的else就包含两种情况,一种是p<=root<=q, 一种是q<=root<=p
17 | return root
18 | ```
19 |
20 | 时间复杂度:O(h)
21 | 空间复杂度:O(h)
22 |
23 | - 迭代
24 |
25 | ```python
26 |
27 | ```
28 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/291. Word Pattern II.md:
--------------------------------------------------------------------------------
1 | # 291. Word Pattern II
2 |
3 | [https://leetcode.com/problems/word-pattern-ii](https://leetcode.com/problems/word-pattern-ii)
4 |
5 | ## solution
6 |
7 | ```python
8 |
9 | ```
10 |
11 | 时间复杂度:O()
12 | 空间复杂度:O()
13 |
14 | ## follow up
15 |
16 | [290. Word Pattern](https://leetcode.com/problems/word-pattern/description/)
17 |
18 | ```python
19 |
20 | ```
21 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/333. Largest BST Subtree.md:
--------------------------------------------------------------------------------
1 | # 333. Largest BST Subtree
2 |
3 | [https://leetcode.com/problems/largest-bst-subtree/](https://leetcode.com/problems/largest-bst-subtree/)
4 |
5 | ## solution
6 |
7 | ```python
8 | import math
9 |
10 | class Solution:
11 | def largestBSTSubtree(self, root: Optional[TreeNode]) -> int:
12 | largest_bst_size = 0
13 |
14 | def dfs(root):
15 | if not root:
16 | return (math.inf, -math.inf, 0)
17 |
18 | left_min, left_max, left_size = dfs(root.left)
19 | right_min, right_max, right_size = dfs(root.right)
20 |
21 | nonlocal largest_bst_size
22 | if left_max < root.val < right_min:
23 | largest_bst_size = max(largest_bst_size, left_size + right_size + 1)
24 | return min(left_min, root.val), max(right_max, root.val), left_size + right_size + 1
25 | else:
26 | return (math.inf, -math.inf, 0)
27 |
28 | dfs(root)
29 | return largest_bst_size
30 | ```
31 |
32 | 时间复杂度:O(n)
33 | 空间复杂度:O(n)
34 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/341. Flatten Nested List Iterator.md:
--------------------------------------------------------------------------------
1 | # 341. Flatten Nested List Iterator
2 |
3 | [https://leetcode.com/problems/flatten-nested-list-iterator/](https://leetcode.com/problems/flatten-nested-list-iterator/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class NestedIterator:
9 | def __init__(self, nestedList: [NestedInteger]):
10 | self.queue = collections.deque()
11 | self.flat(nestedList)
12 |
13 | def next(self) -> int:
14 | return self.queue.popleft()
15 |
16 | def hasNext(self) -> bool:
17 | return self.queue
18 |
19 | def flat(self, nestedList):
20 | for n in nestedList:
21 | if not n.isInteger():
22 | self.flat(n.getList())
23 | else:
24 | self.queue.append(n.getInteger())
25 | ```
26 |
27 | 时间复杂度:O(n)
28 | 空间复杂度:O(n)
29 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/377. Combination Sum IV.md:
--------------------------------------------------------------------------------
1 | # 377. Combination Sum IV
2 |
3 | [https://leetcode.com/problems/combination-sum-iv/](https://leetcode.com/problems/combination-sum-iv/)
4 |
5 | ## solution
6 |
7 | - 完全背包
8 |
9 | ```python
10 | class Solution:
11 | def combinationSum4(self, nums: List[int], target: int) -> int:
12 | dp = [0] * (target + 1)
13 | dp[0] = 1
14 | for i in range(1, target+1):
15 | for num in nums:
16 | if i - num >= 0:
17 | dp[i] += dp[i - num]
18 | return dp[target]
19 | ```
20 |
21 | 时间复杂度:O()
22 | 空间复杂度:O()
23 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/394. Decode String.md:
--------------------------------------------------------------------------------
1 | # 394. Decode String
2 |
3 | [https://leetcode.com/problems/decode-string/description/](https://leetcode.com/problems/decode-string/description/)
4 |
5 | ## solution
6 |
7 | - 栈
8 |
9 | ```python
10 | class Solution:
11 | def decodeString(self, s: str) -> str:
12 | stack = []
13 | cur_num = 0
14 | cur_str = ''
15 |
16 | for char in s:
17 | if char == '[':
18 | stack.append(cur_str) # 栈也可以直接保存元素 (cur_str, cur_num), 思路关键是字母和次数都分别进栈, 方便重新开始统计
19 | stack.append(cur_num)
20 | cur_str = ''
21 | cur_num = 0
22 | elif char == ']':
23 | prev_num = stack.pop() # 注意这里两个pop出来的都要用新的名字
24 | prev_str = stack.pop()
25 | cur_str = prev_str + prev_num * cur_str # 更新
26 | elif char.isdigit():
27 | cur_num = cur_num * 10 + int(char)
28 | else:
29 | cur_str += char
30 | return cur_str
31 | ```
32 |
33 | 时间复杂度:O(n)
34 | 空间复杂度:O(n)
35 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/403. Frog Jump.md:
--------------------------------------------------------------------------------
1 | # 403. Frog Jump
2 |
3 | [https://leetcode.com/problems/frog-jump/](https://leetcode.com/problems/frog-jump/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution(object):
9 | def canCross(self, stones):
10 | n = len(stones)
11 | stoneSet = set(stones)
12 | visited = set()
13 | def goFurther(value,units):
14 | if (value+units not in stoneSet) or ((value,units) in visited):
15 | return False
16 | if value+units == stones[n-1]:
17 | return True
18 | visited.add((value,units))
19 | return goFurther(value+units,units) or goFurther(value+units,units-1) or goFurther(value+units,units+1)
20 | return goFurther(stones[0],1)
21 | ```
22 |
23 | 时间复杂度:O()
24 | 空间复杂度:O()
25 |
26 | - 动态规划
27 |
28 | ```python
29 | # dp[i][k] = dp[j][k - 1] || dp[j][k] || dp[j][k + 1]
30 |
31 | ```
32 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/472. Concatenated Words.md:
--------------------------------------------------------------------------------
1 | # 472. Concatenated Words
2 |
3 | [https://leetcode.com/problems/concatenated-words/](https://leetcode.com/problems/concatenated-words/)
4 |
5 | ## solution
6 |
7 | - dfs [超时]
8 |
9 | ```python
10 | # https://zhuanlan.zhihu.com/p/134658803
11 |
12 | class Solution:
13 | def findAllConcatenatedWordsInADict(self, words: List[str]) -> List[str]:
14 | words.sort(key=len)
15 | prev = set()
16 | res = []
17 | for word in words:
18 | if self.dfs(prev, word):
19 | res.append(word)
20 | prev.add(word)
21 | return res
22 |
23 | def dfs(self, prev, word):
24 | if not prev:
25 | return False
26 | if not word:
27 | return True
28 | for i in range(1, len(word)+1):
29 | if word[:i] in prev and self.dfs(prev, word[i:]):
30 | return True
31 | return False
32 | ```
33 |
34 | 时间复杂度:O()
35 | 空间复杂度:O()
36 |
37 | - 动态规划
38 |
39 | ```python
40 |
41 | ```
42 |
43 | - trie
44 |
45 | ## follow up
46 |
47 | - 返回所有结果
48 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/491. Non-decreasing Subsequences.md:
--------------------------------------------------------------------------------
1 | # 491. Non-decreasing Subsequences
2 |
3 | [https://leetcode.com/problems/non-decreasing-subsequences/](https://leetcode.com/problems/non-decreasing-subsequences/)
4 |
5 | ## solution
6 |
7 | - 注意:本题dfs里不能有return,要取树上的所有节点。如果return遇到一层符合的就返回了
8 | - [原去重思路:排序+判断相等](./78%20Subsets.md)无法使用,因为无法排序。另一种去重思路:保存后保存
9 |
10 | ```python
11 | class Solution:
12 | def findSubsequences(self, nums: List[int]) -> List[List[int]]:
13 | path = []
14 | res = []
15 | self.dfs(nums, path, res, start=0)
16 | return res
17 |
18 | def dfs(self, nums, path, res, start):
19 | if len(path) > 1:
20 | res.append(path[:])
21 |
22 | used = set() # 记录本层元素是否重复使用,新一层used都会被清空。因此进来之后才刚刚定义,所以不需要最后回溯时处理
23 | for i in range(start, len(nums)):
24 | if nums[i] in used:
25 | continue
26 | if path and nums[i] < path[-1]:
27 | continue
28 |
29 | used.add(nums[i])
30 | path.append(nums[i])
31 | self.dfs(nums, path, res, i+1)
32 | path.pop()
33 | ```
34 |
35 | 时间复杂度:O(n⋅2^n)
36 | 空间复杂度:O(2^n)
37 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/526. Beautiful Arrangement.md:
--------------------------------------------------------------------------------
1 | # 526. Beautiful Arrangement
2 |
3 | [https://leetcode.com/problems/beautiful-arrangement/](https://leetcode.com/problems/beautiful-arrangement/)
4 |
5 | ## solution
6 |
7 | ```python
8 |
9 | ```
10 |
11 | 时间复杂度:O()
12 | 空间复杂度:O()
13 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/572. Subtree of Another Tree.md:
--------------------------------------------------------------------------------
1 | # 572. Subtree of Another Tree
2 |
3 | [https://leetcode.com/problems/subtree-of-another-tree/](https://leetcode.com/problems/subtree-of-another-tree/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def isSubtree(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool:
10 | if subRoot is None:
11 | return True
12 |
13 | if root is None:
14 | return False
15 |
16 | if self.same(root , subRoot):
17 | return True
18 | return self.isSubtree(root.left , subRoot) or self.isSubtree(root.right , subRoot)
19 |
20 | def same(self , r , s):
21 | if r is None and s is None :
22 | return True
23 |
24 | if r and s and r.val == s.val:
25 | return self.same(r.right , s.right) and self.same(r.left , s.left)
26 |
27 | return False
28 | ```
29 |
30 | 时间复杂度:O(mn)
31 | 空间复杂度:O(h)
32 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/669. Trim a Binary Search Tree.md:
--------------------------------------------------------------------------------
1 | # 669. Trim a Binary Search Tree
2 |
3 | [https://leetcode.com/problems/trim-a-binary-search-tree/](https://leetcode.com/problems/trim-a-binary-search-tree/)
4 |
5 | ## solution
6 |
7 | - 小于low,那么所有左子树都小于low可以舍弃,返回右子树
8 | - 大于high,那么所有右子树都大于high可以舍弃,返回左子树
9 | - 对于位于期间的节点,递归其子树,左子树的返回节点接在左子树上,可能是正常节点,也可能是舍弃后返回的节点
10 |
11 | ```python
12 | class Solution:
13 | def trimBST(self, root: Optional[TreeNode], low: int, high: int) -> Optional[TreeNode]:
14 | if not root:
15 | return None
16 | if root.val > high:
17 | return self.trimBST(root.left, low, high)
18 | if root.val < low:
19 | return self.trimBST(root.right, low, high)
20 |
21 | if root.val >= low and root.val <= high:
22 | root.left = self.trimBST(root.left, low, high)
23 | root.right = self.trimBST(root.right, low, high)
24 | return root
25 | ```
26 |
27 | 时间复杂度:O()
28 | 空间复杂度:O()
29 |
30 | ## follow up
31 |
32 | [1110. Delete Nodes And Return Forest](./1110.%20Delete%20Nodes%20And%20Return%20Forest.md)
33 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/698. Partition to K Equal Sum Subsets.md:
--------------------------------------------------------------------------------
1 | # 698. Partition to K Equal Sum Subsets
2 |
3 | [https://leetcode.com/problems/partition-to-k-equal-sum-subsets/](https://leetcode.com/problems/partition-to-k-equal-sum-subsets/)
4 |
5 | ## solution
6 |
7 | ```python
8 |
9 | ```
10 |
11 | 时间复杂度:O()
12 | 空间复杂度:O()
13 |
14 | ## follow up
15 |
16 | [473. Matchsticks to Square](https://leetcode.com/problems/matchsticks-to-square/description/)
17 |
18 | - 回溯
19 |
20 | ```python
21 |
22 | ```
23 |
24 | [416. 分割等和子集](https://leetcode.com/problems/partition-equal-subset-sum/)
25 |
26 | - 动态规划/01背包
27 |
28 | ```python
29 | class Solution:
30 | def canPartition(self, nums: List[int]) -> bool:
31 | if sum(nums) % 2 == 1:
32 | return False
33 |
34 | length = sum(nums) // 2 # 背包重量为 一半
35 | dp = [0] * (length + 1)
36 |
37 | for i in nums: # 先物品
38 | for j in range(length, i-1, -1): # 再背包,01背包倒序避免重复放入
39 | dp[j] = max(dp[j], dp[j-i]+i)
40 | return dp[-1] == length # 如果恰好装满一半
41 | ```
42 |
43 | 时间复杂度:O(nk)
44 | 空间复杂度:O(k)
45 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/700. Search in a Binary Search Tree.md:
--------------------------------------------------------------------------------
1 | # 700. Search in a Binary Search Tree
2 |
3 | [https://leetcode.com/problems/search-in-a-binary-search-tree/](https://leetcode.com/problems/search-in-a-binary-search-tree/)
4 |
5 | ## solution
6 |
7 | - 注意递归部分需要return,这样才是找到节点就返回。不返回的话,整体输出反而是最后一个递归的返回None
8 |
9 | ```python
10 | class Solution:
11 | def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
12 | if root is None:
13 | return
14 | if root.val == val:
15 | return root
16 |
17 | if root.val > val:
18 | return self.searchBST(root.left, val)
19 | if root.val < val:
20 | return self.searchBST(root.right, val)
21 | ```
22 |
23 | 时间复杂度:O(n)
24 | 空间复杂度:O(h)
25 |
26 | ## follow up
27 |
28 | [701. Insert into a Binary Search Tree](https://leetcode.com/problems/insert-into-a-binary-search-tree/)
29 |
30 | ```python
31 | class Solution:
32 | def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
33 | if not root:
34 | node = TreeNode(val)
35 | return node
36 |
37 | if root.val > val:
38 | root.left = self.insertIntoBST(root.left, val)
39 |
40 | else:
41 | root.right = self.insertIntoBST(root.right, val)
42 |
43 | return root
44 | ```
45 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/77. Combinations.md:
--------------------------------------------------------------------------------
1 | # 77. Combinations
2 |
3 | [https://leetcode.com/problems/combinations/](https://leetcode.com/problems/combinations/)
4 |
5 | ## solution
6 |
7 | 回溯
8 |
9 | - 整体输出结果、单次尝试的path、本次选择的选项
10 | - 本题回溯时,注意不需要重复项,通过控制**开始index**不从前面选
11 | - index: 下一层for循环搜索的起始位置
12 |
13 | ```python
14 | class Solution:
15 | def combine(self, n: int, k: int) -> List[List[int]]:
16 | res = []
17 | path = []
18 | self.dfs(res, path, n, k, start=1)
19 | return res
20 |
21 | def dfs(self, res, path, n, k, start):
22 | if len(path) == k:
23 | res.append(path[:]) # [:]和下面的copy保留一个即可, python中一定要有
24 | return
25 |
26 | for i in range(start, n+1): # 本层集合中的元素,递归N叉树,树节点孩子数量就是集合的大小
27 | path.append(i)
28 | self.dfs(res, path.copy(), n, k, i+1)
29 | path.pop()
30 | ```
31 |
32 | 时间复杂度:O(C(n, k)) = O(n! / (k! _ (n - k)!))
33 | 空间复杂度:O(C(n, k) _ n)
34 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/79. Word Search.md:
--------------------------------------------------------------------------------
1 | # 79. Word Search
2 |
3 | [https://leetcode.com/problems/word-search/](https://leetcode.com/problems/word-search/)
4 |
5 | ## solution
6 |
7 | - 通过修改访问标记的方式回溯
8 |
9 | ```python
10 | class Solution:
11 | def exist(self, board: List[List[str]], word: str) -> bool:
12 | m = len(board)
13 | n = len(board[0])
14 |
15 | for i in range(m):
16 | for j in range(n):
17 | if self.dfs(i, j, 0, board, word):
18 | return True
19 | return False
20 |
21 | def dfs(self, x, y, k, board, word):
22 | if k == len(word):
23 | return True
24 |
25 | if x < 0 or x >= len(board) or y < 0 or y >= len(board[0]) or board[x][y] != word[k]:
26 | return False
27 |
28 | mem = board[x][y]
29 | board[x][y] = '*'
30 | res = self.dfs(x+1, y, k+1, board, word) or self.dfs(x, y+1, k+1, board, word) or self.dfs(x-1, y, k+1, board, word) or self.dfs(x, y-1, k+1, board, word)
31 | board[x][y] = mem
32 | return res
33 | ```
34 |
35 | 时间复杂度:O(mn4^word)
36 | 空间复杂度:O(4^word)
37 |
38 | ## follow up
39 |
40 | [212 Word Search II](./212.%20Word%20Search%20II.md)
41 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/856. Score of Parentheses.md:
--------------------------------------------------------------------------------
1 | # 856. Score of Parentheses
2 |
3 | [https://leetcode.com/problems/score-of-parentheses/](https://leetcode.com/problems/score-of-parentheses/)
4 |
5 | ## solution
6 |
7 | ```python
8 | # 左括号更新深度,右括号更新结果
9 |
10 | class Solution:
11 | def scoreOfParentheses(self, s: str) -> int:
12 | score = 0
13 | depth = 0
14 |
15 | for i, char in enumerate(s):
16 | if char == '(':
17 | depth += 1
18 | else:
19 | depth -= 1
20 | if s[i-1] == '(':
21 | score += 2 ** depth
22 | return score
23 | ```
24 |
25 | 时间复杂度:O()
26 | 空间复杂度:O()
27 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/93. Restore IP Addresses.md:
--------------------------------------------------------------------------------
1 | # 93. Restore IP Addresses
2 |
3 | [https://leetcode.com/problems/restore-ip-addresses/description/](https://leetcode.com/problems/restore-ip-addresses/description/)
4 |
5 | ## solution
6 |
7 | ```python
8 | # 分割类回溯
9 |
10 | class Solution:
11 | def restoreIpAddresses(self, s: str) -> List[str]:
12 | path = []
13 | res = []
14 | self.dfs(s, path, res, start=0)
15 | return res
16 |
17 | def dfs(self, s, path, res, start):
18 | if start >= len(s) and len(path) == 4:
19 | res.append('.'.join(path[:]))
20 |
21 | for i in range(start, len(s)):
22 | temp = s[start: i+1]
23 | if len(temp) > 1 and temp[0] == '0':
24 | continue
25 | elif int(temp) > 255:
26 | continue
27 | elif len(path) > 3:
28 | break
29 | else:
30 | path.append(temp)
31 | self.dfs(s, path, res, i+1)
32 | path.pop()
33 | ```
34 |
35 | 时间复杂度:O(3^4)
36 | 空间复杂度:O(1)
37 |
--------------------------------------------------------------------------------
/01_leetcode/07_dfs/951. Flip Equivalent Binary Trees.md:
--------------------------------------------------------------------------------
1 | # 951. Flip Equivalent Binary Trees
2 |
3 | [https://leetcode.com/problems/flip-equivalent-binary-trees/](https://leetcode.com/problems/flip-equivalent-binary-trees/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def flipEquiv(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> bool:
10 | if root1 is None and root2 is None:
11 | return True
12 |
13 | if root1 is None or root2 is None:
14 | return False
15 |
16 | if root1.val != root2.val:
17 | return False
18 |
19 | return ((self.flipEquiv(root1.left, root2.left) and self.flipEquiv(root1.right, root2.right))
20 | or (self.flipEquiv(root1.right, root2.left) and self.flipEquiv(root1.left, root2.right)))
21 | ```
22 |
23 | 时间复杂度:O(n)
24 | 空间复杂度:O(h)
25 |
--------------------------------------------------------------------------------
/01_leetcode/08_bfs/103. Binary Tree Zigzag Level Order Traversal.md:
--------------------------------------------------------------------------------
1 | # 103. Binary Tree Zigzag Level Order Traversal
2 |
3 | [https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/](https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def zigzagLevelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
10 | if root is None:
11 | return []
12 |
13 | queue = collections.deque([root])
14 | res = []
15 | flag = 0
16 |
17 | while queue:
18 | level = []
19 | for _ in range(len(queue)):
20 | node = queue.popleft()
21 | level.append(node.val)
22 |
23 | if node.left:
24 | queue.append(node.left)
25 | if node.right:
26 | queue.append(node.right)
27 |
28 | if flag % 2 == 1:
29 | level = level[::-1]
30 | res.append(level)
31 | flag += 1
32 | return res
33 | ```
34 |
35 | 时间复杂度:O(n)
36 | 空间复杂度:O(n)
37 |
--------------------------------------------------------------------------------
/01_leetcode/08_bfs/1514. Path with Maximum Probability.md:
--------------------------------------------------------------------------------
1 | # 1514. Path with Maximum Probability
2 |
3 | [https://leetcode.com/problems/path-with-maximum-probability/description/](https://leetcode.com/problems/path-with-maximum-probability/description/)
4 |
5 | ## solution
6 |
7 | ```python
8 | import collections
9 |
10 | class Solution:
11 | def maxProbability(self, n: int, edges: List[List[int]], succProb: List[float], start_node: int, end_node: int) -> float:
12 | graph = collections.defaultdict(list)
13 | queue = collections.deque([start_node])
14 |
15 | for i, (a, b) in enumerate(edges):
16 | graph[a].append([b, i])
17 | graph[b].append([a, i])
18 |
19 | p = [0] * n
20 | p[start_node] = 1.0
21 |
22 | while queue:
23 | cur = queue.popleft()
24 | for nei, i in graph[cur]:
25 | if p[cur] * succProb[i] > p[nei]:
26 | p[nei] = p[cur] * succProb[i]
27 | queue.append(nei)
28 | return p[end_node]
29 | ```
30 |
31 | 时间复杂度:O()
32 | 空间复杂度:O()
33 |
--------------------------------------------------------------------------------
/01_leetcode/08_bfs/210. Course Schedule II.md:
--------------------------------------------------------------------------------
1 | # 210. Course Schedule II
2 |
3 | [https://leetcode.com/problems/course-schedule-ii/](https://leetcode.com/problems/course-schedule-ii/)
4 |
5 | ## solution
6 |
7 | ```python
8 | import collections
9 |
10 | class Solution:
11 | def findOrder(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]:
12 | courses = collections.defaultdict(set)
13 | pres = collections.defaultdict(set)
14 |
15 | for (x, y) in prerequisites:
16 | courses[y].add(x) # 上完这个课之后可以上的
17 | pres[x].add(y) # 这个课程的所有先修课程
18 |
19 | no_pre = [i for i in range(numCourses) if not pres[i]]
20 |
21 | res = []
22 | count = 0
23 | while no_pre:
24 | take_course = no_pre.pop()
25 | count += 1
26 | res.append(take_course)
27 | for i in courses[take_course]:
28 | pres[i].remove(take_course)
29 | if not pres[i]:
30 | no_pre.append(i)
31 |
32 | return res if count == numCourses else []
33 | ```
34 |
35 | 时间复杂度:O(V + E)
36 | 空间复杂度:O(V + E)
37 |
--------------------------------------------------------------------------------
/01_leetcode/08_bfs/314. Binary Tree Vertical Order Traversal.md:
--------------------------------------------------------------------------------
1 | # 314. Binary Tree Vertical Order Traversal
2 |
3 | [https://leetcode.com/problems/binary-tree-vertical-order-traversal/](https://leetcode.com/problems/binary-tree-vertical-order-traversal/)
4 |
5 | ## solution
6 |
7 | - bfs,同时记录当前节点的垂直位置
8 |
9 | ```python
10 | import collections
11 |
12 | class Solution(object):
13 | def verticalOrder(self, root):
14 | if not root: # 注意边界
15 | return []
16 |
17 | # queue = collections.deque([(root, 0)]) # 注意初始化时每个item是(root, distance)的tuple
18 | queue = collections.deque()
19 | queue.append((root, 0))
20 | res_dict = collections.defaultdict(list) # 注意结果保存的数据结构
21 |
22 | while queue:
23 | for _ in range(len(queue)):
24 | node, distance = queue.popleft()
25 | res_dict[distance].append(node.val)
26 | if node.left:
27 | queue.append((node.left, distance - 1))
28 | if node.right:
29 | queue.append((node.right, distance + 1))
30 |
31 | res = []
32 | for key in sorted(res_dict): # 可以直接对字典的key进行排序
33 | res.append(res_dict[key])
34 | return res
35 | ```
36 |
37 | 时间复杂度:O(nlog(n))
38 | 空间复杂度:O(n)
39 |
40 | - 时间复杂度O(n)优化
41 |
42 | ## follow up
43 |
44 | [987. Vertical Order Traversal of a Binary Tree](../07_dfs/987.%20Vertical%20Order%20Traversal%20of%20a%20Binary%20Tree.md)
45 |
--------------------------------------------------------------------------------
/01_leetcode/08_bfs/366. Find Leaves of Binary Tree.md:
--------------------------------------------------------------------------------
1 | # 366. Find Leaves of Binary Tree
2 |
3 | [https://leetcode.com/problems/find-leaves-of-binary-tree/](https://leetcode.com/problems/find-leaves-of-binary-tree/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def findLeaves(self, root: Optional[TreeNode]) -> List[List[int]]:
10 | ans = []
11 |
12 | def dfs(root):
13 | if not root:
14 | return -1
15 |
16 | left = dfs(root.left)
17 | right = dfs(root.right)
18 | h = max(left, right) + 1
19 |
20 | if len(ans) == h:
21 | ans.append([])
22 |
23 | ans[h].append(root.val)
24 | return h
25 |
26 | dfs(root)
27 | return ans
28 | ```
29 |
30 | 时间复杂度:O(n)
31 | 空间复杂度:O(h)
32 |
--------------------------------------------------------------------------------
/01_leetcode/08_bfs/444. Sequence Reconstruction.md:
--------------------------------------------------------------------------------
1 | # 444. Sequence Reconstruction
2 |
3 | [https://leetcode.com/problems/sequence-reconstruction/](https://leetcode.com/problems/sequence-reconstruction/)
4 |
5 | ## solution
6 |
7 | ```python
8 |
9 | ```
10 |
11 | 时间复杂度:O()
12 | 空间复杂度:O()
13 |
--------------------------------------------------------------------------------
/01_leetcode/08_bfs/542. 01 Matrix.md:
--------------------------------------------------------------------------------
1 | # 542. 01 Matrix
2 |
3 | [https://leetcode.com/problems/01-matrix/](https://leetcode.com/problems/01-matrix/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def updateMatrix(self, mat: List[List[int]]) -> List[List[int]]:
10 | queue = collections.deque()
11 | m = len(mat)
12 | n = len(mat[0])
13 | for i in range(m):
14 | for j in range(n):
15 | if mat[i][j] == 0:
16 | queue.append([i, j])
17 | else:
18 | mat[i][j] = '*'
19 |
20 | step = 0
21 | dirs = [[1, 0], [0, 1], [-1, 0], [0, -1]]
22 | while queue:
23 | step += 1
24 | for i in range(len(queue)):
25 | this_x, this_y = queue.popleft()
26 | for step_x, step_y in dirs:
27 | new_x = this_x + step_x
28 | new_y = this_y + step_y
29 | if new_x >=0 and new_x < m and new_y >= 0 and new_y < n and mat[new_x][new_y] == '*':
30 | mat[new_x][new_y] = step
31 | queue.append([new_x, new_y])
32 | return mat
33 | ```
34 |
35 | 时间复杂度:O(mn)
36 | 空间复杂度:O(mn)
37 |
38 | - 动态规划
39 |
40 | ```python
41 |
42 | ```
43 |
--------------------------------------------------------------------------------
/01_leetcode/08_bfs/752. Open the Lock.md:
--------------------------------------------------------------------------------
1 | # 752. Open the Lock
2 |
3 | [https://leetcode.com/problems/open-the-lock/](https://leetcode.com/problems/open-the-lock/)
4 |
5 | ## solution
6 |
7 | - 最短路径 -> BFS
8 |
9 | ```python
10 | class Solution:
11 | def openLock(self, deadends: List[str], target: str) -> int:
12 | if '0000' in deadends:
13 | return -1 # 注意, 如果把deadend和target的判断放在pop后面判断,反而避免杜绝了该问题?
14 | if target == '0000':
15 | return 0
16 |
17 | deadends = set(deadends)
18 | visited = set()
19 | visited.add('0000')
20 | queue = collections.deque([('0000', 0)]) # 还是要注意这里两层, append时一层
21 |
22 | while queue:
23 | node, step = queue.popleft()
24 |
25 | for i in range(4):
26 | for j in [1, -1]:
27 | new_i = (int(node[i]) + j) % 10
28 | new_node = node[:i] + str(new_i) + node[i+1:]
29 |
30 | if new_node in deadends:
31 | continue
32 |
33 | if new_node == target:
34 | return step + 1
35 |
36 | if new_node not in visited:
37 | visited.add(new_node)
38 | queue.append((new_node, step + 1))
39 | return -1
40 | ```
41 |
42 | 时间复杂度:O(10^4)
43 | 空间复杂度:O(10^4)
44 |
--------------------------------------------------------------------------------
/01_leetcode/08_bfs/815. Bus Routes.md:
--------------------------------------------------------------------------------
1 | # 815. Bus Routes
2 |
3 | [https://leetcode.com/problems/bus-routes/](https://leetcode.com/problems/bus-routes/)
4 |
5 | ## solution
6 |
7 | ```python
8 | import collections
9 |
10 | class Solution:
11 | def numBusesToDestination(self, routes: List[List[int]], source: int, target: int) -> int:
12 | if source == target:
13 | return 0
14 |
15 | graph = collections.defaultdict(list)
16 | visited = set()
17 |
18 | for i in range(len(routes)):
19 | for j in routes[i]:
20 | # {站点: 所属路线}
21 | graph[j].append(i)
22 |
23 | res = 0
24 | queue = collections.deque()
25 | queue.append(source)
26 |
27 | # BFS解法关键在于: 一次加入一个route的stop. 所以比常见最短路径多了一层for
28 | while queue:
29 | res += 1
30 | for _ in range(len(queue)):
31 | node = queue.popleft()
32 | for route in graph[node]:
33 | if route in visited:
34 | continue
35 | visited.add(route)
36 |
37 | for next_stop in routes[route]:
38 | if next_stop == target:
39 | return res
40 | queue.append(next_stop)
41 | return -1
42 | ```
43 |
44 | 时间复杂度:O()
45 | 空间复杂度:O()
46 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/10. Regular Expression Matching.md:
--------------------------------------------------------------------------------
1 | # 10. Regular Expression Matching
2 |
3 | [https://leetcode.com/problems/regular-expression-matching/](https://leetcode.com/problems/regular-expression-matching/)
4 |
5 | ## solution
6 |
7 | - 动态规划
8 | - \* 意味着从前面转移而来
9 |
10 | ```python
11 | # dp[i][j]: s[0:i-1], p[0: j-1]的子字符串是否符合
12 |
13 | class Solution:
14 | def isMatch(self, s: str, p: str) -> bool:
15 | m = len(s)
16 | n = len(p)
17 | dp = [[False] * (n + 1) for _ in range(m + 1)]
18 |
19 | dp[0][0] = True
20 | for j in range(2, n + 1):
21 | if p[j-1] == '*':
22 | dp[0][j] = dp[0][j-2] # *取0个时
23 |
24 | for i in range(1, m+1):
25 | for j in range(1, n+1):
26 | if s[i-1] == p[j-1] or p[j-1] == '.':
27 | dp[i][j] = dp[i-1][j-1]
28 | elif p[j-1] == '*':
29 | if p[j-2] == s[i-1] or p[j-2] == '.':
30 | dp[i][j] = dp[i][j-2] or dp[i-1][j]
31 | else:
32 | dp[i][j] = dp[i][j-2]
33 | return dp[-1][-1]
34 | ```
35 |
36 | 时间复杂度:O(mn)
37 | 空间复杂度:O(mn)
38 |
39 | ## follow up
40 |
41 | [44 Wildcard Matching](./44.%20Wildcard%20Matching.md)
42 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/1043. Partition Array for Maximum Sum.md:
--------------------------------------------------------------------------------
1 | # 1043. Partition Array for Maximum Sum
2 |
3 | [https://leetcode.com/problems/partition-array-for-maximum-sum/](https://leetcode.com/problems/partition-array-for-maximum-sum/)
4 |
5 | ## solution
6 |
7 | ```python
8 |
9 | ```
10 |
11 | 时间复杂度:O()
12 | 空间复杂度:O()
13 |
14 | ## follow up
15 |
16 | [410. Split Array Largest Sum](../00_binary_search/410.%20Split%20Array%20Largest%20Sum.md)
17 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/1062. Longest Repeating Substring.md:
--------------------------------------------------------------------------------
1 | # 1062. Longest Repeating Substring
2 |
3 | [https://leetcode.com/problems/longest-repeating-substring/](https://leetcode.com/problems/longest-repeating-substring/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def longestRepeatingSubstring(self, s: str) -> int:
10 | n = len(s)
11 | dp = [[0] * n for _ in range(n)]
12 | max_length = 0
13 | for i in range(n):
14 | for j in range(i + 1, n):
15 | if s[i] == s[j]:
16 | dp[i][j] = dp[i - 1][j - 1] + 1 if i else 1
17 | max_length = max(max_length, dp[i][j])
18 | return max_length
19 | ```
20 |
21 | 时间复杂度:O(n^2)
22 | 空间复杂度:O(n^2)
23 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/115. Distinct Subsequences.md:
--------------------------------------------------------------------------------
1 | # 115. Distinct Subsequences
2 |
3 | [https://leetcode.com/problems/distinct-subsequences/](https://leetcode.com/problems/distinct-subsequences/)
4 |
5 | ## solution
6 |
7 | - 递归-分治-记忆化dfs
8 |
9 | ```python
10 | # S 每个字母就是两种状态:选或者不选
11 | # https://leetcode.wang/leetcode-115-Distinct-Subsequences.html
12 |
13 | ```
14 |
15 | 时间复杂度:O()
16 | 空间复杂度:O()
17 |
18 | - 动态规划
19 | - dp含义:`dp[i][j]` 以i-1结尾的子序列和以j-1结尾的子序列个数
20 | - dp推导:不同状态分别对待,如果相等时,用和不用
21 |
22 | ```python
23 | class Solution:
24 | def numDistinct(self, s: str, t: str) -> int:
25 | m = len(s)
26 | n = len(t)
27 | dp = [[0] * (n + 1) for _ in range(m+1)]
28 |
29 | for i in range(m+1):
30 | dp[i][0] = 1
31 |
32 | for i in range(1, m+1):
33 | for j in range(1, n+1):
34 | if s[i-1] == t[j-1]:
35 | dp[i][j] = dp[i-1][j-1] + dp[i-1][j]
36 | else: # 根据dp含义, 不相等也要传播下去
37 | dp[i][j] = dp[i-1][j]
38 | return dp[-1][-1]
39 | ```
40 |
41 | 时间复杂度:O()
42 | 空间复杂度:O()
43 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/1216. Valid Palindrome III.md:
--------------------------------------------------------------------------------
1 | # 1216. Valid Palindrome III
2 |
3 | [https://leetcode.com/problems/valid-palindrome-iii/](https://leetcode.com/problems/valid-palindrome-iii/)
4 |
5 | ## solution
6 |
7 | ```python
8 | # https://www.geeksforgeeks.org/find-if-string-is-k-palindrome-or-not/
9 | # 680 的更普遍情况, 编辑距离72的变种, 516一样的设计
10 | # dp[i][j]: 字符串中i到j修正成回文串所需的最少操作次数, 子串 -> 子序列
11 |
12 | ```
13 |
14 | 时间复杂度:O()
15 | 空间复杂度:O()
16 |
17 | ## follow up
18 |
19 | [回文类](../01_two_pointers/5.%20Longest%20Palindromic%20Substring.md)
20 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/1235. Maximum Profit in Job Scheduling.md:
--------------------------------------------------------------------------------
1 | # 1235. Maximum Profit in Job Scheduling
2 |
3 | [https://leetcode.com/problems/maximum-profit-in-job-scheduling/](https://leetcode.com/problems/maximum-profit-in-job-scheduling/)
4 |
5 | ## solution
6 |
7 | ```python
8 | # dp[i]: max(包含本job利润,不包含本job利润),包含时需要用二分查找从前面job中找到开始时间不冲突的
9 |
10 | class Solution:
11 | def jobScheduling(self, startTime: List[int], endTime: List[int], profit: List[int]) -> int:
12 | jobs = sorted(zip(endTime, startTime, profit))
13 | number_of_jobs = len(profit)
14 |
15 | dp = [0] * (number_of_jobs + 1)
16 | for i, (current_end_time, current_start_time, current_profit) in enumerate(jobs):
17 | index = bisect.bisect_right(jobs, current_start_time, hi=i, key=lambda x: x[0])
18 | dp[i + 1] = max(dp[i], dp[index] + current_profit)
19 | return dp[number_of_jobs]
20 | ```
21 |
22 | 时间复杂度:O(nlog(n))
23 | 空间复杂度:O(n)
24 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/1277. Count Square Submatrices with All Ones.md:
--------------------------------------------------------------------------------
1 | # 1277. Count Square Submatrices with All Ones
2 |
3 | [https://leetcode.com/problems/count-square-submatrices-with-all-ones/](https://leetcode.com/problems/count-square-submatrices-with-all-ones/)
4 |
5 | ## solution
6 |
7 | ```python
8 |
9 | ```
10 |
11 | 时间复杂度:O()
12 | 空间复杂度:O()
13 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/132. Palindrome Partitioning II.md:
--------------------------------------------------------------------------------
1 | # 132. Palindrome Partitioning II
2 |
3 | [https://leetcode.com/problems/palindrome-partitioning-ii/description/](https://leetcode.com/problems/palindrome-partitioning-ii/description/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def minCut(self, s: str) -> int:
10 | n = len(s)
11 | # isPalindrome[i][j] := True if s[i..j] is a palindrome
12 | isPalindrome = [[True] * n for _ in range(n)]
13 | # dp[i] := the minimum cuts needed for a palindrome partitioning of s[0..i]
14 | dp = [n] * n
15 |
16 | for l in range(2, n + 1):
17 | i = 0
18 | for j in range(l - 1, n):
19 | isPalindrome[i][j] = s[i] == s[j] and isPalindrome[i + 1][j - 1]
20 | i += 1
21 |
22 | for i in range(n):
23 | if isPalindrome[0][i]:
24 | dp[i] = 0
25 | continue
26 |
27 | # Try all the possible partitions.
28 | for j in range(i):
29 | if isPalindrome[j + 1][i]:
30 | dp[i] = min(dp[i], dp[j] + 1)
31 |
32 | return dp[-1]
33 | ```
34 |
35 | 时间复杂度:O()
36 | 空间复杂度:O()
37 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/1335. Minimum Difficulty of a Job Schedule.md:
--------------------------------------------------------------------------------
1 | # 1335. Minimum Difficulty of a Job Schedule
2 |
3 | [https://leetcode.com/problems/minimum-difficulty-of-a-job-schedule/](https://leetcode.com/problems/minimum-difficulty-of-a-job-schedule/)
4 |
5 | ## solution
6 |
7 | - 给定的数组 jobDifficulty 分为d个子数组,然后将每个子数组中的最大值加起来,使得这个总和最小
8 |
9 | ```python
10 | class Solution:
11 | def minDifficulty(self, jobDifficulty: List[int], d: int) -> int:
12 | n = len(jobDifficulty)
13 | if d > n:
14 | return -1
15 |
16 | # dp[i][k] := the minimum difficulty to schedule the first i jobs in k days
17 | dp = [[math.inf] * (d + 1) for _ in range(n + 1)]
18 | dp[0][0] = 0
19 |
20 | for i in range(1, n + 1):
21 | for k in range(1, d + 1):
22 | maxDifficulty = 0 # max(job[j + 1..i])
23 | for j in range(i - 1, k - 2, -1): # 1-based
24 | maxDifficulty = max(maxDifficulty, jobDifficulty[j]) # 0-based
25 | dp[i][k] = min(dp[i][k], dp[j][k - 1] + maxDifficulty)
26 | return dp[n][d]
27 | ```
28 |
29 | 时间复杂度:O()
30 | 空间复杂度:O()
31 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/174. Dungeon Game.md:
--------------------------------------------------------------------------------
1 | # 174. Dungeon Game
2 |
3 | [https://leetcode.com/problems/dungeon-game/](https://leetcode.com/problems/dungeon-game/)
4 |
5 | ## solution
6 |
7 | ```python
8 | # 1. 只能两个方向 -> 动态规划;2. 中途必须大于1 -> 从目标出发
9 | # 空间复杂度可进一步优化至O(n)
10 |
11 | class Solution:
12 | def calculateMinimumHP(self, dungeon: List[List[int]]) -> int:
13 | m = len(dungeon)
14 | n = len(dungeon[0])
15 |
16 | dp = [[float('inf')] * (n + 1) for _ in range(m + 1)]
17 | dp[m][n-1] = 1
18 | dp[m-1][n] = 1
19 |
20 | for i in range(m-1, -1, -1):
21 | for j in range(n-1, -1, -1):
22 | dp[i][j] = max(1, min(dp[i+1][j], dp[i][j+1]) - dungeon[i][j])
23 |
24 | return dp[0][0]
25 | ```
26 |
27 | 时间复杂度:O(mn)
28 | 空间复杂度:O(mn)
29 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/198. House Robber.md:
--------------------------------------------------------------------------------
1 | # 198. House Robber
2 |
3 | [https://leetcode.com/problems/house-robber/](https://leetcode.com/problems/house-robber/)
4 |
5 | ## solution
6 |
7 | - 只用到两个状态的DP,可以进一步优化空间
8 |
9 | ```python
10 | class Solution:
11 | def rob(self, nums: List[int]) -> int:
12 | if len(nums) <= 2:
13 | return max(nums)
14 |
15 | dp = [0] * len(nums)
16 | dp[0] = nums[0]
17 | dp[1] = max(nums[0], nums[1])
18 | for i in range(2, len(nums)):
19 | dp[i] = max(dp[i-1], dp[i-2]+nums[i])
20 | return dp[-1]
21 | ```
22 |
23 | 时间复杂度:O(n)
24 | 空间复杂度:O(n)
25 |
26 | ## follow up
27 |
28 | [213 House Robber II](./213.%20House%20Robber%20II.md)
29 |
30 | [337. House Robber III](https://leetcode.com/problems/house-robber-iii/)
31 |
32 | - 树形DP
33 | - 此外,还有三角形DP [120. Triangle](https://leetcode.com/problems/triangle/description/)
34 |
35 | ```python
36 | class Solution:
37 | def rob(self, root: Optional[TreeNode]) -> int:
38 | dp = self.traversal(root)
39 | return max(dp)
40 |
41 | def traversal(self, root):
42 | if not root:
43 | return (0, 0)
44 |
45 | l = self.traversal(root.left)
46 | r = self.traversal(root.right)
47 |
48 | val0 = max(l[0], l[1]) + max(r[0], r[1]) # 不偷当前节点
49 | val1 = root.val + l[0] + r[0] # 偷当前节点
50 | return [val0, val1]
51 | ```
52 |
53 | 时间复杂度:O()
54 | 空间复杂度:O()
55 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/213. House Robber II.md:
--------------------------------------------------------------------------------
1 | # 213. House Robber II
2 |
3 | [https://leetcode.com/problems/house-robber-ii/](https://leetcode.com/problems/house-robber-ii/)
4 |
5 | ## solution
6 |
7 | - 首尾相连, 从整体上分两个状态来考虑
8 |
9 | ```python
10 | class Solution:
11 | def rob(self, nums: List[int]) -> int:
12 | if len(nums) == 0:
13 | return 0
14 | if len(nums) == 1:
15 | return nums[0]
16 |
17 | res1 = self._run_rob(nums, 0, len(nums)-2)
18 | res2 = self._run_rob(nums, 1, len(nums)-1)
19 | return max(res1, res2)
20 |
21 | def _run_rob(self, nums, start, end): # 左闭右闭
22 | if end == start:
23 | return nums[start]
24 |
25 | pre = nums[start]
26 | cur = max(nums[start], nums[start+1])
27 |
28 | for i in range(start+2, end+1):
29 | tmp = cur
30 | cur = max(pre+nums[i], cur)
31 | pre = tmp
32 | return cur
33 | ```
34 |
35 | 时间复杂度:O()
36 | 空间复杂度:O()
37 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/221. Maximal Square.md:
--------------------------------------------------------------------------------
1 | # 221. Maximal Square
2 |
3 | [https://leetcode.com/problems/maximal-square/](https://leetcode.com/problems/maximal-square/)
4 |
5 | ## solution
6 |
7 | - 2d动态规划, dp[i][j]以matrix[i-1][j-1]为右下底的全是1的最大square的**边长**
8 | - 因为涉及到前面的状态,i-1和j-1来简化初始化过程
9 | - Space can be optimized as we don't need to keep the whole dp grid as we progress down the rows in matrix
10 |
11 | ```python
12 | class Solution:
13 | def maximalSquare(self, matrix: List[List[str]]) -> int:
14 | if not matrix:
15 | return 0
16 |
17 | m = len(matrix)
18 | n = len(matrix[0])
19 |
20 | dp = [[0] * (n + 1) for _ in range(m + 1)]
21 |
22 | max_len = 0
23 | for i in range(m):
24 | for j in range(n):
25 | if matrix[i][j] == '1':
26 | # 有些tricky
27 | dp[i+1][j+1] = min(dp[i][j], dp[i+1][j], dp[i][j+1]) + 1
28 | if dp[i+1][j+1] > max_len:
29 | max_len = dp[i+1][j+1]
30 | return max_len * max_len
31 | ```
32 |
33 | 时间复杂度:O(m*n)
34 | 空间复杂度:Onm*N)
35 |
36 | ## follow up
37 |
38 | [85. Maximal Rectangle](../05_stack_queue/85.%20Maximum%20Rectangle.md)
39 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/256. Paint House.md:
--------------------------------------------------------------------------------
1 | # 256. Paint House
2 |
3 | [https://leetcode.com/problems/paint-house](https://leetcode.com/problems/paint-house)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def minCost(self, costs: List[List[int]]) -> int:
10 | cost_red = cost_blue = cost_green = 0
11 | for cost_of_red, cost_of_blue, cost_of_green in costs:
12 | new_cost_red = min(cost_blue, cost_green) + cost_of_red
13 | new_cost_blue = min(cost_red, cost_green) + cost_of_blue
14 | new_cost_green = min(cost_red, cost_blue) + cost_of_green
15 | cost_red, cost_blue, cost_green = new_cost_red, new_cost_blue, new_cost_green
16 | return min(cost_red, cost_blue, cost_green)
17 | ```
18 |
19 | 时间复杂度:O(n)
20 | 空间复杂度:O(1)
21 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/300. Longest Increasing Subsequence.md:
--------------------------------------------------------------------------------
1 | # 300. Longest Increasing Subsequence
2 |
3 | [https://leetcode.com/problems/longest-increasing-subsequence/](https://leetcode.com/problems/longest-increasing-subsequence/)
4 |
5 | ## solution
6 |
7 | - dp
8 |
9 | ```python
10 | class Solution:
11 | def lengthOfLIS(self, nums: List[int]) -> int:
12 | if not nums:
13 | return
14 |
15 | dp = [1] * len(nums) # dp[i]: 以nums[i]结尾的最长子序列
16 | for i in range(1, len(nums)):
17 | for j in range(i):
18 | if nums[i] > nums[j]:
19 | dp[i] = max(dp[i], dp[j]+1)
20 | return max(dp)
21 | ```
22 |
23 | 时间复杂度:O(n^2)
24 | 空间复杂度:O(n)
25 |
26 | - binary search
27 |
28 | ```python
29 | class Solution:
30 | def lengthOfLIS(self, nums: list[int]) -> int:
31 | tails = []
32 | for num in nums:
33 | if not tails or num > tails[-1]:
34 | tails.append(num)
35 | else:
36 | tails[bisect.bisect_left(tails, num)] = num
37 | return len(tails)
38 | ```
39 |
40 | 时间复杂度:O(nlog(n))
41 | 空间复杂度:O(n)
42 |
43 | ## follow up
44 |
45 | [674 Longest Continuous Increasing Subsequence](./674.%20Longest%20Continuous%20Increasing%20Subsequence.md)
46 |
47 | - 最长连续递增序列,由于要求必须连续,因此只需要dp(i)与dp(i-1)比较即可
48 |
49 | [646. Maximum Length of Pair Chain](https://leetcode.com/problems/maximum-length-of-pair-chain/description/)
50 |
51 | ```python
52 |
53 | ```
54 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/312. Burst Balloons.md:
--------------------------------------------------------------------------------
1 | # 312. Burst Balloons
2 |
3 | [https://leetcode.com/problems/burst-balloons/](https://leetcode.com/problems/burst-balloons/)
4 |
5 | ## solution
6 |
7 | ```python
8 | # https://leetcode.com/problems/burst-balloons/solutions/1659427/python-beginner-brute-force-recursion-brute-better-memoization-dp/
9 | # https://www.cnblogs.com/niuyourou/p/11964842.html
10 | # dp[i][j] = max([dp[i][k-1] + nums[i-1]*nums[k]*nums[j+1] + dp[k+1][j])_{i <= k <= j}
11 |
12 | class Solution:
13 | def maxCoins(self, nums: List[int]) -> int:
14 | nums = [1] + nums + [1]
15 | dp = [[0] * len(nums) for _ in range(len(nums))]
16 |
17 | for gap in range(len(nums)): # 从短的开始构建, 依次求打破一个气球的,打破两个气球的
18 | for left in range(len(nums) - gap):
19 | right = left + gap
20 |
21 | res = 0
22 | for k in range(left + 1, right):
23 | res = max(res, dp[left][k] + nums[left] * nums[k] * nums[right] + dp[k][right])
24 |
25 | dp[left][right] = res
26 | return dp[0][len(nums) - 1]
27 | ```
28 |
29 | 时间复杂度:O()
30 | 空间复杂度:O()
31 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/32. Longest Valid Parentheses.md:
--------------------------------------------------------------------------------
1 | # 32. Longest Valid Parentheses
2 |
3 | [https://leetcode.com/problems/longest-valid-parentheses/](https://leetcode.com/problems/longest-valid-parentheses/)
4 |
5 | ## solution
6 |
7 | - 动态规划
8 | - 以s[i]结尾的字符串能够构成的最长的匹配串的长度
9 |
10 | ```python
11 | # https://zhuanlan.zhihu.com/p/110240060
12 |
13 |
14 | ```
15 |
16 | 时间复杂度:O()
17 | 空间复杂度:O()
18 |
19 | - 经典做法
20 | - 一个栈维护左括号的下标,然后遇到匹配的右括号时弹出左括号并通过下标计算长度
21 |
22 | ```python
23 | class Solution:
24 | def longestValidParentheses(self, s: str) -> int:
25 | max_len = 0
26 | stack = [-1]
27 | for i in range(len(s)):
28 |
29 | if s[i] == '(':
30 | stack.append(i)
31 | else:
32 | stack.pop()
33 | if not stack:
34 | stack.append(i)
35 | else:
36 | max_len = max(max_len, i - stack[-1])
37 | return max_len
38 | ```
39 |
40 | ## follow op
41 |
42 | [括号类小结](../07_dfs/22.%20Generate%20Parentheses.md)
43 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/354. Russian Doll Envelopes.md:
--------------------------------------------------------------------------------
1 | # 354. Russian Doll Envelopes
2 |
3 | [https://leetcode.com/problems/russian-doll-envelopes/](https://leetcode.com/problems/russian-doll-envelopes/)
4 |
5 | ## solution
6 |
7 | ```python
8 |
9 | ```
10 |
11 | 时间复杂度:O()
12 | 空间复杂度:O()
13 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/368. Largest Divisible Subset.md:
--------------------------------------------------------------------------------
1 | # 368. Largest Divisible Subset
2 |
3 | [https://leetcode.com/problems/largest-divisible-subset/](https://leetcode.com/problems/largest-divisible-subset/)
4 |
5 | ## solution
6 |
7 | ```python
8 |
9 | ```
10 |
11 | 时间复杂度:O()
12 | 空间复杂度:O()
13 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/377. Combination Sum IV.md:
--------------------------------------------------------------------------------
1 | # 377. Combination Sum IV
2 |
3 | [https://leetcode.com/problems/combination-sum-iv/](https://leetcode.com/problems/combination-sum-iv/)
4 |
5 | ## solution
6 |
7 | - 完全背包|求组合方案个数
8 |
9 | ```python
10 | class Solution:
11 | def combinationSum4(self, nums: List[int], target: int) -> int:
12 | dp = [0] * (target + 1)
13 | dp[0] = 1
14 | # 排列: 先物品再背包
15 | # 组合: 先背包在物品 (本题)
16 | for i in range(1, target+1):
17 | for num in nums:
18 | if i - num >= 0:
19 | dp[i] += dp[i - num]
20 | return dp[target]
21 | ```
22 |
23 | 时间复杂度:O(∣coins∣⋅target)
24 | 空间复杂度:O(target)
25 |
26 | - dfs
27 |
28 | ```python
29 |
30 | ```
31 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/403. Frog Jump.md:
--------------------------------------------------------------------------------
1 | # 403. Frog Jump
2 |
3 | [https://leetcode.com/problems/frog-jump/](https://leetcode.com/problems/frog-jump/)
4 |
5 | ## solution
6 |
7 | ```python
8 |
9 | ```
10 |
11 | 时间复杂度:O()
12 | 空间复杂度:O()
13 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/44. Wildcard Matching.md:
--------------------------------------------------------------------------------
1 | # 44. Wildcard Matching
2 |
3 | [https://leetcode.com/problems/wildcard-matching/](https://leetcode.com/problems/wildcard-matching/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def isMatch(self, s: str, p: str) -> bool:
10 | dp = [[False] * (len(p) + 1) for _ in range(len(s) + 1)]
11 | dp[0][0] = True
12 |
13 | for j in range(1, len(p) + 1):
14 | # 如果前面全都是*开头, 则全都是True
15 | if p[j-1] != '*':
16 | break
17 | dp[0][j] = True
18 |
19 | for i in range(1, len(s) + 1):
20 | for j in range(1, len(p) + 1):
21 | if p[j-1] == s[i-1] or p[j-1] == '?':
22 | dp[i][j] = dp[i-1][j-1]
23 | elif p[j-1] == '*':
24 | # 代表0个或多个, 0个相当于dp[i-1][j], 多个相当于dp[i][j-1]
25 | dp[i][j] = dp[i-1][j] or dp[i][j-1]
26 | return dp[-1][-1]
27 | ```
28 |
29 | 时间复杂度:O()
30 | 空间复杂度:O()
31 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/472. Concatenated Words.md:
--------------------------------------------------------------------------------
1 | # 472. Concatenated Words
2 |
3 | [https://leetcode.com/problems/concatenated-words/](https://leetcode.com/problems/concatenated-words/)
4 |
5 | ## solution
6 |
7 | ```python
8 |
9 | ```
10 |
11 | 时间复杂度:O()
12 | 空间复杂度:O()
13 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/518. Coin Change II.md:
--------------------------------------------------------------------------------
1 | # 518. Coin Change II
2 |
3 | [https://leetcode.com/problems/coin-change-ii/](https://leetcode.com/problems/coin-change-ii/)
4 |
5 | ## solution
6 |
7 | - 完全背包
8 | - 01背包和完全背包区别在于,对背包遍历顺序是右到左,还是左到右
9 | - 注意遍历顺序,物品还是背包决定了结果是排列还是组合
10 |
11 | ```python
12 | class Solution:
13 | def change(self, amount: int, coins: List[int]) -> int:
14 | dp = [0] * (amount + 1)
15 | dp[0] = 1
16 | for i in range(len(coins)):
17 | for j in range(coins[i], amount+1):
18 | dp[j] += dp[j-coins[i]]
19 | return dp[amount]
20 | ```
21 |
22 | 时间复杂度:O(|coins|⋅amount)
23 | 空间复杂度:O(amount)
24 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/639. Decode Ways II.md:
--------------------------------------------------------------------------------
1 | # 639. Decode Ways II
2 |
3 | [https://leetcode.com/problems/decode-ways-ii/](https://leetcode.com/problems/decode-ways-ii/)
4 |
5 | ## solution
6 |
7 | ```python
8 |
9 | ```
10 |
11 | 时间复杂度:O()
12 | 空间复杂度:O()
13 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/64. Minimum Path Sum.md:
--------------------------------------------------------------------------------
1 | # 64. Minimum Path Sum
2 |
3 | [https://leetcode.com/problems/minimum-path-sum/](https://leetcode.com/problems/minimum-path-sum/)
4 |
5 | ## solution
6 |
7 | ```python
8 | # 原grid直接作为dp可以进一步优化空间
9 |
10 | class Solution:
11 | def minPathSum(self, grid: List[List[int]]) -> int:
12 | m = len(grid)
13 | n = len(grid[0])
14 | dp = [[0] * n for _ in range(m)]
15 | dp[0][0] = grid[0][0]
16 |
17 | for i in range(1, m):
18 | dp[i][0] = dp[i-1][0] + grid[i][0]
19 |
20 | for j in range(1, n):
21 | dp[0][j] = dp[0][j-1] + grid[0][j]
22 |
23 | for i in range(1, m):
24 | for j in range(1, n):
25 | dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j]
26 | return dp[-1][-1]
27 | ```
28 |
29 | 时间复杂度:O(mn)
30 | 空间复杂度:O(mn)
31 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/674. Longest Continuous Increasing Subsequence.md:
--------------------------------------------------------------------------------
1 | # 674. Longest Continuous Increasing Subsequence
2 |
3 | [https://leetcode.com/problems/longest-continuous-increasing-subsequence/](https://leetcode.com/problems/longest-continuous-increasing-subsequence/)
4 |
5 | ## solution
6 |
7 | - 贪心
8 |
9 | ```python
10 | class Solution:
11 | def findLengthOfLCIS(self, nums: List[int]) -> int:
12 | res = 1
13 | this_res = 1
14 | for i in range(1, len(nums)):
15 | if nums[i] > nums[i-1]:
16 | this_res += 1
17 | res = max(this_res, res)
18 | else:
19 | this_res = 1
20 | return res
21 | ```
22 |
23 | 时间复杂度:O()
24 | 空间复杂度:O()
25 |
26 | - 动态规划
27 | - 和[300 最长递增子序列](./300.%20Longest%20Increasing%20Subsequence.md)的区别在于,连续只需要和上一个比较;不连续则需要和之前挨个比较
28 | - 可以认为其follow up [718. 最长重复子数组](./718.%20Maximum%20Length%20of%20Repeated%20Subarray.md),只有某个条件下进行更新,否则维持初始值
29 |
30 | ```python
31 |
32 | ```
33 |
34 | 时间复杂度:O()
35 | 空间复杂度:O()
36 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/70. Climbing Stairs.md:
--------------------------------------------------------------------------------
1 | # 70. Climbing Stairs
2 |
3 | [https://leetcode.com/problems/climbing-stairs/](https://leetcode.com/problems/climbing-stairs/)
4 |
5 | ## solution
6 |
7 | ```python
8 | # 空间优化写法: 状态转移过程中只依赖过去两步
9 | class Solution:
10 | def climbStairs(self, n: int) -> int:
11 | if n <= 2:
12 | return n
13 | prev = 1
14 | cur = 2
15 | for i in range(3, n + 1):
16 | dp = prev + cur
17 | prev = cur
18 | cur = dp
19 | return cur
20 | ```
21 |
22 | 时间复杂度:O(n)
23 | 空间复杂度:O(1)
24 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/712. Minimum ASCII Delete Sum for Two Strings.md:
--------------------------------------------------------------------------------
1 | # 712. Minimum ASCII Delete Sum for Two Strings
2 |
3 | [https://leetcode.com/problems/minimum-ascii-delete-sum-for-two-strings/](https://leetcode.com/problems/minimum-ascii-delete-sum-for-two-strings/)
4 |
5 | ## solution
6 |
7 | ```python
8 |
9 | ```
10 |
11 | 时间复杂度:O()
12 | 空间复杂度:O()
13 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/718. Maximum Length of Repeated Subarray.md:
--------------------------------------------------------------------------------
1 | # 718. Maximum Length of Repeated Subarray
2 |
3 | [https://leetcode.com/problems/maximum-length-of-repeated-subarray/](https://leetcode.com/problems/maximum-length-of-repeated-subarray/)
4 |
5 | ## solution
6 |
7 | - 动态规划
8 | - 最长重复子数组,和[最长公共子序列](./1143%20Longest%20Common%20Subsequence.md)的不同在于需要子数组是连续的
9 | - 子数组的dp含义是: 以下标i - 1为结尾的A,和以下标j - 1为结尾的B,最长重复子数组长度为`dp[i][j]`
10 | - 公共子序列的dp含义是: 长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符串text2的最长公共子序列为`dp[i][j]`
11 | - 为什么是以...结尾的,否则断开之后,再有相同值的就会dp值会继续累加上去。因此要求连续的含义需要以...结尾的,不要求连续则是长度为...的
12 |
13 | ```python
14 | class Solution:
15 | def findLength(self, nums1: List[int], nums2: List[int]) -> int:
16 | # dp[i][j]: 以i-1为结尾的nums1和以nums2为结尾的nums2的最长重复子序列
17 | dp = [[0] * (len(nums2) + 1) for _ in range(len(nums1) + 1)]
18 | res = 0
19 | for i in range(1, len(nums1)+1):
20 | for j in range(1, len(nums2)+1):
21 | if nums1[i-1] == nums2[j-1]: # 这里一开始的判断条件写错了
22 | dp[i][j] = dp[i-1][j-1] + 1
23 | if dp[i][j] > res:
24 | res = dp[i][j]
25 | return res
26 | ```
27 |
28 | 时间复杂度:O()
29 | 空间复杂度:O()
30 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/740. Delete and Earn.md:
--------------------------------------------------------------------------------
1 | # 740. Delete and Earn
2 |
3 | [https://leetcode.com/problems/delete-and-earn/](https://leetcode.com/problems/delete-and-earn/)
4 |
5 | ## solution
6 |
7 | ```python
8 |
9 | ```
10 |
11 | 时间复杂度:O()
12 | 空间复杂度:O()
13 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/87. Scramble String.md:
--------------------------------------------------------------------------------
1 | # 87. Scramble String
2 |
3 | [https://leetcode.com/problems/scramble-string/](https://leetcode.com/problems/scramble-string/)
4 |
5 | ## solution
6 |
7 | ```python
8 |
9 | ```
10 |
11 | 时间复杂度:O()
12 | 空间复杂度:O()
13 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/91. Decode Ways.md:
--------------------------------------------------------------------------------
1 | # 91. Decode Ways
2 |
3 | [https://leetcode.com/problems/decode-ways/](https://leetcode.com/problems/decode-ways/)
4 |
5 | ## solution
6 |
7 | ```python
8 | # 状态转移的原因在于: 存在两位的字符(10-26), 斐波那契
9 |
10 | class Solution:
11 | def numDecodings(self, s: str) -> int:
12 | if s[0] == "0": # 非法,中途的非法通过条件判断
13 | return 0
14 |
15 | dp = [0] * (len(s) + 1)
16 | dp[0] = 1
17 | dp[1] = 1
18 |
19 | for i in range(2, len(s) + 1):
20 | if 1 <= int(s[i-1]) <= 9:
21 | dp[i] += dp[i - 1]
22 | if 10 <= int(s[i - 2] + s[i - 1]) <= 26 :
23 | dp[i] += dp[i - 2]
24 | return dp[-1]
25 | ```
26 |
27 | 时间复杂度:O(n)
28 | 空间复杂度:O(n)
29 |
30 | ## follow up
31 |
32 | [639 Decode Ways II](./639.%20Decode%20Ways%20II.md)
33 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/926. Flip String to Monotone Increasing.md:
--------------------------------------------------------------------------------
1 | # 926. Flip String to Monotone Increasing
2 |
3 | [https://leetcode.com/problems/flip-string-to-monotone-increasing/](https://leetcode.com/problems/flip-string-to-monotone-increasing/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def minFlipsMonoIncr(self, s: str) -> int:
10 | dp = 0
11 | count1 = 0
12 |
13 | for c in s:
14 | if c == '0':
15 | # 1. Flip '0'.
16 | # 2. Keep '0' and flip all the previous 1s.
17 | dp = min(dp + 1, count1)
18 | else:
19 | count1 += 1
20 | return dp
21 | ```
22 |
23 | 时间复杂度:O(n)
24 | 空间复杂度:O(1)
25 |
26 | ## follow up
27 |
28 | [1653. Minimum Deletions to Make String Balanced](../05_stack_queue/1249.%20Minimum%20Remove%20to%20Make%20Valid%20Parentheses.md)
29 |
--------------------------------------------------------------------------------
/01_leetcode/09_dynamic_program/97. Interleaving String.md:
--------------------------------------------------------------------------------
1 | # 97. Interleaving String
2 |
3 | [https://leetcode.com/problems/interleaving-string/](https://leetcode.com/problems/interleaving-string/)
4 |
5 | ## solution
6 |
7 | - 两个字符串,想到2D DP
8 |
9 | ```python
10 | class Solution:
11 | def isInterleave(self, s1: str, s2: str, s3: str) -> bool:
12 | if len(s1) + len(s2) != len(s3):
13 | return False
14 |
15 | m = len(s1)
16 | n = len(s2)
17 |
18 | dp = [[False] * (n + 1) for _ in range(m + 1)]
19 | dp[0][0] = True
20 |
21 | for i in range(1, m+1):
22 | if dp[i-1][0] and s1[i-1] == s3[i-1]:
23 | dp[i][0] = True
24 | else:
25 | break
26 |
27 | for j in range(1, n+1):
28 | if dp[0][j-1] and s2[j-1] == s3[j-1]:
29 | dp[0][j] = True
30 | else:
31 | break
32 |
33 | for i in range(1, m+1):
34 | for j in range(1, n+1):
35 | if (dp[i-1][j] and s1[i-1] == s3[i+j-1]) or (dp[i][j-1] and s2[j-1] == s3[i+j-1]):
36 | dp[i][j] = True
37 | return dp[-1][-1]
38 | ```
39 |
40 | 时间复杂度:O(mn)
41 | 空间复杂度:O()
42 |
--------------------------------------------------------------------------------
/01_leetcode/10_greedy/1005. Maximize Sum Of Array After K Negations.md:
--------------------------------------------------------------------------------
1 | # 1005. Maximize Sum Of Array After K Negations
2 |
3 | [https://leetcode.com/problems/maximize-sum-of-array-after-k-negations](https://leetcode.com/problems/maximize-sum-of-array-after-k-negations)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:
10 | nums.sort()
11 |
12 | n = 0
13 | for i, num in enumerate(nums):
14 | if n <= k-1 and num < 0:
15 | nums[i] = -nums[i]
16 | n += 1
17 | else:
18 | break
19 |
20 | if k > n:
21 | if (k - n) % 2 == 0:
22 | return sum(nums)
23 | else:
24 | nums.sort()
25 | nums[0] = -nums[0]
26 | return sum(nums)
27 | else:
28 | return sum(nums)
29 | ```
30 |
31 | 时间复杂度:O()
32 | 空间复杂度:O()
33 |
--------------------------------------------------------------------------------
/01_leetcode/10_greedy/134. Gas Station.md:
--------------------------------------------------------------------------------
1 | # 134. Gas Station
2 |
3 | [https://leetcode.com/problems/gas-station/](https://leetcode.com/problems/gas-station/)
4 |
5 | ## solution
6 |
7 | - 暴力法
8 |
9 | ```python
10 | class Solution:
11 | def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
12 | for i in range(len(gas)):
13 | rest = gas[i] - cost[i]
14 | next_index = (i + 1) % len(gas)
15 |
16 | while rest > 0 and next_index != i:
17 | rest += gas[next_index] - cost[next_index] # 注意这里是next_index
18 | next_index = (next_index + 1) % len(gas)
19 |
20 | if rest >= 0 and next_index == i:
21 | return i
22 | return -1
23 | ```
24 |
25 | 时间复杂度:O(n^2)
26 | 空间复杂度:O(1)
27 |
28 | - 贪心
29 |
30 | ```python
31 | class Solution:
32 | def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
33 | if sum(gas) < sum(cost):
34 | return -1
35 |
36 | tank = idx = 0
37 | for i in range(len(gas)):
38 | tank += gas[i] - cost[i]
39 | if tank < 0:
40 | tank = 0
41 | idx = i+1
42 | return idx
43 | ```
44 |
45 | 时间复杂度:O(n)
46 | 空间复杂度:O(1)
47 |
--------------------------------------------------------------------------------
/01_leetcode/10_greedy/135. Candy.md:
--------------------------------------------------------------------------------
1 | # 135. Candy
2 |
3 | [https://leetcode.com/problems/candy/](https://leetcode.com/problems/candy/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def candy(self, ratings: List[int]) -> int:
10 | res = [1 for _ in range(len(ratings))]
11 | for i in range(1, len(ratings)):
12 | if ratings[i] > ratings[i-1]:
13 | res[i] = res[i-1] + 1
14 |
15 | for j in range(len(ratings)-1, 0, -1):
16 | if ratings[j] < ratings[j-1]:
17 | res[j-1] = max(res[j-1], res[j]+1)
18 |
19 | return sum(res)
20 | ```
21 |
22 | 时间复杂度:O()
23 | 空间复杂度:O()
24 |
--------------------------------------------------------------------------------
/01_leetcode/10_greedy/406. Queue Reconstruction by Height.md:
--------------------------------------------------------------------------------
1 | # 406. Queue Reconstruction by Height
2 |
3 | [https://leetcode.com/problems/queue-reconstruction-by-height/](https://leetcode.com/problems/queue-reconstruction-by-height/)
4 |
5 | ## solution
6 |
7 | - 两个维度h和k,看到这种题目要想如何确定一个维度,然后再按照另一个维度重新排列
8 |
9 | ```python
10 | class Solution:
11 | def reconstructQueue(self, people: List[List[int]]) -> List[List[int]]:
12 | people.sort(key=lambda x: (-x[0], x[1])) # 高度升序, k降序
13 |
14 | que = []
15 | for p in people:
16 | que.insert(p[1], p)
17 | return que
18 | ```
19 |
20 | 时间复杂度:O()
21 | 空间复杂度:O()
22 |
--------------------------------------------------------------------------------
/01_leetcode/10_greedy/452. Minimum Number of Arrows to Burst Balloons.md:
--------------------------------------------------------------------------------
1 | # 452. Minimum Number of Arrows to Burst Balloons
2 |
3 | [https://leetcode.com/problems/minimum-number-of-arrows-to-burst-balloons/](https://leetcode.com/problems/minimum-number-of-arrows-to-burst-balloons/)
4 |
5 | ## solution
6 |
7 | - 关键,重叠一个后更新右边界用于判断下一个
8 |
9 | ```python
10 | class Solution:
11 | def findMinArrowShots(self, points: List[List[int]]) -> int:
12 | points.sort(key= lambda x: x[0])
13 | res = 1
14 | for i in range(1, len(points)):
15 | if points[i][0] > points[i-1][1]:
16 | res += 1
17 | else:
18 | points[i][1] = min(points[i][1], points[i-1][1])
19 | return res
20 | ```
21 |
22 | 时间复杂度:O()
23 | 空间复杂度:O()
24 |
25 | - interval题目template可以采用以下方式:记录额外一个结果表
26 |
27 | ```python
28 | class Solution:
29 | def findMinArrowShots(self, points: List[List[int]]) -> int:
30 | points.sort(key=lambda x: x[1])
31 |
32 | res_list = [points[0]]
33 | for i in range(1, len(points)):
34 | if points[i][0] <= res_list[-1][1]:
35 | l = max(points[i][0], res_list[-1][0])
36 | r = min(points[i][1], res_list[-1][1])
37 | res_list.pop()
38 | res_list.append([l, r])
39 | else:
40 | res_list.append(points[i])
41 | return len(res_list)
42 | ```
43 |
--------------------------------------------------------------------------------
/01_leetcode/10_greedy/621. Task Scheduler.md:
--------------------------------------------------------------------------------
1 | # 621. Task Scheduler
2 |
3 | [https://leetcode.com/problems/task-scheduler/](https://leetcode.com/problems/task-scheduler/)
4 |
5 | ## solution
6 |
7 | ```python
8 | import collections
9 |
10 | class Solution:
11 | def leastInterval(self, tasks: List[str], n: int) -> int:
12 | count_dict = collections.defaultdict(int)
13 | for task in tasks:
14 | count_dict[task] += 1
15 |
16 | max_freq = max(count_dict.values())
17 | max_freq_count = 0
18 | for key, value in count_dict.items():
19 | if value == max_freq:
20 | max_freq_count += 1
21 |
22 | res = (max_freq - 1) * (n + 1) + max_freq_count
23 | return max(res, len(tasks))
24 | ```
25 |
26 | 时间复杂度:O(|tasks|)
27 | 空间复杂度:O(1)
28 |
--------------------------------------------------------------------------------
/01_leetcode/10_greedy/763. Partition Labels.md:
--------------------------------------------------------------------------------
1 | # 763. Partition Labels
2 |
3 | [https://leetcode.com/problems/partition-labels/](https://leetcode.com/problems/partition-labels/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def partitionLabels(self, s: str) -> List[int]:
10 | # hash记录每个字母最后出现的index
11 | mydict = {}
12 | for i, char in enumerate(s):
13 | mydict[char] = i
14 |
15 | res = []
16 | start, end = 0, 0
17 | for i, char in enumerate(s):
18 | end = max(end, mydict[char])
19 | if i == end:
20 | res.append(end - start + 1)
21 | start = i + 1
22 |
23 | return res
24 | ```
25 |
26 | 时间复杂度:O(n)
27 | 空间复杂度:O(n)
28 |
--------------------------------------------------------------------------------
/01_leetcode/10_greedy/README.md:
--------------------------------------------------------------------------------
1 | # 贪心
2 |
3 | > - DFS:穷举每个子问题
4 | > - DP: 利用重叠子问题
5 | > - 贪心: 每次以子问题的最优解作为原问题的最优解
6 |
7 | 基本没有统一规律,变化多端. 多从解决问题角度出发思考
8 |
--------------------------------------------------------------------------------
/01_leetcode/11_prefix_sum/1031. Maximum Sum of Two Non-Overlapping Subarrays.md:
--------------------------------------------------------------------------------
1 | # 1031. Maximum Sum of Two Non-Overlapping Subarrays
2 |
3 | [https://leetcode.com/problems/maximum-sum-of-two-non-overlapping-subarrays/](https://leetcode.com/problems/maximum-sum-of-two-non-overlapping-subarrays/)
4 |
5 | ## solution
6 |
7 | - 注意利用已知条件: 有且只有两个
8 |
9 | ```python
10 | class Solution:
11 | def maxSumTwoNoOverlap(self, nums: List[int], firstLen: int, secondLen: int) -> int:
12 | def get_maxsum(l, r):
13 | max_l = ans = 0
14 | for i in range(l+r, len(prefix)):
15 | max_l = max(max_l, prefix[i-r] - prefix[i-r-l])
16 | ans = max(ans, max_l + prefix[i] - prefix[i-r])
17 | return ans
18 |
19 | prefix = [0] * (len(nums) + 1)
20 | for i, num in enumerate(nums):
21 | prefix[i+1] = prefix[i] + num
22 | return max(get_maxsum(firstLen, secondLen), get_maxsum(secondLen, firstLen))
23 | ```
24 |
25 | 时间复杂度:O()
26 | 空间复杂度:O()
27 |
--------------------------------------------------------------------------------
/01_leetcode/11_prefix_sum/1423. Maximum Points You Can Obtain from Cards.md:
--------------------------------------------------------------------------------
1 | # 1423. Maximum Points You Can Obtain from Cards
2 |
3 | [https://leetcode.com/problems/maximum-points-you-can-obtain-from-cards/](https://leetcode.com/problems/maximum-points-you-can-obtain-from-cards/)
4 |
5 | ## solution
6 |
7 | ```python
8 |
9 | ```
10 |
11 | 时间复杂度:O()
12 | 空间复杂度:O()
13 |
--------------------------------------------------------------------------------
/01_leetcode/11_prefix_sum/304. Range Sum Query 2D - Immutable.md:
--------------------------------------------------------------------------------
1 | # 304. Range Sum Query 2D - Immutable
2 |
3 | [https://leetcode.com/problems/range-sum-query-2d-immutable/](https://leetcode.com/problems/range-sum-query-2d-immutable/)
4 |
5 | ## solution
6 |
7 | - 把前缀和拓展到二维,即积分图(image integral)
8 |
9 | ```python
10 | class NumMatrix:
11 | def __init__(self, matrix: List[List[int]]):
12 | m = len(matrix)
13 | n = len(matrix[0])
14 |
15 | self.dp = [[0] * (n + 1) for _ in range(m + 1)] # 考虑到后续计算,这里必须+1. 顺便简化了dp初始化
16 |
17 | for i in range(m):
18 | for j in range(n):
19 | self.dp[i+1][j+1] = self.dp[i][j+1] + self.dp[i+1][j] - self.dp[i][j] + matrix[i][j]
20 |
21 | def sumRegion(self, row1: int, col1: int, row2: int, col2: int) -> int:
22 | return self.dp[row2+1][col2+1] - self.dp[row1][col2+1] - self.dp[row2+1][col1] + self.dp[row1][col1]
23 | ```
24 |
25 | 时间复杂度:O(mn)
26 | 空间复杂度:O(mn)
27 |
--------------------------------------------------------------------------------
/01_leetcode/11_prefix_sum/README.md:
--------------------------------------------------------------------------------
1 | # 前缀和
2 |
3 | prefix有多种类型,如prefix tree, prefix hashmap
4 |
5 | 使用双指针解决子数组之和的前提是:正数数组。当数组中有负数是,无法确定一个固定的方向,此时需要的就是前缀和。
6 |
7 | - 计算从下标0到各个位置的数组cumsum,把子数组看作是之前数组之和新加一个数字
8 | - prefix sum - target有无出现和出现的次数
9 |
--------------------------------------------------------------------------------
/01_leetcode/12_union_find/305. Number of Islands II.md:
--------------------------------------------------------------------------------
1 | # 305. Number of Islands II
2 |
3 | [https://leetcode.com/problems/number-of-islands-ii/](https://leetcode.com/problems/number-of-islands-ii/)
4 |
5 | ## solution
6 |
7 | ```python
8 |
9 | ```
10 |
11 | 时间复杂度:O()
12 | 空间复杂度:O()
13 |
--------------------------------------------------------------------------------
/01_leetcode/12_union_find/547. Number of Provinces.md:
--------------------------------------------------------------------------------
1 | # 547. Number of Provinces
2 |
3 | [https://leetcode.com/problems/number-of-provinces/](https://leetcode.com/problems/number-of-provinces/)
4 |
5 | ## solution
6 |
7 | - union find
8 |
9 | ```python
10 | class UF:
11 | def __init__(self, n):
12 | self.parents = list(range(n))
13 |
14 | def find(self, x):
15 | if self.parents[x] != x:
16 | self.parents[x] = self.find(self.parents[x])
17 | return self.parents[x]
18 |
19 | def union(self, parent, child):
20 | self.parents[self.find(child)] = self.find(parent)
21 |
22 | class Solution:
23 | def findCircleNum(self, isConnected: List[List[int]]) -> int:
24 | uf = UF(n=len(isConnected))
25 |
26 | for i in range(len(isConnected)):
27 | for j in range(i):
28 | if isConnected[i][j] == 1:
29 | uf.union(i, j)
30 |
31 | res = []
32 | for i in range(len(isConnected)):
33 | if uf.find(i) not in res:
34 | res.append(uf.find(i))
35 | return len(res)
36 | ```
37 |
38 | 时间复杂度:O()
39 | 空间复杂度:O()
40 |
41 | - dfs
42 |
43 | ```python
44 |
45 | ```
46 |
--------------------------------------------------------------------------------
/01_leetcode/12_union_find/684. Redundant Connection.md:
--------------------------------------------------------------------------------
1 | # 684. Redundant Connection
2 |
3 | [https://leetcode.com/problems/redundant-connection/](https://leetcode.com/problems/redundant-connection/)
4 |
5 | ## solution
6 |
7 | - 并查集
8 |
9 | ```python
10 |
11 | ```
12 |
13 | 时间复杂度:O()
14 | 空间复杂度:O()
15 |
16 | - bfs
17 |
18 | ```python
19 | class Solution:
20 | def findRedundantConnection(self, edges: List[List[int]]) -> List[int]:
21 | graph = collections.defaultdict(list)
22 | indegree = collections.defaultdict(int)
23 | for i, j in edges:
24 | graph[i].append(j)
25 | graph[j].append(i)
26 | indegree[i] += 1
27 | indegree[j] += 1
28 |
29 | queue = collections.deque([i for i, v in indegree.items() if v == 1])
30 |
31 | while queue:
32 | node = queue.popleft()
33 | for i in graph[node]:
34 | indegree[i] -= 1
35 | if indegree[i] == 1:
36 | queue.append(i)
37 |
38 | for a, b in edges[::-1]:
39 | if indegree[a] == 2 and indegree[b] == 2:
40 | return [a, b]
41 | ```
42 |
43 | 时间复杂度:O()
44 | 空间复杂度:O()
45 |
46 | ## follow up
47 |
48 | [685. Redundant Connection II](https://leetcode.com/problems/redundant-connection-ii/)
49 |
50 | ```python
51 |
52 | ```
53 |
54 | 时间复杂度:O()
55 | 空间复杂度:O()
56 |
--------------------------------------------------------------------------------
/01_leetcode/12_union_find/737. Sentence Similarity II.md:
--------------------------------------------------------------------------------
1 | # 737. Sentence Similarity II
2 |
3 | [https://leetcode.com/problems/sentence-similarity-ii/](https://leetcode.com/problems/sentence-similarity-ii/)
4 |
5 | ## solution
6 |
7 | - union find
8 |
9 | ```python
10 |
11 | ```
12 |
13 | 时间复杂度:O()
14 | 空间复杂度:O()
15 |
16 | - dfs
17 |
18 | ```python
19 |
20 | ```
21 |
22 | 时间复杂度:O()
23 | 空间复杂度:O()
24 |
--------------------------------------------------------------------------------
/01_leetcode/12_union_find/README.md:
--------------------------------------------------------------------------------
1 | # 并查集 Union find
2 |
3 | - 某些题可以用DFS/BFS,DFS/BFS可能会有找不到某些点,只能用union find
4 | - 并查集常用来解决连通性问题,当需要判断两个元素是否在同一个集合里时,想到用并查集
5 | - 用集合中的一个元素代表集合
6 |
7 | ```python
8 | class DSU:
9 | def __init__(self):
10 | self.parent = range(10001) # 用一个数组来存储每个元素的父节点,初始时每个节点parent都是自己
11 |
12 | def find(self, x): # 查询parent
13 | if x != self.parent[x]: # 注意是if
14 | self.parent[x] = self.find(self.parent[x]) # 一层一层访问父节点,直至根节点
15 | return self.parent[x] # 返回父节点
16 |
17 | def union(self, x, y): # 合并
18 | self.parent[self.find(x)] = self.find(y) # 先找到两个集合的代表元素,然后将前者的父节点设为后者
19 |
20 | def same(self, x, y):
21 | return self.find(x) == self.find(y)
22 | ```
23 |
24 | ## 优化
25 |
26 | - 路径压缩
27 | - find过程,把沿途的每个节点的父节点都设为根节点
28 | - 按秩合并
29 | - 把简单的树往复杂的树上合并; 合并后,到根节点距离变长的节点个数比较少
30 |
31 | ## 阅读
32 |
33 | - [算法学习笔记(1) : 并查集](https://zhuanlan.zhihu.com/p/93647900)
34 |
--------------------------------------------------------------------------------
/01_leetcode/13_trie/1166. Design File System.md:
--------------------------------------------------------------------------------
1 | # 1166. Design File System
2 |
3 | [https://leetcode.com/problems/design-file-system/](https://leetcode.com/problems/design-file-system/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class TrieNode:
9 | def __init__(self, value=0):
10 | self.children = {}
11 | self.value = value
12 |
13 | class FileSystem:
14 | def __init__(self):
15 | self.root = TrieNode()
16 |
17 | def createPath(self, path: str, value: int) -> bool:
18 | node = self.root
19 | subpaths = path.split('/')
20 |
21 | for i in range(1, len(subpaths) - 1):
22 | if subpaths[i] not in node.children:
23 | return False
24 | node = node.children[subpaths[i]]
25 |
26 | if subpaths[-1] in node.children:
27 | return False
28 |
29 | node.children[subpaths[-1]] = TrieNode(value)
30 | return True
31 |
32 | def get(self, path: str) -> int:
33 | node = self.root
34 | for subpath in path.split('/')[1:]:
35 | if subpath not in node.children:
36 | return -1
37 | node = node.children[subpath]
38 | return node.value
39 | ```
40 |
41 | 时间复杂度:O()
42 | 空间复杂度:O()
43 |
44 | ## follow up
45 |
46 | [588. Design In-Memory File System](../17_design/588.%20Design%20In-Memory%20File%20System.md)
47 |
--------------------------------------------------------------------------------
/01_leetcode/13_trie/642. Design Search Autocomplete System.md:
--------------------------------------------------------------------------------
1 | # 642. Design Search Autocomplete System
2 |
3 | [https://leetcode.com/problems/design-search-autocomplete-system/](https://leetcode.com/problems/design-search-autocomplete-system/)
4 |
5 | ## solution
6 |
7 | ```python
8 |
9 | ```
10 |
11 | 时间复杂度:O()
12 | 空间复杂度:O()
13 |
--------------------------------------------------------------------------------
/01_leetcode/13_trie/README.md:
--------------------------------------------------------------------------------
1 | # 字典树/前缀树 trie
2 |
3 | [基础知识](https://zh.wikipedia.org/wiki/Trie)
4 |
5 | - 一个树形结构,一种专门处理**字符串匹配**的数据结构,persistent, 用来解决在**一组字符串集合中快速查找某个字符串**的问题
6 | - 多数情况下可以通过用一个set来记录所有单词的prefix来替代,时间复杂度不变,空间复杂度略高
7 | - 确定有限状态自动机
8 | - 可以解决多个string查询prefix/suffix,如588, 1268, 745
9 | - trie+dfs结合解决字典题如 139,140
10 | - trie vs hashmap tradeoff
11 | - Trie非常适合前缀匹配操作, 在O(k)时间内找到以某个前缀开头的所有字符串,其中k是前缀的长度
12 | - 稀疏字符串集合,Trie的空间复杂度可能较高
13 | - Trie的插入和查找时间复杂度为O(k),其中k是字符串的长度。对于较长的字符串,时间复杂度可能较高。
14 | - Trie可以用于按字典序排序字符串。
15 | - Hashmap的插入和查找时间复杂度为O(1),平均情况下非常高效。
16 | - Hashmap不适合前缀匹配操作。要找到以某个前缀开头的所有字符串,需要遍历整个哈希表,时间复杂度为O(n),其中n是哈希表的大小。
17 | - Hashmap中的键是无序的,因此不适合按字典序排序字符串。
18 |
--------------------------------------------------------------------------------
/01_leetcode/14_sweep_line/1094. Car Pooling.md:
--------------------------------------------------------------------------------
1 | # 1094. Car Pooling
2 |
3 | [https://leetcode.com/problems/car-pooling/](https://leetcode.com/problems/car-pooling/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def carPooling(self, trips: List[List[int]], capacity: int) -> bool:
10 | path = [0] * (max([i[2] for i in trips]) + 1)
11 | for a, s, e in trips:
12 | path[s] += a
13 | path[e] -= a
14 | res = 0
15 | for n in path:
16 | res += n
17 | if res > capacity:
18 | return False
19 | return True
20 | ```
21 |
22 | 时间复杂度:O()
23 | 空间复杂度:O()
24 |
--------------------------------------------------------------------------------
/01_leetcode/14_sweep_line/218. The Skyline Problem.md:
--------------------------------------------------------------------------------
1 | # 218. The Skyline Problem
2 |
3 | [https://leetcode.com/problems/the-skyline-problem/](https://leetcode.com/problems/the-skyline-problem/)
4 |
5 | ## solution
6 |
7 | - 使用优先队列储存每个建筑物的高度和右端
8 |
9 | ```python
10 |
11 | ```
12 |
13 | 时间复杂度:O()
14 | 空间复杂度:O()
15 |
16 | - tree map
17 |
18 | ```python
19 |
20 | ```
21 |
22 | - 扫描线
23 |
24 | ```python
25 |
26 | ```
27 |
28 | ```python
29 | class Solution:
30 | def getSkyline(self, buildings: List[List[int]]) -> List[List[int]]:
31 | if not buildings:
32 | return []
33 |
34 | events = []
35 |
36 | for left, right, h in buildings:
37 | events.append((left, -h, right)) # start point of building
38 | events.append((right, 0, 0)) # end point of building
39 |
40 | events.sort()
41 | res = [[0, 0]]
42 | hp = [(0, float('inf'))] # 结果存的就是高度,右边界
43 |
44 | for pos, h, r in events:
45 | while hp[0][1] <= pos: # 本身已经按高度排序,如果右边比上一个小
46 | heapq.heappop(hp)
47 |
48 | if h != 0:
49 | heapq.heappush(hp, (h, r))
50 |
51 | if res[-1][1] != -hp[0][0]:
52 | res.append([pos, -hp[0][0]])
53 | return res[1:]
54 | ```
55 |
--------------------------------------------------------------------------------
/01_leetcode/14_sweep_line/README.md:
--------------------------------------------------------------------------------
1 | # 扫描线
2 |
3 | - 不需要暴力遍历每一个点,只检测起点和重点的位置
4 | - 有些题目和线段树结合
5 |
6 | [lintcode-391 · 数飞机](https://www.lintcode.com/problem/391/)
7 |
8 | ```python
9 | # 本题也可以使用前缀和
10 |
11 | class Solution:
12 | def countOfAirplanes(self, airplanes):
13 | room=[]
14 | for i in airplanes:
15 | room.append((i.start, 1))
16 | room.append((i.end, -1))
17 |
18 | tmp = 0
19 | ans = 0
20 | room = sorted(room)
21 | for idx, cost in room:
22 | tmp += cost
23 | ans = max(ans,tmp)
24 | return ans
25 | ```
26 |
27 | 时间复杂度:O(nlog(n))
28 | 空间复杂度:O(time)
29 |
30 | ## Reference
31 |
32 | - [一文读懂扫描线算法 - 小水的文章 - 知乎](https://zhuanlan.zhihu.com/p/103616664)
33 |
--------------------------------------------------------------------------------
/01_leetcode/15_tree_map/318. Count of Smaller Numbers After Self.md:
--------------------------------------------------------------------------------
1 | # 318. Count of Smaller Numbers After Self
2 |
3 | [https://leetcode.com/problems/maximum-product-of-word-lengths/](https://leetcode.com/problems/maximum-product-of-word-lengths/)
4 |
5 | ## solution
6 |
7 | - 线段树、二分索引树、TreeMap都可以
8 |
9 | ```python
10 | # bitmask
11 |
12 | class Solution:
13 | def maxProduct(self, words: List[str]) -> int:
14 | num_words = len(words)
15 | # Create a list to store the bitmask representation of each word
16 | masks = [0] * num_words
17 |
18 | # Generate a bitmask for each word where bit i is set if the
19 | # word contains the i-th letter of the alphabet: [4194311, 33554435, 16416, 131075, 8921120, 63]
20 | for i, word in enumerate(words):
21 | for ch in word:
22 | masks[i] |= 1 << (ord(ch) - ord('a'))
23 |
24 | max_product = 0
25 | for i in range(num_words - 1):
26 | for j in range(i + 1, num_words):
27 | if masks[i] & masks[j] == 0:
28 | max_product = max(max_product, len(words[i]) * len(words[j]))
29 |
30 | return max_product
31 | ```
32 |
33 | 时间复杂度:O()
34 | 空间复杂度:O()
35 |
--------------------------------------------------------------------------------
/01_leetcode/15_tree_map/480. Sliding Window Median.md:
--------------------------------------------------------------------------------
1 | # 480. Sliding Window Median
2 |
3 | [https://leetcode.com/problems/sliding-window-median/](https://leetcode.com/problems/sliding-window-median/)
4 |
5 | ## solution
6 |
7 | ```python
8 | # 类似于81题数据流的中位数,两个堆,一个大根堆维护中位数以左的,一个小根堆维护中位数以右的元素
9 |
10 | from bisect import insort, bisect_left
11 |
12 | class Solution:
13 | def medianSlidingWindow(self, nums: List[int], k: int) -> List[float]:
14 | ans = []
15 | window = sorted(nums[:k]) # 排序
16 |
17 | def get_median(window, k):
18 | return (window[(k - 1) // 2] + window[k // 2]) / 2.0
19 |
20 | ans.append(get_median(window, k))
21 |
22 | for i in range(k, len(nums)):
23 | index = bisect_left(window, nums[i - k]) # 即将移出窗口的元素,其他的仍然排序
24 | window.pop(index)
25 |
26 | insort(window, nums[i])
27 | ans.append(get_median(window, k))
28 |
29 | return ans
30 | ```
31 |
32 | 时间复杂度:O(n x k)
33 | 空间复杂度:O(n)
34 |
35 | ## follow up
36 |
37 | [295. Find Median from Data Stream](../06_heap/295.%20Find%20Median%20from%20Data%20Stream.md)
38 |
--------------------------------------------------------------------------------
/01_leetcode/15_tree_map/846. Hand of Straights.md:
--------------------------------------------------------------------------------
1 | # 846. Hand of Straights
2 |
3 | [https://leetcode.com/problems/hand-of-straights/](https://leetcode.com/problems/hand-of-straights/)
4 |
5 | ## solution
6 |
7 | ```python
8 |
9 | ```
10 |
11 | 时间复杂度:O()
12 | 空间复杂度:O()
13 |
14 | - 原写法,速度不快
15 |
16 | ```python
17 | class Solution:
18 | def isNStraightHand(self, hand: List[int], groupSize: int) -> bool:
19 | if len(hand) < groupSize or len(hand) % groupSize != 0:
20 | return False
21 |
22 | hand.sort()
23 | while hand:
24 | mini = hand[0]
25 | for _ in range(groupSize):
26 | if mini in hand:
27 | hand.remove(mini)
28 | mini += 1
29 | else:
30 | return False
31 | return True
32 | ```
33 |
--------------------------------------------------------------------------------
/01_leetcode/15_tree_map/981. Time Based Key-Value Store.md:
--------------------------------------------------------------------------------
1 | # 981. Time Based Key-Value Store
2 |
3 | [https://leetcode.com/problems/time-based-key-value-store/](https://leetcode.com/problems/time-based-key-value-store/)
4 |
5 | ## solution
6 |
7 | ```python
8 | import bisect
9 | import collections
10 |
11 | class TimeMap:
12 | def __init__(self):
13 | # 两个并列字典, 其中value顺序对应上
14 | self.value_map = collections.defaultdict(list)
15 | self.time_map = collections.defaultdict(list)
16 |
17 | def set(self, key: str, value: str, timestamp: int) -> None:
18 | self.value_map[key].append(value)
19 | self.time_map[key].append(timestamp)
20 |
21 | def get(self, key: str, timestamp: int) -> str:
22 | if key not in self.value_map:
23 | return ''
24 |
25 | key_time = self.time_map[key]
26 | # bisect 输出: 第一个比timestamp大的index
27 | index = bisect.bisect(key_time, timestamp)
28 | if index >= 1: # 注意输出
29 | return self.value_map[key][index - 1]
30 | return ''
31 | ```
32 |
33 | 时间复杂度:O(log(n))
34 | 空间复杂度:O(key+value+timestamp)
35 |
--------------------------------------------------------------------------------
/01_leetcode/15_tree_map/README.md:
--------------------------------------------------------------------------------
1 | # tree map
2 |
3 | - In python, you may use [sortedcontainers](https://grantjenks.com/docs/sortedcontainers/) library.
4 |
5 | ```python
6 | from sortedcontainers import SortedList
7 | ```
8 |
9 | - JAVA can use TreeSet or TreeMap.
10 |
--------------------------------------------------------------------------------
/01_leetcode/16_math/1227. Airplane Seat Assignment Probability.md:
--------------------------------------------------------------------------------
1 | # 1227. Airplane Seat Assignment Probability
2 |
3 | [https://leetcode.com/problems/airplane-seat-assignment-probability/description/](https://leetcode.com/problems/airplane-seat-assignment-probability/description/)
4 |
5 | ## follow up
6 |
7 | ```python
8 |
9 | ```
10 |
11 | 时间复杂度:O()
12 | 空间复杂度:O()
13 |
--------------------------------------------------------------------------------
/01_leetcode/16_math/204. Count Primes.md:
--------------------------------------------------------------------------------
1 | # 204. Count Primes
2 |
3 | [https://leetcode.com/problems/count-primes/description/](https://leetcode.com/problems/count-primes/description/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class Solution:
9 | def countPrimes(self, n: int) -> int:
10 | if n < 2:
11 | return 0
12 | primes = [True] * n
13 | ans = 0
14 | for i in range(2, n):
15 | if primes[i]:
16 | ans += 1
17 | for j in range(i * i, n, i):
18 | primes[j] = False
19 | return ans
20 | ```
21 |
22 | 时间复杂度:O()
23 | 空间复杂度:O()
24 |
--------------------------------------------------------------------------------
/01_leetcode/16_math/382. Linked List Random Node.md:
--------------------------------------------------------------------------------
1 | # 382. Linked List Random Node
2 |
3 | [https://leetcode.com/problems/linked-list-random-node/description/](https://leetcode.com/problems/linked-list-random-node/description/)
4 |
5 | ## solution
6 |
7 | ```python
8 | # 直接思路:将链表转化为数组,然后通过数组下标实现O(1)的随机取
9 | # Reservoir Sampling思路: 当链表长度未知且只能用常数空间,采用蓄水池算法. (很适合链表无法一次性取到全部, 类似stream)
10 |
11 | class Solution(object):
12 | def __init__(self, head):
13 | self.head = head
14 |
15 | def getRandom(self):
16 | count = 0
17 | res = None
18 |
19 | cur = self.head
20 | while cur:
21 | if random.randint(0, count) == 0:
22 | res = cur.val
23 | count += 1
24 | cur = cur.next
25 |
26 | return res
27 | ```
28 |
29 | 时间复杂度:O(n)
30 | 空间复杂度:O(1)
31 |
32 | ## follow up
33 |
34 | [随机类小结](./398.%20Random%20Pick%20Index.md)
35 |
--------------------------------------------------------------------------------
/01_leetcode/16_math/50. Pow(x, n).md:
--------------------------------------------------------------------------------
1 | # 50. Pow(x, n)
2 |
3 | [https://leetcode.com/problems/powx-n/description/](https://leetcode.com/problems/powx-n/description/)
4 |
5 | ## solution
6 |
7 | - 快速幂: recursive
8 | - n为奇数,x^n = x(x^2)^(n//2)
9 | - n为偶数,x^n = (x^2)^(n//2)
10 |
11 | ```python
12 | class Solution:
13 | def myPow(self, x: float, n: int) -> float:
14 | if n == 0: # 退出递归的关键返回
15 | return 1
16 | if n < 0:
17 | return 1 / self.myPow(x, -n)
18 | if n % 2 == 1:
19 | return x * self.myPow(x, n - 1)
20 | return self.myPow(x * x, n // 2) # 注意是 (x ** 2 ^ n//2) 而不是 (x ^ n//2 ^ 2)
21 | ```
22 |
23 | 时间复杂度:O(log(n))
24 | 空间复杂度:O(1)
25 |
26 | - 非递归: iterative
27 |
28 | ```python
29 | # https://algo.monster/liteproblems/50
30 |
31 | ```
32 |
33 | ## follow up
34 |
35 | [372. Super Pow](https://leetcode.com/problems/super-pow/description/)
36 |
37 | ```python
38 | class Solution:
39 | def superPow(self, a: int, b: List[int]) -> int:
40 | mode = 1337
41 | ans = 1
42 |
43 | for i in b:
44 | ans = pow(ans, 10, mode) * pow(a, i, mode)
45 | return ans % mode
46 | ```
47 |
48 | 时间复杂度:O(n)
49 | 空间复杂度:O(1)
50 |
--------------------------------------------------------------------------------
/01_leetcode/17_design/1116. Print Zero Even Odd.md:
--------------------------------------------------------------------------------
1 | # 1116. Print Zero Even Odd
2 |
3 | [https://leetcode.com/problems/print-zero-even-odd/description/](https://leetcode.com/problems/print-zero-even-odd/description/)
4 |
5 | ## solution
6 |
7 | ```python
8 | # 对比互斥锁,互斥锁多线程的情况下,只能争抢同一把锁
9 | from threading import Semaphore
10 |
11 | class ZeroEvenOdd:
12 | def __init__(self, n: int):
13 | self.n = n
14 | self.zero_semaphore = Semaphore(1)
15 | self.even_semaphore = Semaphore(0)
16 | self.odd_semaphore = Semaphore(0)
17 |
18 | def zero(self, print_number: Callable[[int], None]) -> None:
19 | for i in range(self.n):
20 | self.zero_semaphore.acquire()
21 | print_number(0)
22 |
23 | if i % 2 == 0:
24 | self.odd_semaphore.release()
25 | else:
26 | self.even_semaphore.release()
27 |
28 | def even(self, print_number: Callable[[int], None]) -> None:
29 | for i in range(2, self.n + 1, 2):
30 | self.even_semaphore.acquire()
31 | print_number(i)
32 | self.zero_semaphore.release()
33 |
34 | def odd(self, print_number: Callable[[int], None]) -> None:
35 | for i in range(1, self.n + 1, 2):
36 | self.odd_semaphore.acquire()
37 | print_number(i)
38 | self.zero_semaphore.release()
39 | ```
40 |
41 | 时间复杂度:O()
42 | 空间复杂度:O()
43 |
--------------------------------------------------------------------------------
/01_leetcode/17_design/1244. Design A Leaderboard.md:
--------------------------------------------------------------------------------
1 | # 1244. Design A Leaderboard
2 |
3 | [https://leetcode.com/problems/design-a-leaderboard/description/](https://leetcode.com/problems/design-a-leaderboard/description/)
4 |
5 | ## solution
6 |
7 | ```python
8 | from heapq import heappop, heappush, heapify
9 |
10 | class Leaderboard:
11 | def __init__(self):
12 | self.d = {}
13 | self.q = []
14 |
15 | def add_score(self, pid: int, score: int):
16 | if pid not in self.d:
17 | self.d[pid] = 0
18 | self.d[pid] -= score
19 | heappush(self.q, [self.d[pid], pid])
20 |
21 | def top(self, k: int) -> int:
22 | tem_d, tem_q, ans = {}, [], 0
23 | for _ in range(k):
24 | while(self.q and (self.q[0][1] not in self.d or self.d[self.q[0][1]] != self.q[0][0])):
25 | heappop(self.q)
26 | if self.q:
27 | s, i = heappop(self.q)
28 | self.d.pop(i)
29 | ans -= s
30 | tem_q.append([s, i])
31 | tem_d[i] = s
32 | self.q += tem_q
33 | self.d |= tem_d
34 | heapify(self.q)
35 | return ans
36 |
37 | def reset(self, pid: int):
38 | self.d[pid] = 0
39 | heappush(self.q, [self.d[pid], pid])
40 | ```
41 |
42 | 时间复杂度:O()
43 | 空间复杂度:O()
44 |
--------------------------------------------------------------------------------
/01_leetcode/17_design/1396. Design Underground System.md:
--------------------------------------------------------------------------------
1 | # 1396. Design Underground System
2 |
3 | [https://leetcode.com/problems/design-underground-system/description/](https://leetcode.com/problems/design-underground-system/description/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class UndergroundSystem:
9 | def __init__(self):
10 | self.station_id_dict = {}
11 | # 两个int 字典,一个记录总时长,一个记录总个数,可以进一步优化空间
12 | self.station_duration_dict = collections.defaultdict(list)
13 |
14 | def checkIn(self, id: int, stationName: str, t: int) -> None:
15 | self.station_id_dict[id] = (stationName, t)
16 |
17 | def checkOut(self, id: int, stationName: str, t: int) -> None:
18 | in_station, in_t = self.station_id_dict.pop(id)
19 | self.station_duration_dict[(in_station, stationName)].append(t - in_t)
20 |
21 | def getAverageTime(self, startStation: str, endStation: str) -> float:
22 | time_list = self.station_duration_dict[(startStation, endStation)]
23 | return sum(time_list) / len(time_list)
24 | ```
25 |
26 | 时间复杂度:O(1)
27 | 空间复杂度:O()
28 |
--------------------------------------------------------------------------------
/01_leetcode/17_design/1603. Design Parking System.md:
--------------------------------------------------------------------------------
1 | # 1603. Design Parking System
2 |
3 | [https://leetcode.com/problems/design-parking-system/description/](https://leetcode.com/problems/design-parking-system/description/)
4 |
5 | ## solution
6 |
7 | ```python
8 | class ParkingSystem:
9 | def __init__(self, big: int, medium: int, small: int):
10 | self.count = [big, medium, small]
11 |
12 | def addCar(self, carType: int) -> bool:
13 | self.count[carType - 1] -= 1
14 | return self.count[carType - 1] >= 0
15 | ```
16 |
17 | 时间复杂度:O(1)
18 | 空间复杂度:O(1)
19 |
--------------------------------------------------------------------------------
/01_leetcode/17_design/359. Logger Rate Limiter.md:
--------------------------------------------------------------------------------
1 | # 359. Logger Rate Limiter
2 |
3 | [https://leetcode.com/problems/logger-rate-limiter/description/](https://leetcode.com/problems/logger-rate-limiter/description/)
4 |
5 | ## solution
6 |
7 | ```python
8 | # hashmap 做一个类似 inverted index 功能
9 |
10 | class Logger:
11 | def __init__(self):
12 | self.messageQueue = collections.deque()
13 | self.messageSet = set()
14 |
15 | def shouldPrintMessage(self, timestamp: int, message: str) -> bool:
16 | while self.messageQueue:
17 | headTimestamp, headMessage = self.messageQueue[0]
18 | if timestamp < headTimestamp + 10:
19 | break
20 | # 大于10秒的去掉
21 | self.messageQueue.popleft()
22 | self.messageSet.remove(headMessage)
23 |
24 | if message in self.messageSet:
25 | return False
26 | self.messageQueue.append((timestamp, message))
27 | self.messageSet.add(message)
28 | return True
29 | ```
30 |
31 | 时间复杂度:O(n)
32 | 空间复杂度:O(n)
33 |
34 | ## follow up
35 |
36 | 给定一个公共API,限制每个用户每秒只能调用1000次,如何实现?
37 |
38 | - counter
39 | - Token Bucket
40 | - Leak Bucket
41 | - https://zhuanlan.zhihu.com/p/20872901
42 |
--------------------------------------------------------------------------------
/01_leetcode/17_design/379. Design Phone Directory.md:
--------------------------------------------------------------------------------
1 | # 379. Design Phone Directory
2 |
3 | [https://leetcode.com/problems/design-phone-directory/](https://leetcode.com/problems/design-phone-directory/)
4 |
5 | ## solution
6 |
7 | ```python
8 | from heapq import heappop, heappush
9 |
10 | class PhoneDirectory:
11 | def __init__(self, maxNumbers: int):
12 | self.used = set() # 记录已被使用的编号
13 | self.heap = [] # 按照号码的值由小到大进行分配
14 | self.next = 0
15 | self.k = maxNumbers # 电话目录的最大编号
16 |
17 | def get(self) -> int:
18 | ans = -1
19 | if len(self.used) == self.k:
20 | return ans
21 | if self.heap:
22 | ans = heappop(self.heap)
23 | else:
24 | ans, self.next = self.next, self.next+1
25 | self.used.add(ans)
26 | return ans
27 |
28 | def check(self, n: int) -> bool:
29 | return n < self.k and n not in self.used
30 |
31 | def release(self, n: int):
32 | if n in self.used:
33 | self.used.remove(n)
34 | heappush(self.heap, n)
35 | ```
36 |
37 | 时间复杂度:O()
38 | 空间复杂度:O()
39 |
--------------------------------------------------------------------------------
/01_leetcode/17_design/README.md:
--------------------------------------------------------------------------------
1 | # 设计类
2 |
3 | 结合 [OOD-面向对象设计](../../03_system/01_ood/README.md)
4 |
--------------------------------------------------------------------------------
/02_ml/08_unsuperwised.md:
--------------------------------------------------------------------------------
1 | # 无监督学习
2 |
3 | ## 1. 统计学习
4 |
5 | **Clustering**
6 |
7 | - Centroid models: [k-means clustering](./09_k_means.md)
8 | - Connectivity models: Hierarchical clustering
9 | - Density models: DBSCAN
10 |
11 | **Gaussian Mixture Models**
12 |
13 | - EM是解KMS算法的方法,EM还可以解其他问题例如GMM
14 |
15 | **Latent semantic analysis**
16 |
17 | **Hidden Markov Models (HMMs)**
18 |
19 | - Markov processes
20 | - Transition probability and emission probability
21 | - Viterbi algorithm
22 |
23 | **Dimension reduction techniques**
24 |
25 | - Principal Component Analysis (PCA)
26 | - Independent Component Analysis (ICA)
27 | - T-SNE
28 |
29 | ## 2. 深度学习自监督
30 |
31 | contrastive learning 对比学习
32 |
33 | > 相似的实例在投影空间中比较接近,不相似的实例在投影空间中距离比较远
34 |
35 | ## 3. 半监督
36 |
37 | ## 4. 应用场景
38 |
39 | 实际应用中,无监督往往更注重强特征提取
40 |
41 | 见[异常检测专题](./16_anomaly.md)
42 |
43 | ## reference
44 |
45 | - [clustering](https://developers.google.com/machine-learning/clustering/clustering-algorithms)
46 |
--------------------------------------------------------------------------------
/02_ml/14_multimodal.md:
--------------------------------------------------------------------------------
1 | # 多模态
2 |
3 | 多模态任务主要有Align和Fuse两种方式,或称为Light fusion和Heavy fusion。把不同模态的特征映射到相同的向量空间的操作叫align。代表作是OpenAI的CLIP,Google的Align。用一个模型把不同模态的特征混在一起用来完成某项任务,叫做Fuse。代表作有微软的UNITER,OSCAR等。
4 |
5 | - Align 双塔
6 | - 向量内积,CLIP和ALIGN
7 | - Fusion 单塔
8 | - transformer, VLP, OSCAR, UNITER, VINFL
9 |
10 | 单流模型和双流模型
11 |
12 | - 单流模型将图像侧和文本侧的embedding拼接到一起,输入到一个Transformer模型中。
13 | - 双流模型让图像侧和文本侧使用两个独立的Transformer分别编码,可以在中间层加入两个模态之间的Attention来融合多模态信息
14 |
15 | 多模态对齐方法
16 |
17 | - 借鉴BERT的思想进行masked language modeling对齐
18 | - 使用contrastive loss进行多模态对齐
19 |
20 | ## 模型
21 |
22 | **VILBERT**
23 |
24 | **[CLIP](https://github.com/openai/CLIP)**
25 |
26 | **DALL-E**
27 |
28 | ALBEF
29 |
30 | BLIP
31 |
32 | - Q-Former的作用是什么
33 |
34 | Diffusion
35 |
36 | ### vLLM (vision LLM)
37 |
38 | - LLAVA
39 |
40 | ## 语音
41 |
42 | - CTC
43 |
44 | ## 参考
45 |
46 | - [大模型 | CLIP | BLIP | 损失函数代码实现 - 有点晕的文章 - 知乎](https://zhuanlan.zhihu.com/p/699507603)
47 | - [Meta Chameleon](https://github.com/facebookresearch/chameleon)
48 | - [Mono-InternVL](https://arxiv.org/abs/2410.08202)
49 | - [张祥雨访谈 多模态大模型研究的挣扎史和未来 - hzwer 黄哲威的文章 - 知乎](https://zhuanlan.zhihu.com/p/1913614732318995171)
50 |
--------------------------------------------------------------------------------
/02_ml/19_multi_task.md:
--------------------------------------------------------------------------------
1 | # 多任务学习
2 |
3 | > ML design的排序部分经常需要考虑到多任务学习,有多个loss的其实就算多任务学习
4 | >
5 | > - 优化策略: loss量级Magnitude,loss学习速率,loss梯度冲突
6 |
7 | ## 模型
8 |
9 | **shared bottom**
10 |
11 | - pro: 对于稀疏标签,互相补充学习,任务相关性越高,模型的loss可以降低到更低
12 | - con: 任务之前没有好的相关性时,这种Hard parameter sharing会损害效果
13 |
14 | **MOE**
15 |
16 | - Soft parameter sharing
17 | - con: MMOE中所有的Expert是被所有任务所共享的,这可能无法捕捉到任务之间更复杂的关系,从而给部分任务带来一定的噪声; 不同的Expert之间没有交互,联合优化的效果有所折扣
18 |
19 | **MMOE**
20 |
21 | - k个任务则适用k个门控网络
22 |
23 | **ESMM**
24 |
25 | **PLE**
26 |
27 | ## 平衡多个任务
28 |
29 | **GradNorm**
30 |
31 | **DWA (Dynamic Weight Average)**
32 |
33 | ## Reference
34 |
35 | - [收藏|浅谈多任务学习(Multi-task Learning) - 多多笔记的文章 - 知乎](https://zhuanlan.zhihu.com/p/348873723)
36 | - [多任务学习优化(Optimization in Multi-task learning) - 凉爽的安迪的文章 - 知乎](https://zhuanlan.zhihu.com/p/269492239)
37 | - [深度学习的多个loss如何平衡? - 王晋东不在家的回答 - 知乎](https://www.zhihu.com/question/375794498/answer/2307552166)
38 | - [多目标学习在推荐系统的应用(MMOE/ESMM/PLE) - 绝密伏击的文章 - 知乎](https://zhuanlan.zhihu.com/p/291406172)
39 | - [「算法面试开挂专题」MTL多目标训练20问 - 琦琦的文章 - 知乎](https://zhuanlan.zhihu.com/p/701647428)
40 | - [多场景多任务学习在美团到店餐饮推荐的实践](https://tech.meituan.com/2023/03/23/recommendation-multi-scenario-task.html)
41 |
--------------------------------------------------------------------------------
/02_ml/22_online_learning.md:
--------------------------------------------------------------------------------
1 | # Online learning
2 |
3 | ## 案例
4 |
5 | 行为数据logging -> 消息队列 -> 特征pipeline -> 消息队列 -> 训练服务器
6 |
7 | ## 问答
8 |
9 | - 推荐系统在线学习时如何应对延迟反馈(delayed feedback)问题?
10 | - 历史数据进行标签修正
11 | - 建立一个延迟模型,预测每个样本的反馈到达时间分布。基于预测的延迟时间,可以对实时数据进行推断和修正。
12 | - 使用生存分析方法预测某一行为(如点击或购买)是否会发生以及何时发生。对于未发生反馈的样本,可以用生存概率进行估计,避免简单地将其视为负样本。
13 |
14 | ## Reference
15 |
16 | - [蘑菇街首页推荐视频流——增量学习与wide&deepFM实践(工程+算法) - 琦琦的文章 - 知乎](https://zhuanlan.zhihu.com/p/212647751)
17 | - [支持在线模型更新的大型推荐系统](https://openmlsys.github.io/chapter_recommender_system/case_study.html)
18 | - https://github.com/online-ml/river
19 |
--------------------------------------------------------------------------------
/02_ml/23_hardware.md:
--------------------------------------------------------------------------------
1 | # Hardware + cuda/triton
2 |
3 | > 熟悉 C++, GPU kernels, CUDA, Triton, CUTLASS
4 |
5 | ## 1. Cuda
6 |
7 | ## 2. Triton
8 |
9 | ## Reference
10 |
11 | - [一文了解GPU并行计算CUDA](https://zhuanlan.zhihu.com/p/604571345)
12 | - [Triton tutorial](https://triton-lang.org/main/getting-started/tutorials/index.html)
13 | - [https://github.com/cuda-mode/lectures](https://github.com/cuda-mode/lectures)
14 | - [CUDA-MODE 课程笔记 第一课: 如何在 PyTorch 中 profile CUDA kernels - BBuf的文章 - 知乎](https://zhuanlan.zhihu.com/p/706469164)
15 | - [https://github.com/xlite-dev/LeetCUDA](https://github.com/xlite-dev/LeetCUDA)
16 | - [CUDA算子手撕与面试 - 吱吱呼呼的文章 - 知乎](https://zhuanlan.zhihu.com/p/12661298743)
17 |
--------------------------------------------------------------------------------
/02_ml/98_project.md:
--------------------------------------------------------------------------------
1 | # 机器学习项目介绍
2 |
3 | > - 项目复杂体现在:impact大,难度大,合作的组多
4 | > - 讲自己做了什么,讲自己为什么这么做体现**认知**
5 |
6 | 按以下格式,准备自己简历上的每一个项目。介绍项目的思路和系统设计一样,highlight为什么这么做,追加result和impact;简历上的每一句话都可能被深挖下去
7 |
8 | - 商业目标是什么
9 | - 机器学习目标是什么,转化为一个怎样的机器学习任务,主要解决什么问题
10 | - 系统架构到技术细节,scalability
11 | - 评价指标
12 | - 样本构建,数据怎么获取,多大,什么字段,怎么存储,怎么清洗
13 | - 特征
14 | - 模型,为什么使用这个模型(技术选型),与其他解决该类问题的差异
15 | - 部署、更新
16 | - 遇到了什么问题?哪部分是难点,怎么解决
17 | - 如果改变某一条件,应该如何应对
18 | - 如果现在让你做这个项目,会有哪些优化/是否有哪些不足之处
19 |
20 | ## 问答
21 |
22 | - star原则:situation, task, action, results
23 | - 难点和深度
24 | - 项目中的细节
25 | - 机器学习项目:the data, labelling, modeling, evaluation metrics
26 | - 是否有不足之处,怎么改善/或现在让你重新来做,会如何改善
27 | - 技术细节、流程、遇到的困难怎么解决、impact、再来一次如何改善
28 | - 如果对项目抽象成解决的问题,然后改变条件,我们应该如何应对
29 | - 如何体现技术深度?
30 | - 深度其实体现在细节,有共鸣的细节或没有预期但逻辑自洽的细节
31 |
--------------------------------------------------------------------------------
/03_system/01_ood/README.md:
--------------------------------------------------------------------------------
1 | # 面向对象设计OOD
2 |
3 | > 考核关键是如何设计class,class的properties和methods定义好,掌握class的继承
4 |
5 | ## 1. 面试过程
6 |
7 | - clarification: 先理清`业务流程`
8 | - 根据流程图,找到`core object`,明确`use case`
9 | - 完善整体设计`class diagram`,写出`class`和`重点method`
10 |
11 | ## 2. 案例
12 |
13 | - [停车场](./parking_lot.md)
14 | - [电梯](./lift.md)
15 | - [design Linux file search utility](./unix_file.md)
16 | - drink sale system
17 | - amazon locker
18 | - 酒店预订
19 | - vending machine
20 | - 中国象棋
21 | - 操作系统内存管理分页分段的API
22 |
23 | ## 3. 参考
24 |
25 | - Grokking the Object Oriented Design Interview
26 | - https://github.com/ycwkatie/OOD-Object-Oriented-Design
27 | - https://github.com/rajat19/system-design
28 | - http://www.cs.sjsu.edu/~pearce/modules/lectures/ooa2/ood/index.htm
29 | - https://medium.com/javarevisited/top-10-object-oriented-analysis-and-design-interview-questions-and-problems-for-experienced-6c3a53b7cb26
30 | - https://github.com/nikhilagrwl07/System-Design/tree/master/src/main/java
31 | - https://github.com/ycwkatie/OOD-Object-Oriented-Design
32 | - https://rajat19.github.io/system-design/category/system-designs.html
33 | - https://leetcode.com/playground/ay5RFRWQ
34 | - [python手写一个event loop - Kittyhawk的文章 - 知乎](https://zhuanlan.zhihu.com/p/111656060)
35 | - [高并发,用Python适合吗? - 骑蜗牛上月球的回答 - 知乎](https://www.zhihu.com/question/383946811/answer/3297627184)
36 | - [await,async 我要把它翻个底朝天,这回你总该明白了吧 - 一线码农的文章 - 知乎](https://zhuanlan.zhihu.com/p/197335532)
37 |
--------------------------------------------------------------------------------
/03_system/01_ood/unix_file.md:
--------------------------------------------------------------------------------
1 | # Unix文件系统
2 |
3 | ## Reference
4 |
5 | - [Design Unix File Search API](https://leetcode.com/discuss/interview-question/609070/amazon-ood-design-unix-file-search-api)
6 |
--------------------------------------------------------------------------------
/03_system/02_system/ad_click_aggregator.md:
--------------------------------------------------------------------------------
1 | # Ad Click Aggregator
2 |
3 | > 本质上就是一个计数器,design围绕其展开
4 |
5 | ## Reference
6 |
7 | - [Building a reliable and scalable metrics aggregation and monitoring system by Vishnu Gajendran](https://www.youtube.com/watch?v=UEJ6xq4frEw)
8 | -
9 |
--------------------------------------------------------------------------------
/03_system/02_system/chat_system.md:
--------------------------------------------------------------------------------
1 | # 聊天系统
2 |
3 | ## Reference
4 |
5 | - [现代IM系统中的消息系统架构 - 架构篇](https://developer.aliyun.com/article/698301?spm=a2c6h.13262185.profile.9.4ee36b1bVFt5Ee)
6 | - [从无到有:微信后台系统的演进之路](https://www.infoq.cn/article/the-road-of-the-growth-weixin-background/)
7 | - [如何设计微信的聊天系统? - 土汪的文章 - 知乎](https://zhuanlan.zhihu.com/p/34369396)
8 | - [Ace the System Interview— Design a Chat Application](https://towardsdatascience.com/ace-the-system-interview-design-a-chat-application-3f34fd5b85d0)
9 |
--------------------------------------------------------------------------------
/03_system/02_system/crawler.md:
--------------------------------------------------------------------------------
1 | # 爬虫
2 |
3 | A web crawler that will crawl Wikipedia
4 |
5 | - We need to deploy the same software on each node. We have 10,000 nodes, the software can know about all the nodes. We have to minimize communication and make sure each node does equal amount of work.
6 | - 有一些constraint,需要跟面试官交流。给你一千个bot做web crawler,不重复crawl,bot之间不talk
7 |
8 | ## 代码版
9 |
10 | - you are given 3 APIs: fetch (given a url, downloads its content), parse (given the downloaded content, get all urls inside the content), save (dump the content to disk)
11 |
12 | 单线程
13 |
14 | ```python
15 |
16 | ```
17 |
18 | 多线程
19 |
20 | ```python
21 |
22 | ```
23 |
24 | ## requirements
25 |
26 | ## Reference
27 |
28 | - https://leetcode.com/discuss/interview-question/system-design/124657/Face
29 |
--------------------------------------------------------------------------------
/03_system/02_system/database.md:
--------------------------------------------------------------------------------
1 | # 数据库设计
2 |
3 | [SQL](../../01_leetcode/99_SQL)
4 |
5 | ## 参考
6 |
7 | - [Cassandra - A Decentralized Structured Storage System](https://www.cs.cornell.edu/projects/ladis2009/papers/lakshman-ladis2009.pdf)
8 | - [Spanner: Google’s Globally-Distributed Database](https://static.googleusercontent.com/media/research.google.com/en//archive/spanner-osdi2012.pdf)
9 | - [The Google File System](https://static.googleusercontent.com/media/research.google.com/en//archive/gfs-sosp2003.pdf)
10 | -
11 |
--------------------------------------------------------------------------------
/03_system/02_system/distributed_cache.md:
--------------------------------------------------------------------------------
1 | # 分布式缓存
2 |
3 | > 缓存服务器常见的有Memcached和Redis,Redis更轻量级,适用小数据,比如Json/String。Memcached更适用大文件,比如短视频
4 |
5 | ## Reference
6 |
7 | - [https://www.infoq.com/articles/netflix-global-cache/](https://www.infoq.com/articles/netflix-global-cache/)
8 | - [https://www.1point3acres.com/bbs/thread-1097035-1-1.html](https://www.1point3acres.com/bbs/thread-1097035-1-1.html)
9 | - [Distributed Counter System Design](https://systemdesign.one/distributed-counter-system-design/)
10 | - [【造轮子】用C++造一个基于LSM的列存KV存储引擎 - 跑路的文章 - 知乎](https://zhuanlan.zhihu.com/p/603555528)
11 | - https://static.googleusercontent.com/media/research.google.com/en//archive/bigtable-osdi06.pdf
12 |
--------------------------------------------------------------------------------
/03_system/02_system/eta.md:
--------------------------------------------------------------------------------
1 | # ETA
2 |
3 | - They represent the physical map as a graph
4 |
5 | - They compute ETA by finding the shortest path in the directed weighted graph
6 |
7 | - They don't use Dijkstra’s algorithm because it wouldn't scale with O(n logn) time complexity
8 |
9 | - They partition the graph and then precompute the best path within each partition
10 |
11 | - Partitioning graph reduces the time complexity from O(n^2) to O(n)
12 |
13 | - They populate the edge weights of the graph with traffic information
14 |
15 | - They do map matching to find accurate ETA
16 |
17 | - They use the Kalman filter and Viterbi algorithm for map matching
18 |
19 | ## reference
20 |
21 | - [https://newsletter.systemdesign.one/p/uber-eta](https://newsletter.systemdesign.one/p/uber-eta)
22 |
--------------------------------------------------------------------------------
/03_system/02_system/log_system.md:
--------------------------------------------------------------------------------
1 | # Log System
2 |
3 | > a distributed data store for logs
4 |
5 | ## 1. requirements
6 |
7 | - 要求能够将PII信息隐藏,能够做top k exceptions,能够做快速查询,比如按各种不同的fi
8 | - Our goal is to build a real-time aggregation system. WebServer logs event to our system using the following function call: log(ad_id, user_id, event_type).
9 | At this moment we plan to have only 2 types of events: "ad was shown" and "ad was clicked on".
10 |
11 | ## 参考
12 |
13 | - https://engineering.fb.com/2017/08/31/core-data/logdevice-a-distributed-data-store-for-logs/
14 |
--------------------------------------------------------------------------------
/03_system/02_system/rate_limiter.md:
--------------------------------------------------------------------------------
1 | # 限流器
2 |
3 | ## reference
4 |
5 | - [Implement Rate Limiting in Python](https://levelup.gitconnected.com/implement-rate-limiting-in-python-d4f86b09259f)
6 | - [System Design Interview - Rate Limiting (local and distributed)](https://www.youtube.com/watch?v=FU4WlwfS3G0)
7 | - [rate limiter](https://leetcode.com/discuss/interview-question/system-design/124558/Uber-or-Rate-Limiter)
8 |
--------------------------------------------------------------------------------
/03_system/02_system/tinyurl.md:
--------------------------------------------------------------------------------
1 | # 短url
2 |
3 | ## Reference
4 |
5 | - [系统设计之路:如何设计一个URL短链服务](https://mp.weixin.qq.com/s/HaOhvgtgbCJyNXp-DtgedQ)
6 |
--------------------------------------------------------------------------------
/03_system/02_system/top_k.md:
--------------------------------------------------------------------------------
1 | # Top-K
2 |
3 | QPS会很大,但是总数N不会很多,内存可以轻松存下来
4 |
5 | 考点就是real time rough estimate vs offline accurate result
6 |
7 | 计算精确值的时候可以用HDFS或者Cassandra存每小时或者每天的数据,一个定时的map reduce job来根据需求计算这段时间内的top k(可以细化到秒)。长期的metadata可以直接删除也可以migrate到成本更低的S3里面。统计的top k result根据需求可以丢不同的数据库里。这里常问的点就是ingest这么多数据的时候如何来避免写过热。
8 | Real time具体看QPS的大小,标准解法就是每个service直接把需要统计的项丢一个Kafka topic里面用Kafka来decouple ingest, 然后real time Kafka + Flink来统计每秒top k。但是要是QPS太大比如1M左右,其实real time也可以用batch来做in memory batch update的,每个server用in memory的hashmap来存key和counts,每200ms 提交一次in memory的这个result到 Redis里面然后另外每秒对Redis做real time Top K计算。我一般都会把这两种解法抛出来然后讨论下trade off。如果有需求做real time + historical top K 的话 real time计算出来的结果不能删除得和之前的甚至long term的结果结合起来做一个联合的top K。
9 |
10 | ## Reference
11 |
12 | - https://www.1point3acres.com/bbs/thread-953468-1-1.html
13 | - https://github.com/apssouza22/big-data-pipeline-lambda-arch
14 | - https://serhatgiydiren.com/system-design-interview-top-k-problem-heavy-hitters/
15 | -
16 |
--------------------------------------------------------------------------------
/03_system/02_system/twitter.md:
--------------------------------------------------------------------------------
1 | # 设计twitter
2 |
3 | tweets/followers system
4 |
5 | ## news feed
6 |
7 | - celebrity
8 |
9 | ## Reference
10 |
11 | - [Design a News Feed System](https://liuzhenglaichn.gitbook.io/system-design/news-feed/design-a-news-feed-system)
12 | - [Facebook News Feed](https://www.hellointerview.com/learn/system-design/answer-keys/fb-news-feed)
13 | - [Scaling Instagram Infrastructure](https://www.youtube.com/watch?v=hnpzNAPiC0E)
14 | - [Scaling Pinterest](https://www.infoq.com/presentations/pinterest/)
15 |
--------------------------------------------------------------------------------
/03_system/02_system/webhood.md:
--------------------------------------------------------------------------------
1 | # Webhook
2 |
3 | ## Reference
4 |
5 | - [Webhook 服务的设计与实现](https://blog.whichxjy.com/webhook-service-design/)
6 | - [How to Design Webhook](https://pyemma.github.io/How-to-Design-Webhook/)
7 |
--------------------------------------------------------------------------------
/03_system/02_system/youtube.md:
--------------------------------------------------------------------------------
1 | # 设计Youtube
2 |
3 | ## 视频存储
4 |
5 | - 海量用户 海量视频
6 | - 视频文件:distributed file system
7 | - 热门视频: CDN缓存
8 | - 分片上传:拆分成小视频
9 | - 上传结束后:不同分辨率保存不同版本
10 | - 视频meta data: relational database
11 |
12 | - 读:热门视频redis缓存,冷门去hive读出来再缓存
13 | - 写:先写缓存,异步写入hive,同时上传
14 |
15 | ## Reference
16 |
17 | - [Scaling Facebook Live Videos to a Billion Users](https://www.youtube.com/watch?v=IO4teCbHvZw)
18 |
--------------------------------------------------------------------------------
/03_system/03_ml/coupon_deliver.md:
--------------------------------------------------------------------------------
1 | # 优惠券发放
2 |
3 | 优惠券可以在特定场景下刺激消费者冲动消费,从而实现利润最大化
4 |
5 | ## 1. requirements
6 |
7 | Primary Goal: Maximize overall profit by:
8 |
9 | - Increasing purchase frequency.
10 | - Boosting average order value (AOV).
11 | - Encouraging purchases of high-margin items.
12 |
13 | Secondary Goals:
14 |
15 | - Improve customer retention and loyalty.
16 | - Minimize wasted distribution of coupons (cost efficiency).
17 | - Balance supply and demand (e.g., avoid overloading inventory).
18 |
19 | **Constraints**
20 |
21 | - Budget Limit: Total cost of distributed coupons must not exceed a predefined budget.
22 | - Customer Segmentation: Different coupons for different user groups (e.g., high-value vs. low-value users).
23 | - Redemption Rate: Target a specific redemption rate to ensure coupon effectiveness.
24 | - Coupon Fatigue: Avoid over-distributing coupons to prevent diminishing returns or customer dissatisfaction.
25 | - Scalability: Handle millions of users and products.
26 |
27 | ## 2. task & pipeline
28 |
29 | > 机器学习+运筹: hybrid approach combining machine learning for prediction and operations research for optimization
30 |
31 | key challenge:
32 |
33 | - Imbalanced Data
34 | - Cold Start
35 | - Scalability
36 |
37 |
38 | ## 3. data
39 |
40 |
41 | ## reference
42 |
43 | - [大厂的优惠券系统是如何设计的? - JavaEdge的文章 - 知乎](https://zhuanlan.zhihu.com/p/511822092)
44 | - [如何设计优惠券系统?一文带你看懂优惠券 - 薛老板的文章 - 知乎](https://zhuanlan.zhihu.com/p/351658623)
45 |
--------------------------------------------------------------------------------
/03_system/03_ml/fraud_detection.md:
--------------------------------------------------------------------------------
1 | # 异常检测
2 |
3 |
4 | ## Reference
5 | - [Fraud Detection - ML System Design Interview](https://www.youtube.com/watch?v=90eszaYPskk&t=30s)
6 | -
--------------------------------------------------------------------------------
/03_system/03_ml/search_box.md:
--------------------------------------------------------------------------------
1 | # 搜索框
2 |
3 | ## 1. requirements
4 |
5 | > text generation 任务
6 |
7 | ## 2. ML task & pipeline
8 |
9 | ## Reference
10 |
11 | - [别再用前缀树了!深度揭秘搜索框“自动补全”功能 - 张泰源的文章 - 知乎](https://zhuanlan.zhihu.com/p/646509421)
12 | - [该怎么学elasticsearch? - 老炮说Java的回答 - 知乎](https://www.zhihu.com/question/323811022/answer/2530588398)
13 | - [系统设计之路:如何设计搜索提示(Part:1)](https://mp.weixin.qq.com/s/plXhy4R7yyhq51jvqyCP-Q)
14 | - [System design : Design Autocomplete or Typeahead Suggestions for Google search](https://www.youtube.com/watch?v=us0qySiUsGU)
15 |
--------------------------------------------------------------------------------
/03_system/03_ml/text_generation.md:
--------------------------------------------------------------------------------
1 | # 个性化标题生成
2 |
3 | ## 1. requirements
4 |
5 | **functional**
6 |
7 | - 语言
8 | - 长度
9 |
10 | **non-functional**
11 |
12 | - throughput
13 | - latency
14 |
15 | ## 2. ML task & pipeline
16 |
17 | ## 3. data collection
18 |
19 | - start from zero-shot/few-shot and prompt engineering
20 |
21 | ## 4. feature
22 |
23 | ## 5. model
24 |
25 | **生成策略**
26 |
27 | - Greedy
28 | - Beam Search
29 | - Random Sampling
30 | - Temperature
31 | - Top-K Sampling
32 | - Nucleus Sampling
33 |
34 | ## 6. evaluation
35 |
36 | ## 7. deploy & serving
37 |
38 | framework
39 |
40 | - vLLM + Huggingface TGI
41 | - TensorRT-LLM (especially for hardware supports float8 inference)
42 | - Triton Inference Server with TensorRT-LLM
43 | - sglang
44 | - Triton Inference Server
45 | - lmdeploy
46 |
47 | ## 8. monitor & maintenance
48 |
49 | ## reference
50 |
51 | - [信息流场景下的AIGC实践](https://mp.weixin.qq.com/s/AOTP6oNXhtcCUhdtcEwMTg)
52 | - [https://github.com/microsoft/promptflow](https://github.com/microsoft/promptflow)
53 |
--------------------------------------------------------------------------------
/05_case/02_cheat_sheet.md:
--------------------------------------------------------------------------------
1 | # 面试前必看
2 |
3 | > - 调整面试状态: 自信,积极
4 | > - 框架思维,量化结果,先summary
5 |
6 | ## HR screening
7 |
8 | - 自我介绍
9 | - 介绍身份、签证状态
10 | - 介绍和JD相关的一个典型项目
11 | - 介绍自己为什么对公司、岗位感兴趣
12 | - 介绍自己哪些方面能够打动Hiring manager
13 | - 反问环节
14 | - interview process
15 | - team/role responsibility
16 |
17 | ## Hiring manager
18 |
19 | - 介绍和JD相关的项目、技能: star组织回答
20 | - 反问环节
21 | - tech stack
22 | - like most
23 | - challenge in work
24 |
25 | ## Tech-算法
26 |
27 | > 考察沟通、解决问题的能力、计算机基础
28 | >
29 | > - clarification, think out loudly, coding, complexity & test
30 |
31 | - [How to Talk to the Interviewer](https://blog.faangshui.com/p/how-to-talk-to-the-interviewer)
32 | - [上百场算法面试的软实力经验分享](https://www.1point3acres.com/bbs/thread-1099499-1-1.html)
33 | - [从面试官角度解答coding interview](https://www.1point3acres.com/bbs/thread-1023899-1-1.html)
34 | - 最后看下公司tag题与最近一周的面经题
35 |
36 | ## Tech-系统设计
37 |
38 | > 考察设计能力、思维框架。注意 clarification, think out loudly, trade-off & preference
39 | >
40 | > - 提出需求下可能遇到的问题,解决的几种思路,各个思路的trade-off,从而提出自己的设计主张
41 |
42 | ## BQ
43 |
44 | > 考察软技能、团队合作。注意按框架回答,注意让没有你项目背景的人也能听懂
45 |
46 | - [A Senior Engineer's Guide to the Amazon Leadership Principles Interview](https://interviewing.io/guides/amazon-leadership-principles)
47 |
--------------------------------------------------------------------------------
/05_case/03_post_interview.md:
--------------------------------------------------------------------------------
1 | # 面试之后
2 |
3 | > 面试成功只是第一步,更长的路还在后面;dream company也可能是大坑
4 |
5 | ## 1. competition offer
6 |
7 | > 关键是能多拿offer
8 |
9 | ## 2. 实际工作
10 |
11 | - 对大公司不要抱有任何幻想,任何想不到、没下限的事情都可能发生
12 | - 想promote就要多找机会做下一个级别的事情,多去问老板困扰的问题,多去搞关系,scope, impact, credit;但不想promote,合理提升skill满足自己
13 | - 增强技术的同时,学会吹嘘自己的工作,给老板画饼
14 | - 主动,至少要时不时体现主动
15 | - 多要feedback
16 | - [办公室政治-全是私货](https://www.1point3acres.com/bbs/thread-1031902-1-1.html)
17 | - [中厂Director讲讲我提拔manager的经验](https://www.1point3acres.com/bbs/thread-1031943-1-1.html)
18 |
19 | ## Reference
20 |
21 | - [Shift-AI-models-to-real-world-products](https://github.com/lonelygo/Shift-AI-models-to-real-world-products)
22 | - [谷歌工程实践](https://github.com/google/eng-practices)
23 | - [What is the Team Data Science Process](https://docs.microsoft.com/en-us/azure/machine-learning/team-data-science-process/overview)
24 |
--------------------------------------------------------------------------------
/05_case/README.md:
--------------------------------------------------------------------------------
1 | # 案例
2 |
3 | > - 每个人的背景、技术、运气都不同,但成功的案例总是能给予我们启发,激励我们前进
4 | > - 每次面试后进行复盘,把不会的问题搞懂。面试本身也是一种技能,也需要练习才能提升,不要因为短暂失败而一蹶不振
5 | > - 比如我的明显缺点,(1)题目一问完,我习惯立马回应, 有时忽略了clarification,忽视了回答框架;(2) 面试官给hint的时候,往往还沉浸在不会的思维里,甚至有点主动放弃的消极思想,期待面试官说: 咱不考这个了下一题;(3)英语本身不熟,get 不到提示;(4)回答项目相关的问题时不注意往JD上靠,而是只往问题靠;(5)现场写代码毛躁,易犯低级错误; (6) 结果、指标等关键signal容易忘
6 |
7 | **国内面试国外案例**
8 |
9 | - [小熊猫的 2019 年末跳槽流水账](https://blog.xxm.plus/%E5%B0%8F%E7%86%8A%E7%8C%AB%E7%9A%84-2019-%E5%B9%B4%E6%9C%AB%E8%B7%B3%E6%A7%BD%E6%B5%81%E6%B0%B4%E8%B4%A6)
10 | - [youngforest-从北京到都柏林 一名程序员的润欧之旅](https://zhuanlan.zhihu.com/p/603300157)
11 | - [上海BAT硕5P7,如何肉身在国内面海外工作](https://www.xiaohongshu.com/explore/64a8cbed000000000f00cd76)
12 | - [Sicheng-我所经历的欧美科技公司的面试](https://www.zhihu.com/question/23921846/answer/2337072383)
13 | - [2年国内经验码农的UK求职上岸历程](https://www.1point3acres.com/bbs/thread-1031661-1-1.html)
14 |
15 |
16 | **海外代表性案例**
17 |
18 | - [2023年6月至9月找工体验与分享(III)-面试篇](https://www.1point3acres.com/bbs/thread-1013082-1-1.html)
19 | - [new grads湾区DA/DS找工作超细致回顾+面经+资料总结](https://www.1point3acres.com/bbs/thread-469408-1-1.html)
20 | - [MLE 四个月跳槽总结](https://www.1point3acres.com/bbs/thread-1034084-1-1.html)
21 | - [一年被layoff两次辛路历程和一些面试经验](https://www.1point3acres.com/bbs/thread-1034698-1-1.html)
22 | - [layoff期间拿到超多面试及offer经验分享](https://www.1point3acres.com/bbs/thread-991886-1-1.html)
23 | - [Guide to ML Engineer Job Hunting](https://www.yuan-meng.com/posts/mle_interviews/)
24 | - [2024找工总结与发现](https://www.1point3acres.com/bbs/thread-1098907-1-1.html)
25 |
--------------------------------------------------------------------------------