├── AlgorithmDaily ├── 2022_03_06_lc560 Subarray Sum Equals K.cpp └── README.md ├── AlgorithmImages ├── README.md ├── eventual-consistency.png ├── hash_ring.png ├── load_balancer.jpg ├── load_balancing.png ├── mapreduce.png ├── segtree.png ├── strong-consistency.png └── web-server.svg ├── Competitive Programmer’s Handbook ├── Chapter 05: Complete Search │ ├── 1.Generating Subsets.cpp │ ├── 2.Generating permutations.cpp │ ├── 3.N-Queens.cpp │ ├── 4.Combination Sum.cpp │ └── README.md ├── Chapter 06: Greedy Algorithm │ ├── 1.Interval Scheduling.cpp │ └── README.md ├── Chapter 07: Dynamic Programming │ ├── 1.Coin Change.cpp │ ├── 2.Coin Change 2.cpp │ ├── 3.Longest Increasing Subsequence.cpp │ ├── 4.Minimum Path Sum.cpp │ ├── 5.Target Sum.cpp │ ├── 6.Maximum Profit in Job Scheduling.cpp │ ├── 7.Partition Equal Subset Sum.cpp │ └── README.md ├── Chapter 08: Amortized analysis │ ├── 2.Subarray Product Less Than K.cpp │ └── README.md ├── Chapter 09: Range queries │ └── README.md ├── Chapter 10: Bit manipulation │ ├── 1.Optimal Selection.cpp │ ├── 2.From permutations to subsets.cpp │ ├── 3.Max or subarray.cpp │ └── README.md ├── Chapter 11: Basics of Graphs │ └── README.md ├── Chapter 12: Graph Traversal │ └── README.md ├── Chapter 13: Shortest Paths │ ├── 1.Cheapest Flights Within K Stops.cpp │ ├── 2.Path with Maximum Probability.cpp │ └── README.md ├── Chapter 14: Tree Algorithm │ ├── 1.Maximum Path Sum.cpp │ ├── 2.All Longest Path.cpp │ ├── 3.DP_Diameter.cpp │ ├── 4.DFS_Diameter.cpp │ └── README.md ├── Chapter 15: Spanning Trees │ └── README.md ├── Chapter 16: Directed Graphs │ └── README.md ├── Chapter 17: Strong Connectivity │ ├── 1.Strongly Connected Components.cpp │ └── README.md ├── Chapter 18: Tree Queries │ ├── 1. Kth Ancestor of a Tree Node.cpp │ ├── 2.Most Frequent Subtree Sum.cpp │ ├── 3.Lowest Common Ancestor of a Binary Tree.cpp │ └── README.md ├── Chapter 19: Paths and Circuits │ └── README.md ├── Chapter 20: Flows and Cuts │ ├── 1.Ford–Fulkerson Algorithm.cpp │ └── README.md ├── Chapter 26: String Algorithm │ └── README.md ├── Chapter 27: Square Root Algorithms │ └── README.md ├── Chapter 28: Segment Trees Revisited │ └── README.md ├── Chapter 29: Geometry │ └── README.md ├── Chapter 30: Sweep Line Algorithms │ └── README.md └── README.md ├── Facebook Interviews ├── 020. Valid Parentheses.cpp ├── 033. Search in Rotated Sorted Array.cpp ├── 037. Sudoku Solver.cpp ├── 050. Pow(x, n).cpp ├── 053. Maximum Subarray.cpp ├── 056. Merge Intervals.cpp ├── 057. Insert Interval.cpp ├── 124. Binary Tree Maximum Path Sum.cpp ├── 1249. Minimum Remove to Make Valid Parentheses.cpp ├── 211. Design Add and Search Words Data Structure.cpp ├── 253. Meeting Rooms II.cpp ├── 560. Subarray Sum Equals K.cpp ├── 621. Task Scheduler.cpp ├── 785. Is Graph Bipartite?.cpp ├── 986. Interval List Intersections.cpp └── README.md ├── Google Kick Start ├── 2016 │ ├── README.md │ └── Round A │ │ ├── Problem A: Country Leader.cpp │ │ ├── Problem B: Rain.cpp │ │ └── README.md └── README.md ├── LeetCode-Hard系列 ├── 76. Minimum Window Substring.cpp └── README.md ├── README.md ├── Sort Algorithms ├── HeapSort.cpp ├── MergeSort.cpp ├── QuickSort.cpp └── README.md ├── Two Medium Each Day └── README.md ├── Week01-基础(C++ Basics) ├── README.md └── UVa1585_Score.cpp ├── Week02-数组(Array) ├── README.md ├── UVa1225_Digit Counting.cpp ├── UVa1586_Molar mass.cpp ├── UVa232_Crossword Answers.cpp └── Uva1588_Kickdown.cpp ├── Week03-递归(Recursion) └── README.md ├── Week04-STL(C++ STL) ├── README.md ├── STL_Queue.cpp └── STL_Stack.cpp ├── Week05-并查集(Union-Find) └── README.md ├── Week06-线段树(Segment Tree) ├── README.md ├── UVa11235_Frequent values.cpp ├── UVa11402_Ahoy, Pirates!.cpp ├── UVa1232_SKYLINE.cpp └── UVa12532_Interval Product.cpp ├── Week07-BFS&DFS(Graph) └── README.md ├── Week08-割点&桥(Cut-Vertex&Bridge) └── README.md ├── Week09-暴力&贪心(Brute-Force&Greedy) └── README.md ├── Week10-暴力&贪心2(Brute-Force&Greedy2) └── README.md ├── Week11-动态规划(Dynamic Programming) ├── README.md └── UVa10684_The Jackpot.cpp ├── Week12-动态规划2(01 knapsack) └── README.md ├── Week13-TSP旅行商&区间DP ├── README.md ├── UVa10496_Collecting Beepers.cpp ├── UVa10721_Bar Codes.cpp ├── UVa10943_How do you add?.cpp └── Uva1261_String Popping.cpp ├── Week14-基础数论(Basic Number Theory) ├── README.md ├── UVa10007_Count the Trees.py ├── UVa10689_Yet another Number Sequence.cpp ├── UVa948_Fibonaccimal Base.cpp ├── UVa991_Safe Salutations.cpp └── primes.cpp ├── 剑☞Offer系列 ├── README.md ├── 题目01-10 │ ├── 01二维数组中的查找.cpp │ ├── 02替换空格.cpp │ ├── 03从头到尾打印链表.cpp │ ├── 04重建二叉树.cpp │ ├── 05用两个栈实现队列.cpp │ ├── 06斐波那契数列.cpp │ ├── 07旋转数组的最小数字.cpp │ ├── 08跳台阶.cpp │ ├── 09变态跳台阶.cpp │ ├── 10矩形覆盖.cpp │ └── README.md ├── 题目11-20 │ ├── 11二进制中1的个数.cpp │ ├── 12数值的整数次方.cpp │ ├── 13调整数组顺序使奇数位于偶数前面.cpp │ ├── 14链表中倒数第k个结点.cpp │ ├── 15反转链表.cpp │ ├── 16合并两个排序的链表.cpp │ ├── 17树的子结构.cpp │ ├── 18二叉树的镜像.cpp │ ├── 19顺时针打印矩阵.cpp │ ├── 20包含min函数的栈.cpp │ └── README.md ├── 题目21-30 │ ├── 21栈的压入、弹出序列.cpp │ ├── 22从上往下打印二叉树.cpp │ ├── 23二叉搜索树的后序遍历序列.cpp │ ├── 24二叉树中和为某一值的路径.cpp │ ├── 25复杂链表的复制.cpp │ ├── 26二叉搜索树与双向链表.cpp │ ├── 27字符串的排列.cpp │ ├── 28数组中出现次数超过一半的数字.cpp │ ├── 29最小的K个数.cpp │ ├── 30连续子数组的最大和.cpp │ └── README.md ├── 题目31-40 │ ├── 31从1到n整数中1出现的次数.cpp │ ├── 32把数组排成最小的数.cpp │ ├── 33丑数.cpp │ ├── 34第一个只出现一次的字符.cpp │ ├── 35数组中的逆序对.cpp │ ├── 36两个链表的第一个公共结点.cpp │ ├── 37数字在排序数组中出现的次数.cpp │ ├── 38二叉树的深度.cpp │ ├── 39平衡二叉树.cpp │ ├── 40数组中只出现一次的数字.cpp │ └── README.md ├── 题目41-50 │ ├── 41和为S的连续正数序列.cpp │ ├── 42和为S的两个数字.cpp │ ├── 43左旋转字符串.cpp │ ├── 44翻转单词顺序列.cpp │ ├── 45扑克牌顺子.cpp │ ├── 46孩子们的游戏(圆圈中最后剩下的数).cpp │ ├── 47求1+2+3+...+n.cpp │ ├── 48不用加减乘除做加法.cpp │ ├── 49把字符串转换成整数.cpp │ ├── 50数组中重复的数字.cpp │ └── README.md ├── 题目51-60 │ ├── 51构建乘积数组.cpp │ ├── 52正则表达式匹配.cpp │ ├── 53表示数值的字符串.cpp │ ├── 54字符流中第一个不重复的字符.cpp │ ├── 55链表中环的入口结点.cpp │ ├── 56删除链表中重复的结点.cpp │ ├── 57二叉树的下一个结点.cpp │ ├── 58对称的二叉树.cpp │ ├── 59按之字形顺序打印二叉树.cpp │ ├── 60把二叉树打印成多行.cpp │ └── README.md └── 题目61-67 │ ├── 61序列化二叉树.cpp │ ├── 62二叉搜索树的第k个结点.cpp │ ├── 63数据流中的中位数.cpp │ ├── 64滑动窗口的最大值.cpp │ ├── 65矩阵中的路径.cpp │ ├── 66机器人的运动范围.cpp │ ├── 67剪绳子.cpp │ └── README.md ├── 动态规划Top50 └── README.md ├── 算法博客(Algorithm Blogs) ├── Bit-Manipulation.md ├── Fenwick Tree(树状数组).md ├── Interval-Trees.md ├── README.md └── Tire(字典树).md └── 莱特扣的-系列 ├── 01.Pattern: Sliding Window ├── 01 Maximum Sum Subarray of Size K.cpp ├── 02 Minimum Size Subarray Sum.cpp ├── 03 Longest Substring with At Most K Distinct Characters.cpp ├── 04 Fruits into Baskets.cpp ├── 05 Longest Substring Without Repeating Characters.cpp ├── 06 Maximum Length Substring Having All Same Characters after K Changes.cpp ├── 07 Longest Subsegment of ‘1’s Formed by Changing at Most K ‘0’s.cpp ├── 08. Sliding Window Maximum.cpp ├── 09. Shortest Subarray with Sum at Least K.cpp ├── 10. Max Consecutive Ones III.cpp ├── 11. Replace the Substring for Balanced String.cpp ├── 12. Count Number of Nice Subarrays.cpp └── README.md ├── 02.Pattern: Two Pointers ├── 01 Two Sum.cpp ├── 02 Remove Duplicates from Sorted Array.cpp ├── 03 Squares of a Sorted Array.cpp ├── 04 3Sum.cpp ├── 05 3Sum Closest.cpp ├── 06 3Sum Smaller.cpp ├── 07 Subarray Product Less Than K.cpp ├── 08 Sort Colors.cpp └── README.md ├── 03.Pattern: Fast&Slow Pointers ├── 01 Linked List Cycle.cpp ├── 02 Middle of the Linked List.cpp ├── 03 Happy Number.cpp ├── 04 Linked List Cycle II.cpp └── README.md ├── 04.Pattern: Merge Intervals ├── 01 Merge Intervals.cpp ├── 02 Insert Interval.cpp ├── 03 Interval List Intersections.cpp ├── 04 Conflicting Appointments.cpp ├── 05 Non-overlapping Intervals.cpp ├── 06 Data Stream as Disjoint Intervals.cpp ├── 07 Range Module.cpp └── README.md ├── 05.Pattern: Cyclic Sort ├── 01 Cycle Sort.cpp ├── 02 Missing Number.cpp ├── 03 Find All Numbers Disappeared in an Array.cpp ├── 04 Find the Duplicate Number.cpp ├── 05 Find All Duplicates in an Array.cpp └── README.md ├── 06.Pattern: In-place Reversal of a LinkedList ├── 01 Reverse Linked List.cpp ├── 02 Reverse Linked List II.cpp ├── 03 Reverse Nodes in k-Group.cpp └── README.md ├── 07.Pattern: Tree Breadth First Search ├── 01 Binary Tree Level Order Traversal.cpp ├── 02 Binary Tree Level Order Traversal II.cpp ├── 03 Minimum Depth of Binary Tree.cpp ├── 04 Average of Levels in Binary Tree.cpp ├── 05 Level Order Successor of a node in Binary Tree.cpp ├── 06 Binary Tree Zigzag Level Order Traversal.cpp ├── 07 Populating Next Right Pointers in Each Node.cpp └── README.md ├── 08.Pattern: Tree Depth First Search ├── 01 Path Sum.cpp ├── 02 Path Sum II.cpp ├── 03 Sum Root to Leaf Numbers.cpp ├── 04 Path With Given Sequence.cpp ├── 05 Path Sum III.cpp └── README.md ├── 09.Pattern: Two Heaps ├── 01 Find Median from Data Stream.cpp ├── 02 Sliding Window Median.cpp ├── 03 IPO.cpp └── README.md ├── 10.Pattern: Subsets ├── 01 Subsets.cpp ├── 02 Subsets II.cpp ├── 03 Permutations.cpp ├── 04 Letter Case Permutation.cpp ├── 05 Minimum Remove to Make Valid Parentheses.cpp ├── 07 Generalized Abbreviation.cpp └── README.md ├── 11.Pattern: Modified Binary Search ├── 1. Maximum sum Bi-tonic Sub-sequence.cpp ├── 2. Order-Agnostic Binary Search.cpp ├── 3. Ceiling of a Number.cpp ├── 4. Find Smallest Letter Greater Than Target.cpp ├── 5. Find First and Last Position of Element in Sorted Array.cpp ├── 6. Search in a Sorted Infinite Array.cpp ├── 7. Kth Smallest Element in a Sorted Matrix.cpp ├── 8. Median of Two Sorted Arrays.cpp └── README.md ├── 12.Pattern: Top ‘K’ Elements ├── 1. K Closest Points to Origin.cpp ├── 2. Min Cost to Connect Ropes.cpp ├── 3. Top K Frequent Elements.cpp ├── 4. Sort Characters By Frequency.cpp ├── 5. Kth Largest Element in an Array.cpp ├── 6. Find K Closest Elements.cpp ├── 7. Maximum distinct elements after removing k elements.cpp ├── 8. Reorganize String.cpp └── README.md ├── 13.Pattern: K-Way Merge ├── 1. Merge k Sorted Lists.cpp ├── 2. Find m-th smallest value in k sorted arrays.cpp ├── 3, Kth Smallest Element in a Sorted Matrix.cpp ├── 4. Smallest Range Covering Elements from K Lists.cpp └── README.md ├── 14.Pattern: 01 Knapsack (Dynamic Programming) ├── 2. Partition Equal Subset Sum.cpp ├── 4. Constrained Subset Sum.cpp ├── 5. Minimum Partition.cpp └── README.md ├── 15.Pattern: Topological Sort (Graph) ├── 1. Topological Sort.cpp ├── 2. Course Schedule.cpp ├── 3. Course Schedule II.cpp ├── 5. Alien Dictionary.cpp └── README.md ├── 16.Pattern: Design a XXX ├── 1. Design Twitter.cpp ├── 2. Design Circular Queue.cpp ├── 2. Design Hit Counter.cpp └── README.md └── README.md /AlgorithmDaily/2022_03_06_lc560 Subarray Sum Equals K.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | LC560. Subarray Sum Equals K (https://leetcode.com/problems/subarray-sum-equals-k/) 3 | "Given an array of integers nums and an integer k, return the total number of subarrays whose sum equals to k" 4 | */ 5 | class Solution { 6 | public: 7 | int subarraySum(vector& nums, int k) { 8 | int sum = 0, res = 0; 9 | unordered_map mp; mp[0] = 1; 10 | for(auto n : nums) { 11 | sum += n; 12 | if(mp.count(sum - k) != 0) 13 | res += mp[sum - k]; 14 | ++mp[sum]; 15 | } 16 | return res; 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /AlgorithmDaily/README.md: -------------------------------------------------------------------------------- 1 | ### LC560. [Subarray Sum Equals K](https://leetcode.com/problems/subarray-sum-equals-k/) 解析 2 | #### 【关键字】: 3 | * 数组 4 | * 哈希Table 5 | * 前缀和 6 | 7 | ### LC1570. [Dot Product of Two Sparse Vectors](https://zhenchaogan.gitbook.io/leetcode-solution/leetcode-1570-dot-product-of-two-sparse-vectors) 解析 8 | #### 【关键字】: 9 | -------------------------------------------------------------------------------- /AlgorithmImages/README.md: -------------------------------------------------------------------------------- 1 | To save some images used in my blogs. 2 | -------------------------------------------------------------------------------- /AlgorithmImages/eventual-consistency.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huixxi/Algorithm-with-Cplusplus/b9c8ebbe7c33ba2239c748fe20290914582edd30/AlgorithmImages/eventual-consistency.png -------------------------------------------------------------------------------- /AlgorithmImages/hash_ring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huixxi/Algorithm-with-Cplusplus/b9c8ebbe7c33ba2239c748fe20290914582edd30/AlgorithmImages/hash_ring.png -------------------------------------------------------------------------------- /AlgorithmImages/load_balancer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huixxi/Algorithm-with-Cplusplus/b9c8ebbe7c33ba2239c748fe20290914582edd30/AlgorithmImages/load_balancer.jpg -------------------------------------------------------------------------------- /AlgorithmImages/load_balancing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huixxi/Algorithm-with-Cplusplus/b9c8ebbe7c33ba2239c748fe20290914582edd30/AlgorithmImages/load_balancing.png -------------------------------------------------------------------------------- /AlgorithmImages/mapreduce.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huixxi/Algorithm-with-Cplusplus/b9c8ebbe7c33ba2239c748fe20290914582edd30/AlgorithmImages/mapreduce.png -------------------------------------------------------------------------------- /AlgorithmImages/segtree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huixxi/Algorithm-with-Cplusplus/b9c8ebbe7c33ba2239c748fe20290914582edd30/AlgorithmImages/segtree.png -------------------------------------------------------------------------------- /AlgorithmImages/strong-consistency.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huixxi/Algorithm-with-Cplusplus/b9c8ebbe7c33ba2239c748fe20290914582edd30/AlgorithmImages/strong-consistency.png -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 05: Complete Search/1.Generating Subsets.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector> res; 4 | vector subset; 5 | vector> subsets(vector& nums) { 6 | helper(nums, 0); 7 | return res; 8 | } 9 | 10 | void helper(vector& nums, int k) { 11 | if(k == nums.size()) { 12 | res.push_back(subset); 13 | return; 14 | } 15 | helper(nums, k + 1); 16 | subset.push_back(nums[k]); 17 | helper(nums, k + 1); 18 | subset.pop_back(); 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 05: Complete Search/2.Generating permutations.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector> res; 4 | vector perm; 5 | vector> permute(vector& nums) { 6 | int n = nums.size(); 7 | vector chosen(n, false); 8 | helper(nums, chosen); 9 | return res; 10 | } 11 | 12 | void helper(vector& nums, vector& chosen) { 13 | if(perm.size() == nums.size()) { 14 | res.push_back(perm); 15 | return; 16 | } 17 | for(int i = 0; i < nums.size(); ++i) { 18 | if(chosen[i]) 19 | continue; 20 | chosen[i] = true; 21 | perm.push_back(nums[i]); 22 | helper(nums, chosen); 23 | perm.pop_back(); 24 | chosen[i] = false; 25 | } 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 05: Complete Search/3.N-Queens.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector> solveNQueens(int n) { 4 | vector> res; 5 | vector nQueens(n, string(n, '.')); 6 | vector flag_col(n, 1), flag_l45(2 * n - 1, 1), flag_r45(2 * n - 1, 1); 7 | helper(res, nQueens, flag_col, flag_l45, flag_r45, 0, n); 8 | return res; 9 | } 10 | 11 | void helper(vector>& res, vector& nQueens, vector& flag_col, vector& flag_l45, vector& flag_r45, int row, int& n) { 12 | if(row == n) { 13 | res.push_back(nQueens); 14 | return; 15 | } 16 | for(int col = 0; col < n; ++col) { 17 | if(flag_col[col] && flag_l45[row + col] && flag_r45[n - 1 + col - row]) { 18 | flag_col[col] = flag_l45[row + col] = flag_r45[n - 1 + col - row] = 0; 19 | nQueens[row][col] = 'Q'; 20 | helper(res, nQueens, flag_col, flag_l45, flag_r45, row + 1, n); 21 | nQueens[row][col] = '.'; 22 | flag_col[col] = flag_l45[row + col] = flag_r45[n - 1 + col - row] = 1; 23 | } 24 | } 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 05: Complete Search/4.Combination Sum.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector combs; 4 | vector> res; 5 | vector> combinationSum(vector& candidates, int target) { 6 | search(candidates, 0, target); 7 | return res; 8 | } 9 | 10 | void search(vector& cands, int k, int tar) { 11 | if(tar < 0) 12 | return; 13 | if(tar == 0) { 14 | res.push_back(combs); 15 | return; 16 | } 17 | for(int i = k; i < cands.size(); ++i) { 18 | combs.push_back(cands[i]); 19 | search(cands, i, tar - cands[i]); 20 | combs.pop_back(); 21 | } 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 05: Complete Search/README.md: -------------------------------------------------------------------------------- 1 | ## Corresponding Problems on LeetCode 2 | * [39. Combination Sum](https://leetcode.com/problems/combination-sum/) 3 | * [46. Permutations](https://leetcode.com/problems/permutations/) 4 | * [51. N-Queens](https://leetcode.com/problems/n-queens/) 5 | * [78. Subsets](https://leetcode.com/problems/subsets/) 6 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 06: Greedy Algorithm/1.Interval Scheduling.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | static bool comp(vector& a, vector& b) { 4 | return a[1] < b[1]; 5 | } 6 | int findLongestChain(vector>& pairs) { 7 | // Greedy, always select the next possible event that ends as early as possible. 8 | sort(pairs.begin(), pairs.end(), comp); 9 | int cnt = 1; 10 | vector p = pairs[0]; 11 | for(int i = 1; i < pairs.size(); ++i) { 12 | if(pairs[i][0] > p[1]) { 13 | ++cnt; 14 | p = pairs[i]; 15 | } 16 | } 17 | return cnt; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 06: Greedy Algorithm/README.md: -------------------------------------------------------------------------------- 1 | # Greedy Algorithm 2 | 贪心算法的意思是每次都选择在当前看起来最优的那一个。设计一个贪心算法的难点在于如何设计一个贪心策略,局部最优的选择也应同样是全局最优选择。 3 | 4 | ## Corresponding Problems on LeetCode 5 | * Coin Problem 6 | * Scheduling 7 | * [646. Maximum Length of Pair Chain](https://leetcode.com/problems/maximum-length-of-pair-chain/) 8 | * Tasks and deadlines 9 | * Just perform the tasks sorted by their durations in increasing order 10 | * Minimizing sums `|a1 − x|^c + |a2 − x|^c + ... + |an − x|^c`. 11 | * `c = 1`: choose `x` be the *median* 12 | * `c = 2`: choose `x` be the *average* 13 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 07: Dynamic Programming/1.Coin Change.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int coinChange(vector& coins, int amount) { 4 | vector dp(amount + 1, 10000); 5 | dp[0] = 0; 6 | for(int a = 1; a <= amount; ++a) { 7 | for(auto c : coins) { 8 | if(a - c >= 0) 9 | dp[a] = min(dp[a - c] + 1, dp[a]); 10 | } 11 | } 12 | return dp[amount] == 10000 ? -1 : dp[amount]; 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 07: Dynamic Programming/2.Coin Change 2.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int change(int amount, vector& coins) { 4 | vector dp(amount + 1, 0); 5 | dp[0] = 1; 6 | for(auto c : coins) { 7 | for(int a = c; a <= amount; ++a) { 8 | if(a - c >= 0) 9 | dp[a] += dp[a - c]; 10 | } 11 | } 12 | return dp[amount]; 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 07: Dynamic Programming/3.Longest Increasing Subsequence.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int lengthOfLIS(vector& nums) { 4 | int n = nums.size(); 5 | if(n == 0) 6 | return 0; 7 | vector lens(n, 0); 8 | for(int k = 0; k < n; ++k) { 9 | lens[k] = 1; 10 | for(int i = 0; i < k; ++i) { 11 | if(nums[i] < nums[k]) { 12 | lens[k] = max(lens[i] + 1, lens[k]); 13 | } 14 | } 15 | } 16 | return lens[n - 1]; 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 07: Dynamic Programming/4.Minimum Path Sum.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int minPathSum(vector>& grid) { 4 | int m = grid.size(); 5 | int n = grid[0].size(); 6 | for(int i = 1; i < m; ++i) grid[i][0] += grid[i - 1][0]; 7 | for(int i = 1; i < n; ++i) grid[0][i] += grid[0][i - 1]; 8 | for(int i = 1; i < m; ++i) { 9 | for(int j = 1; j < n; ++j) { 10 | grid[i][j] += min(grid[i-1][j], grid[i][j-1]); 11 | } 12 | } 13 | return grid[m-1][n-1]; 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 07: Dynamic Programming/5.Target Sum.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int findTargetSumWays(vector& nums, int S) { 4 | int sum = 0; 5 | for(auto& n : nums) sum += n; 6 | if(S > sum || (sum + S) % 2 == 1) 7 | return 0; 8 | int target = (sum + S) / 2; 9 | vector dp(target + 1, 0); 10 | dp[0] = 1; 11 | for(auto& n : nums) { 12 | for(int a = target; a >= n; --a) { 13 | if(a - n >= 0) { 14 | dp[a] += dp[a - n]; 15 | } 16 | } 17 | } 18 | return dp[target]; 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 07: Dynamic Programming/6.Maximum Profit in Job Scheduling.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int jobScheduling(vector& startTime, vector& endTime, vector& profit) { 4 | int n = profit.size(); 5 | vector> jobs(n, vector(3, 0)); 6 | for(int i = 0; i < n; ++i) 7 | jobs[i] = {startTime[i], endTime[i], profit[i]}; 8 | sort(jobs.begin(), jobs.end()); 9 | for(int i = 0; i < n; ++i) 10 | startTime[i] = jobs[i][0], endTime[i] = jobs[i][1], profit[i] = jobs[i][2]; 11 | vector dp(n, 0); 12 | dp[n - 1] = profit[n - 1]; 13 | for(int i = n - 2; i >= 0; --i) { 14 | auto it = lower_bound(startTime.begin() + i, startTime.end(), endTime[i]); 15 | if(it != startTime.end()) 16 | dp[i] += max(dp[i + 1], dp[it - startTime.begin()] + profit[i]); 17 | else 18 | dp[i] += max(dp[i + 1], profit[i]); 19 | } 20 | return dp[0]; 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 07: Dynamic Programming/7.Partition Equal Subset Sum.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | bool canPartition(vector& nums) { 4 | int sum = 0, mx = 0; 5 | for (auto& num : nums) 6 | sum += num; 7 | 8 | if ((sum & 1) == 1) 9 | return false; 10 | 11 | sum /= 2; 12 | 13 | vector dp(sum + 1, false); 14 | dp[0] = true; 15 | for(auto& n : nums) { 16 | for(int i = sum - n; i >= 0; --i) 17 | if(dp[i]) 18 | dp[i + n] = true; 19 | } 20 | return dp[sum]; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 07: Dynamic Programming/README.md: -------------------------------------------------------------------------------- 1 | # Dynamic Programming 2 | 3 | ## Corresponding Problems on LeetCode 4 | * Coin Problem(General Case) 5 | * [322. Coin Change](https://leetcode.com/problems/coin-change/) 6 | * [518. Coin Change 2](https://leetcode.com/problems/coin-change-2/) 7 | * Longest Increasing Subsequence 8 | * [300. Longest Increasing Subsequence](https://leetcode.com/problems/longest-increasing-subsequence/) 9 | * Paths in a Grid 10 | * [64. Minimum Path Sum](https://leetcode.com/problems/minimum-path-sum/) 11 | * Knapsack Problems 12 | * [494. Target Sum](https://leetcode.com/problems/target-sum/) 13 | * [1235. Maximum Profit in Job Scheduling](https://leetcode.com/problems/maximum-profit-in-job-scheduling/) 14 | * [416. Partition Equal Subset Sum](https://leetcode.com/problems/partition-equal-subset-sum/) 15 | * Edit Distance 16 | * [72. Edit Distance](https://github.com/Huixxi/Algorithm-with-Cplusplus/tree/master/Week11-%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92(Dynamic%20Programming)#8-%E6%9C%80%E7%9F%AD%E7%BC%96%E8%BE%91%E8%B7%9D%E7%A6%BB) 17 | * Counting Tilings 18 | * It's a little bit hard... but there is an efficient direct formula to calculate it. 19 | 20 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 08: Amortized analysis/2.Subarray Product Less Than K.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int numSubarrayProductLessThanK(vector& nums, int k) { 4 | int i = 0, j = 0, n = nums.size(), res = 0, pro = 1; 5 | while(j < n) { 6 | pro *= nums[j]; 7 | while(pro >= k && i <= j) { 8 | pro /= nums[i]; 9 | ++i; 10 | } 11 | res += (j - i + 1); 12 | ++j; 13 | } 14 | return res; 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 08: Amortized analysis/README.md: -------------------------------------------------------------------------------- 1 | # Amortized analysis 2 | Sometimes a straightforward analysis does not give a true picture of the efficiency of the algorithm. 3 | 4 | ## Corresponding Problems on LeetCode 5 | * Two pointers method 6 | * [1. Two Sum](https://leetcode.com/problems/two-sum/) 7 | * [76. Minimum Window Substring](https://leetcode.com/problems/minimum-window-substring/) 8 | * [713. Subarray Product Less Than K](https://leetcode.com/problems/subarray-product-less-than-k/) 9 | * Nearest smaller elements 10 | * Solve it with stack. 11 | * Sliding window minimum 12 | * [239. Sliding Window Maximum](https://leetcode.com/problems/sliding-window-maximum/) 13 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 09: Range queries/README.md: -------------------------------------------------------------------------------- 1 | # Range queries 2 | 3 | ## Corresponding Problems on LeetCode 4 | * Static array queries(the array values are never updated between the queries) 5 | * Sum queries -- prefix sum array(1D,2D) 6 | * Minimum queries -- min(a, b) = min(min(a, a+k−1), min(b−k+1, b)). 7 | * Binary indexed tree 8 | * [Fenwick Tree树状数组](https://github.com/Huixxi/Algorithm-with-Cplusplus/blob/master/%E7%AE%97%E6%B3%95%E5%8D%9A%E5%AE%A2(Algorithm%20Blogs)/Fenwick%20Tree(%E6%A0%91%E7%8A%B6%E6%95%B0%E7%BB%84).md) 9 | * Segment tree 10 | * [线段树(Segment Tree)](https://github.com/Huixxi/Algorithm-with-Cplusplus/tree/master/Week06-%E7%BA%BF%E6%AE%B5%E6%A0%91(Segment%20Tree)) 11 | * Additional techniques 12 | * Index compression -- This can be done if we know all the indices needed during the algorithm beforehand. 13 | * Range updates -- difference array, The advantage of the difference array is that we can update a range in the 14 | original array by changing just two elements in the difference array. More generally, to increase the values in range `[ a, b ]` by `x`, we increase the value at position `a` by `x` and decrease the value at position `b + 1` by `x`. 15 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 10: Bit manipulation/1.Optimal Selection.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | input.txt 3 | 3 8 4 | 6 9 5 2 8 9 1 6 5 | 8 2 6 2 7 5 7 2 6 | 5 3 9 7 3 5 1 4 7 | The time complexity of the algorithm is O(nk2^k) 8 | */ 9 | #include 10 | using namespace std; 11 | 12 | const int MX = 1e5; 13 | 14 | int main() { 15 | auto r = freopen("input.txt", "r", stdin); 16 | int k, n; 17 | cin >> k >> n; 18 | int price[k][n]; 19 | for(int i = 0; i < k; ++i) 20 | for(int j = 0; j < n; ++j) 21 | cin >> price[i][j]; 22 | 23 | vector> total(1<(n, MX)); 24 | for(int d = 0; d < n; ++d) 25 | total[0][d] = 0; 26 | for(int x = 0; x < k; ++x) 27 | total[1< 8 | using namespace std; 9 | 10 | int main() { 11 | auto r = freopen("input.txt", "r", stdin); 12 | int x, n; 13 | cin >> x >> n; 14 | int wt[n]; 15 | for(int i = 0; i < n; ++i) { 16 | cin >> wt[i]; 17 | } 18 | // rides(S): the minimum number of rides for a subset S 19 | // last(S): the minimum weight of the last ride 20 | pair best[1< adj[N];` | `vector> adj[N]; // weighted graph` 19 | * Adjacency matrix representation: `int adj[N][N]; // 0/1 or weights` 20 | * Edge list representation: `vector> edges;` | `vector> edges; // weighted graph` 21 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 12: Graph Traversal/README.md: -------------------------------------------------------------------------------- 1 | # Graph Traversal 2 | 3 | ## Depth-First Search(DFS) 4 | ```c++ 5 | vector adj[N]; 6 | bool visited[N]; 7 | 8 | void dfs(int s) { 9 | if(visited[s]) return; 10 | visited[s] = true; 11 | // process node s 12 | for(auto u : adj[s]) : 13 | dfs(u); 14 | } 15 | } 16 | ``` 17 | 18 | ## Breadth-First Search(BFS) 19 | ```c++ 20 | queue q; 21 | bool visited[N]; 22 | int distance[N]; 23 | 24 | visited[x] = true; 25 | distance[x] = 0; 26 | q.push(x); 27 | while (!q.empty()) { 28 | int s = q.front(); q.pop(); 29 | // process node s 30 | for (auto u : adj[s]) { 31 | if (visited[u]) continue; 32 | visited[u] = true; 33 | distance[u] = distance[s] + 1; 34 | q.push(u); 35 | } 36 | } 37 | ``` 38 | 39 | ## Applications 40 | * **Connectivity Check(使用DFS连通性检查以及查找连通分量)** 41 | * **Finding Cycles(使用DFS找环)** 42 | * If during a graph traversal, we find a node whose neighbor has already been visited. 43 | * To simply calculate the number of nodes and edges in every component. 44 | * **Bipartiteness Check(使用DFS二分图/偶图检测)** 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 13: Shortest Paths/1.Cheapest Flights Within K Stops.cpp: -------------------------------------------------------------------------------- 1 | typedef tuple Ti; 2 | class Solution { 3 | public: 4 | int findCheapestPrice(int n, vector>& flights, int src, int dst, int K) { 5 | vector> adj[n]; 6 | priority_queue, greater> q; 7 | for(auto v : flights) { 8 | adj[v[0]].push_back({v[1], v[2]}); 9 | } 10 | q.push({0, src, K + 1}); 11 | while(!q.empty()) { 12 | auto [cost, s, stops] = q.top(); 13 | q.pop(); 14 | if(s == dst) 15 | return cost; 16 | if(stops == 0) 17 | continue; 18 | for(auto d : adj[s]) { 19 | q.push({cost + d.second, d.first, stops - 1}); 20 | } 21 | } 22 | return -1; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 13: Shortest Paths/2.Path with Maximum Probability.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | double maxProbability(int n, vector>& edges, vector& succProb, int start, int end) { 4 | vector> adj[n]; 5 | for(int i = 0; i < edges.size(); ++i) { 6 | adj[edges[i][0]].push_back({succProb[i], edges[i][1]}); 7 | adj[edges[i][1]].push_back({succProb[i], edges[i][0]}); 8 | } 9 | vector visited(n, false); 10 | vector prob(n, 0.0); prob[start] = 1.0; 11 | priority_queue> pq; 12 | pq.push({1.0, start}); 13 | while(!pq.empty()) { 14 | auto p = pq.top(); pq.pop(); 15 | if(visited[p.second]) continue; 16 | visited[p.second] = true; 17 | for(auto x : adj[p.second]) { 18 | double w = x.first; int v = x.second; 19 | if(prob[p.second] * w > prob[v]) { 20 | prob[v] = prob[p.second] * w; 21 | pq.push({prob[v], v}); 22 | } 23 | } 24 | } 25 | return prob[end]; 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 14: Tree Algorithm/1.Maximum Path Sum.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 14 3 | 1 2 4 | 1 3 5 | 1 4 6 | 2 5 7 | 2 6 8 | 3 7 9 | 4 8 10 | 4 9 11 | 4 10 12 | 5 11 13 | 5 12 14 | 7 13 15 | 7 14 16 | 3 2 1 10 1 3 9 1 5 3 4 5 9 8 17 | 18 | output: 22 19 | */ 20 | #include 21 | using namespace std; 22 | 23 | const int mx = 100; 24 | 25 | int dp[mx]; 26 | 27 | void dfs(vector& val, vector adj[], int node) { 28 | dp[node] = val[node]; 29 | int maxium = 0; 30 | for(auto n : adj[node]) { 31 | dfs(val, adj, n); 32 | maxium = max(maxium, dp[n]); 33 | } 34 | dp[node] += maxium; 35 | } 36 | 37 | int main() { 38 | auto r = freopen("input.txt", "r", stdin); 39 | int n; 40 | cin >> n; 41 | vector adj[n + 1]; 42 | vector val(n + 1, 0); 43 | int p, c; 44 | for(int i = 1; i < n; ++i) { 45 | cin >> p >> c; 46 | adj[p].push_back(c); 47 | } 48 | for(int i = 1; i <= n; ++i) 49 | cin >> val[i]; 50 | 51 | dfs(val, adj, 1); 52 | cout << dp[1] << endl; 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 14: Tree Algorithm/3.DP_Diameter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 5 3 | 1 2 4 | 1 3 5 | 2 4 6 | 2 5 7 | 8 | output: 3 9 | */ 10 | #include 11 | using namespace std; 12 | 13 | const int mx = 100; 14 | 15 | int in[mx] = {0}; 16 | int out[mx] = {0}; 17 | 18 | int dfs(vector adj[], int node, int parent) { 19 | int mx1 = -1, mx2 = -1; 20 | 21 | for(auto n : adj[node]) { 22 | if(n == parent) 23 | continue; 24 | 25 | dfs(adj, n, node); 26 | 27 | if(in[n] >= mx1) { 28 | mx2 = mx1; 29 | mx1 = in[n]; 30 | } 31 | else if(in[n] > mx2) 32 | mx2 = in[n]; 33 | } 34 | in[node] = 1; 35 | if(mx1 != -1) 36 | in[node] += mx1; 37 | if(mx2 != -1) 38 | out[node] = 1 + mx1 + mx2; 39 | return max(in[node], out[node]); 40 | } 41 | 42 | 43 | int main() { 44 | auto r = freopen("input.txt", "r", stdin); 45 | int n; 46 | cin >> n; 47 | vector adj[n + 1]; 48 | vector val(n + 1, 0); 49 | int p, c; 50 | for(int i = 1; i < n; ++i) { 51 | cin >> p >> c; 52 | adj[p].push_back(c); 53 | } 54 | cout << dfs(adj, 1, 0) << endl; 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 14: Tree Algorithm/4.DFS_Diameter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 7 3 | 1 2 4 | 1 3 5 | 2 4 6 | 2 5 7 | 3 7 8 | 4 6 9 | 10 | output: 5 11 | */ 12 | #include 13 | using namespace std; 14 | 15 | const int mx = 100; 16 | 17 | int x = 0, mxcnt = INT_MIN; 18 | 19 | int dfs(vector adj[], int cnt, int node, int parent) { 20 | ++cnt; 21 | for(auto n : adj[node]) { 22 | if(n == parent) 23 | continue; 24 | if(cnt >= mxcnt) { 25 | mxcnt = cnt; 26 | x = n; 27 | } 28 | dfs(adj, cnt, n, node); 29 | } 30 | } 31 | 32 | int diameter(vector adj[]) { 33 | dfs(adj, 0, 1, 0); // arbitrary start node, we choose 1 here. 34 | cout << mxcnt << " " << x << endl; // 3 6 35 | dfs(adj, 0, x, 0); 36 | return mxcnt; 37 | } 38 | 39 | int main() { 40 | auto r = freopen("input.txt", "r", stdin); 41 | int n; 42 | cin >> n; 43 | vector adj[n + 1]; 44 | int p, c; 45 | for(int i = 1; i < n; ++i) { 46 | cin >> p >> c; 47 | adj[p].push_back(c); 48 | adj[c].push_back(p); 49 | } 50 | cout << diameter(adj) << endl; 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 17: Strong Connectivity/README.md: -------------------------------------------------------------------------------- 1 | # Strong Connectivity(强连通图) 2 | A directed graph is **strongly connected** if there is a path from any node to all other nodes in the graph. 3 | 4 | The **strongly connected components(强连通分量)** of a graph divide the graph into strongly connected parts that are as large as possible. The strongly connected components form an acyclic **component graph** that represents the deep structure of the original graph. 5 | 6 | ## Kosaraju’s Algorithm(`O(n+m)`) 7 | Detailed explain: [Strongly Connected Components Kosaraju's Algorithm Graph Algorithm](youtube.com/watch?v=RpgcYiky7uw) 8 | 9 | Kosaraju’s algorithm is an efficient method for finding the strongly connected components of a directed graph. The algorithm performs two depth-first searches: 10 | * Search 1: constructs a list of nodes in the order of their timestep that a depth-first search finish processes them. 11 | * Search 2: reverses every edge in the graph, then use a depth-first search to form the strongly connected components. 12 | 13 | ## 2SAT problem 14 | In this problem, we are given a logical formula **(a1 ∨ b1) ∧ (a2 ∨ b2) ∧ · · · ∧ (am ∨ bm)**, our task is to assign each variable a value so that the 15 | formula is **true**, or state that this is **not possible**. The 2SAT problem can be represented as a directed graph whose nodes correspond to variables `xi` and negations `¬xi`, and edges determine the connections between the variables. And in the graph of the formula if there are no nodes `xi` and `¬xi` such that both 16 | nodes belong to the same strongly connected component, so a solution exists. 17 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 18: Tree Queries/1. Kth Ancestor of a Tree Node.cpp: -------------------------------------------------------------------------------- 1 | class TreeAncestor { 2 | public: 3 | int h = 0; 4 | vector> ast; 5 | TreeAncestor(int n, vector& parent) { 6 | ast.push_back(parent); 7 | int cnt = 0; 8 | while(cnt != n) { 9 | cnt = 0; 10 | vector tmp(n, -1); 11 | for(int i = 0; i < n; ++i) { 12 | tmp[i] = ast[h][i] == -1 ? -1 : ast[h][ast[h][i]]; 13 | if(tmp[i] == -1) 14 | ++cnt; 15 | } 16 | ast.push_back(tmp); 17 | ++h; 18 | } 19 | } 20 | 21 | int getKthAncestor(int node, int k) { 22 | if(k > pow(2, h)) return -1; 23 | int j = (1 << h); 24 | for(int i = 0; i <= h; ++i) { 25 | if(k & (j >> i)) { 26 | node = ast[h-i][node]; 27 | if(node == -1) 28 | return node; 29 | } 30 | } 31 | return node; 32 | } 33 | }; 34 | 35 | /** 36 | * Your TreeAncestor object will be instantiated and called as such: 37 | * TreeAncestor* obj = new TreeAncestor(n, parent); 38 | * int param_1 = obj->getKthAncestor(node,k); 39 | */ 40 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 18: Tree Queries/2.Most Frequent Subtree Sum.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * struct TreeNode { 4 | * int val; 5 | * TreeNode *left; 6 | * TreeNode *right; 7 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 8 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 9 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 10 | * }; 11 | */ 12 | class Solution { 13 | public: 14 | unordered_map cnt; 15 | int mx = 0; 16 | vector findFrequentTreeSum(TreeNode* root) { 17 | preOrder(root); 18 | vector res; 19 | for(auto k : cnt) 20 | if(k.second == mx) 21 | res.push_back(k.first); 22 | return res; 23 | } 24 | 25 | int preOrder(TreeNode* root) { 26 | if(root == nullptr) return 0; 27 | int l = preOrder(root->left); 28 | int r = preOrder(root->right); 29 | int f = l + r + root->val; 30 | ++cnt[f]; 31 | mx = max(mx, cnt[f]); 32 | return f; 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 18: Tree Queries/3.Lowest Common Ancestor of a Binary Tree.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * struct TreeNode { 4 | * int val; 5 | * TreeNode *left; 6 | * TreeNode *right; 7 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 | * }; 9 | */ 10 | class Solution { 11 | public: 12 | TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { 13 | if(root == p || root == q || root == nullptr) 14 | return root; 15 | TreeNode* l = lowestCommonAncestor(root->left, p, q); 16 | TreeNode* r = lowestCommonAncestor(root->right, p, q); 17 | return l == nullptr ? r : (r == nullptr ? l : root); 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 27: Square Root Algorithms/README.md: -------------------------------------------------------------------------------- 1 | # Square Root Algorithms 2 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 28: Segment Trees Revisited/README.md: -------------------------------------------------------------------------------- 1 | # Segment Trees Revisited 2 | ```c++ 3 | int sum(int a, int b, int k, int x, int y) { 4 | if (b < x || a > y) return 0; 5 | if (a <= x && y <= b) return tree[k]; 6 | int d = (x + y) / 2; 7 | return sum(a, b, 2*k, x, d) + sum(a, b, 2*k+1, d+1, y); 8 | } 9 | ``` 10 | -------------------------------------------------------------------------------- /Competitive Programmer’s Handbook/Chapter 30: Sweep Line Algorithms/README.md: -------------------------------------------------------------------------------- 1 | # Sweep Line Algorithms 2 | -------------------------------------------------------------------------------- /Facebook Interviews/020. Valid Parentheses.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 使用栈(stack)来解决此题,否则会很难想。。。 3 | */ 4 | class Solution { 5 | public: 6 | bool isValid(string s) { 7 | stack stk; 8 | map mm = {{')', '('}, {']', '['}, {'}', '{'}}; 9 | for(auto c : s) { 10 | if(c == '(' || c == '[' || c == '{') 11 | stk.push(c); 12 | else { 13 | if(!stk.empty() && mm[c] == stk.top()) 14 | stk.pop(); 15 | else 16 | return false; 17 | } 18 | } 19 | return stk.empty(); 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /Facebook Interviews/033. Search in Rotated Sorted Array.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 用两次二分搜索: 3 | 第一次用来找翻转有序数组的中轴点(值最小的点)的下标 4 | 第二次则直接在有序数组中搜索target 5 | */ 6 | 7 | class Solution { 8 | public: 9 | int search(vector& nums, int target) { 10 | int n = nums.size(); 11 | if(n == 0) 12 | return -1; 13 | int lo = 0, hi = n - 1; 14 | // 第一次二分搜索 15 | while(lo < hi) { 16 | int mid = lo + (hi - lo) / 2; 17 | 18 | if(nums[mid] < nums[hi]) 19 | hi = mid; 20 | else 21 | lo = mid + 1; 22 | } 23 | // cout << lo << endl; 24 | // 第二次二分搜索 25 | if(target <= nums[n-1]) 26 | return binarySearch(nums, target, lo, n - 1); 27 | else 28 | return binarySearch(nums, target, 0, lo - 1); 29 | } 30 | 31 | int binarySearch(vector& nums, int target, int lo, int hi) { 32 | while(lo <= hi) { 33 | int mid = lo + (hi - lo) / 2; 34 | if(nums[lo] == target) return lo; 35 | if(nums[hi] == target) return hi; 36 | if(nums[mid] == target) return mid; 37 | 38 | if(nums[mid] < target) 39 | lo = mid + 1; 40 | else 41 | hi = mid - 1; 42 | } 43 | return nums[lo] == target ? lo : -1; 44 | } 45 | }; 46 | -------------------------------------------------------------------------------- /Facebook Interviews/050. Pow(x, n).cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | double myPow(double x, int n) { 4 | if(n == 0) return 1; 5 | int sign = n < 0 ? -1 : 1; 6 | long m = long(n) * sign; 7 | double res = 1.0; 8 | while(m) { 9 | if(m % 2 == 1) 10 | res *= x; 11 | x *= x; 12 | m /= 2; 13 | } 14 | return sign == 1 ? res : double(1 / res); 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /Facebook Interviews/053. Maximum Subarray.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int maxSubArray(vector& nums) { 4 | // use divide and conquer 5 | return divCon(nums, 0, nums.size() - 1); 6 | } 7 | 8 | int divCon(vector& nums, int l, int r) { 9 | if(l > r) 10 | return INT_MIN; 11 | int m = l + (r - l) / 2; 12 | int lmax = divCon(nums, l, m - 1); 13 | int rmax = divCon(nums, m + 1, r); 14 | int ml = 0, mr = 0; 15 | for(int i = m - 1, sum = 0; i >= l; --i) { 16 | sum += nums[i]; 17 | ml = max(ml, sum); 18 | } 19 | for(int i = m + 1, sum = 0; i <= r; ++i) { 20 | sum += nums[i]; 21 | mr = max(mr, sum); 22 | } 23 | return max(max(lmax, rmax), ml + mr + nums[m]); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /Facebook Interviews/056. Merge Intervals.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector> merge(vector>& intervals) { 4 | vector> res; 5 | if(intervals.size() == 0 || intervals[0].size() == 0) 6 | return res; 7 | sort(intervals.begin(), intervals.end()); 8 | vector tmp = intervals[0]; 9 | for(int i = 1; i < intervals.size(); ++i) { 10 | if(intervals[i][0] <= tmp[1] && intervals[i][1] >= tmp[0]) { 11 | tmp[0] = min(intervals[i][0], tmp[0]); 12 | tmp[1] = max(intervals[i][1], tmp[1]); 13 | } 14 | else { 15 | res.push_back(tmp); 16 | tmp = intervals[i]; 17 | } 18 | } 19 | res.push_back(tmp); 20 | return res; 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /Facebook Interviews/057. Insert Interval.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector> insert(vector>& intervals, vector& newInterval) { 4 | vector> res; 5 | vector tmp; 6 | int i = 0; 7 | while(i < intervals.size() && intervals[i][1] < newInterval[0]) { 8 | res.push_back(intervals[i++]); 9 | } 10 | tmp = newInterval; 11 | for(; i < intervals.size(); ++i) { 12 | if(tmp[0] <= intervals[i][1] && tmp[1] >= intervals[i][0]) { 13 | tmp[0] = min(tmp[0], intervals[i][0]); 14 | tmp[1] = max(tmp[1], intervals[i][1]); 15 | } 16 | else { 17 | res.push_back(tmp); 18 | tmp = intervals[i]; 19 | } 20 | } 21 | res.push_back(tmp); 22 | return res; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /Facebook Interviews/124. Binary Tree Maximum Path Sum.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * struct TreeNode { 4 | * int val; 5 | * TreeNode *left; 6 | * TreeNode *right; 7 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 8 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 9 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 10 | * }; 11 | */ 12 | class Solution { 13 | public: 14 | int mxSum = INT_MIN; 15 | int maxPathSum(TreeNode* root) { 16 | dfs(root); 17 | return mxSum; 18 | } 19 | 20 | int dfs(TreeNode* root) { 21 | if(root == nullptr) 22 | return 0; 23 | int l = dfs(root->left); l = max(l, 0); 24 | int r = dfs(root->right); r = max(r, 0); 25 | mxSum = max(mxSum, root->val + l + r); 26 | return root->val + max(l, r); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /Facebook Interviews/1249. Minimum Remove to Make Valid Parentheses.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | string minRemoveToMakeValid(string s) { 4 | stack stk; 5 | for(int i = 0; i < s.length(); ++i) { 6 | if(s[i] == '(') 7 | stk.push(i); 8 | else if(s[i] == ')') { 9 | if(stk.empty() || s[stk.top()] == ')') 10 | stk.push(i); 11 | else 12 | stk.pop(); 13 | } 14 | } 15 | while(!stk.empty()) { 16 | s[stk.top()] = '*'; 17 | stk.pop(); 18 | } 19 | // Note: Erase–remove idiom 20 | s.erase(remove(s.begin(), s.end(), '*'), s.end()); 21 | return s; 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /Facebook Interviews/253. Meeting Rooms II.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int minMeetingRooms(vector>& intervals) { 4 | map m; 5 | for (auto a : intervals) { 6 | ++m[a[0]]; 7 | --m[a[1]]; 8 | } 9 | int rooms = 0, res = 0; 10 | for (auto it : m) { 11 | res = max(res, rooms += it.second); 12 | } 13 | return res; 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /Facebook Interviews/560. Subarray Sum Equals K.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int subarraySum(vector& nums, int k) { 4 | int sum = 0, res = 0; 5 | unordered_map mp; mp[0] = 1; 6 | for(auto n : nums) { 7 | sum += n; 8 | if(mp.count(sum - k) != 0) 9 | res += mp[sum - k]; 10 | ++mp[sum]; 11 | } 12 | return res; 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /Facebook Interviews/621. Task Scheduler.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int leastInterval(vector& tasks, int n) { 4 | unordered_map mp; 5 | int count = 0; 6 | for(auto e : tasks) { 7 | mp[e]++; 8 | count = max(count, mp[e]); 9 | } 10 | int ans = (count-1)*(n+1); 11 | for(auto e : mp) 12 | if(e.second == count) 13 | ans++; 14 | return max((int)tasks.size(), ans); 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /Facebook Interviews/785. Is Graph Bipartite?.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | bool isBipartite(vector>& graph) { 4 | int n = graph.size(); 5 | int coloring[n]; 6 | for(int i = 0; i < n; ++i) { 7 | memset(coloring, -1, sizeof(coloring)); 8 | if(!dfs(graph, coloring, i, 1)) 9 | return false; 10 | } 11 | return true; 12 | } 13 | 14 | bool dfs(vector>& graph, int coloring[], int pos, int color) { 15 | if(coloring[pos] != -1 && coloring[pos] != color) 16 | return false; 17 | coloring[pos] = color; 18 | for(auto v : graph[pos]) { 19 | if((coloring[v] == -1 && !dfs(graph, coloring, v, 1 - color)) || (coloring[v] != -1 && coloring[v] != 1 - color)) 20 | return false; 21 | } 22 | return true; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /Facebook Interviews/986. Interval List Intersections.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector> intervalIntersection(vector>& A, vector>& B) { 4 | vector> res; 5 | int i = 0, j = 0; 6 | while(i < A.size() && j < B.size()) { 7 | if(A[i][0] <= B[j][1] && A[i][1] >= B[j][0]) { 8 | res.push_back({max(A[i][0], B[j][0]), min(A[i][1], B[j][1])}); 9 | } 10 | if(A[i][1] < B[j][1]) 11 | ++i; 12 | else 13 | ++j; 14 | } 15 | return res; 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /Facebook Interviews/README.md: -------------------------------------------------------------------------------- 1 | ## LeetCode上面的Facebook面试题集合 2 | [[Facebook interview experiences - All Combined from LC](https://leetcode.com/discuss/general-discussion/675445/facebook-interview-experiences-all-combined-from-lc-till-date-07-jun-2020)] | [[Non-Premium Version](https://leetcode.com/list/xyvbjku7/)] 3 | -------------------------------------------------------------------------------- /Google Kick Start/2016/README.md: -------------------------------------------------------------------------------- 1 | ## Google Kick Start 2016 2 | -------------------------------------------------------------------------------- /Google Kick Start/2016/Round A/Problem A: Country Leader.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | int T; 6 | cin >> T; 7 | for(int ca = 1; ca <= T; ++ca) { 8 | int n; 9 | cin >> n; 10 | 11 | string tarStr; 12 | string str; 13 | getline(cin, str); 14 | int cnt = 0; 15 | vector nums(27, 0); 16 | for(int i = 0; i < n; ++i) { 17 | getline(cin, str); 18 | for(auto c : str) { 19 | if(c != ' ' && nums[c - 'A'] == 0) { 20 | nums[c - 'A'] = 1; 21 | ++nums[26]; 22 | } 23 | } 24 | if(nums[26] > cnt || (nums[26] == cnt && str < tarStr)) { 25 | tarStr = str; 26 | cnt = nums[26]; 27 | } 28 | fill(nums.begin(), nums.end(), 0); 29 | } 30 | cout << "Case #" << ca << ": " << tarStr << endl; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Google Kick Start/2016/Round A/README.md: -------------------------------------------------------------------------------- 1 | ## Google Kick Start 2016 - Round A 2 | * Problem A: Country Leader 3 | * Problem B: Rain 4 | * Problem C: Jane's Flower Shop 5 | * Problem D: Clash Royale 6 | -------------------------------------------------------------------------------- /Google Kick Start/README.md: -------------------------------------------------------------------------------- 1 | ## Google Kick Start Coding Competition 2 | [Official Website](https://codingcompetitions.withgoogle.com/kickstart) 3 | -------------------------------------------------------------------------------- /LeetCode-Hard系列/76. Minimum Window Substring.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | string minWindow(string s, string t) { 4 | if(s.length() < t.length()) 5 | return ""; 6 | vector mp(128, 0); 7 | int i = 0, j = 0, mi = INT_MAX, start = 0; 8 | 9 | for(auto& c : t) ++mp[c]; 10 | 11 | int cnt = t.length(); 12 | 13 | while(j < s.length()) { 14 | if(mp[s[j++]]-- > 0) --cnt; 15 | while(cnt <= 0) { 16 | if(j - i < mi) 17 | mi = j - i, start = i; 18 | if(mp[s[i++]]++ == 0) 19 | ++cnt; 20 | } 21 | } 22 | return mi == INT_MAX ? "" : s.substr(start, mi); 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /LeetCode-Hard系列/README.md: -------------------------------------------------------------------------------- 1 | # LeetCode 题目集锦 2 | 3 | ## Geeksforgeeks 4 | |题号|二刷耗时|三刷耗时| 5 | |:---:|:---:|:---:| 6 | |居左测试文本|居中测试文本|居右测试文本| 7 | 8 | 9 | 10 | 11 | ## Hard 12 | |题号|二刷耗时|三刷耗时| 13 | |:---:|:---:|:---:| 14 | |居左测试文本|居中测试文本|居右测试文本| 15 | 16 | 17 | 18 | 19 | ## Medium 20 | |题号|二刷耗时|三刷耗时| 21 | |:---:|:---:|:---:| 22 | |居左测试文本|居中测试文本|居右测试文本| 23 | 24 | 25 | 26 | ## Easy 27 | |题号|二刷耗时|三刷耗时| 28 | |:---:|:---:|:---:| 29 | |居左测试文本|居中测试文本|居右测试文本| 30 | -------------------------------------------------------------------------------- /Sort Algorithms/HeapSort.cpp: -------------------------------------------------------------------------------- 1 | void heapify(vector& points, int i, int len) { 2 | // min-heap sort 最小堆 3 | int tmp = points[i]; // i:父节点 4 | int left = 2 * i + 1; // 左子节点 5 | while(left < len) { // 若子节点在范围内 6 | if(left + 1 < len && points[left] > points[left + 1]) // 比较两个子节点的大小,选择最小的 7 | ++left; 8 | if(tmp > points[left]) { // 因为是最小堆,若父节点大于子节点:交换父子节点内容,继续子节点和孙节点比较 9 | points[i] = points[left]; 10 | i = left; 11 | left = 2 * i + 1; 12 | } 13 | else // 调整完成 14 | break; 15 | } 16 | points[i] = tmp; 17 | } 18 | 19 | void heapSort(vector& points) { 20 | int n = points.size(); 21 | // 第一步:将数组堆化,i从最后一个父节点开始调整 22 | for(int i = n / 2 - 1; i >= 0; --i) 23 | heapify(points, i, n); 24 | // 第二步:对堆化数据排序 25 | while(n > 0) { 26 | // 每次都是移出最顶层的根节点A[0],与最尾部节点位置调换,同时遍历长度 -1 27 | swap(points[0], points[n - 1]); 28 | // 然后重新整理被换到根节点的末尾元素,使其符合堆的特性 29 | heapify(points, 0, --n); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Sort Algorithms/MergeSort.cpp: -------------------------------------------------------------------------------- 1 | void merge(vector& nums, int l, int m, int h) { 2 | int i, j, k; 3 | int n1 = m - l + 1; 4 | int n2 = h - m; 5 | 6 | int tmp1[n1], tmp2[n2]; 7 | 8 | for(i = 0; i < n1; ++i) 9 | tmp1[i] = nums[l + i]; 10 | for(j = 0; j < n2; ++j) 11 | tmp2[j] = nums[m + 1 + j]; 12 | 13 | i = 0; 14 | j = 0; 15 | k = l; 16 | 17 | while(i < n1 && j < n2) { 18 | if(tmp1[i] < tmp2[j]) { 19 | nums[k] = tmp1[i]; 20 | ++i; 21 | } 22 | else { 23 | nums[k] = tmp2[j]; 24 | ++j; 25 | } 26 | ++k; 27 | } 28 | 29 | while(i < n1) { 30 | nums[k] = tmp1[i]; 31 | ++i; 32 | ++k; 33 | } 34 | 35 | while(j < n2) { 36 | nums[k] = tmp2[j]; 37 | ++j; 38 | ++k; 39 | } 40 | } 41 | 42 | void mergeSort(vector& nums, int low, int high) { 43 | if(low < high) { 44 | int mid = low + (high - low) / 2; 45 | mergeSort(nums, low, mid); 46 | mergeSort(nums, mid + 1, high); 47 | 48 | merge(nums, low, mid, high); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Sort Algorithms/QuickSort.cpp: -------------------------------------------------------------------------------- 1 | void quickSort(vector& nums, int low, int high) { 2 | if(low < high) { 3 | int l = low; 4 | int h = high; 5 | int pivot = nums[l]; 6 | 7 | while(l < h) { 8 | while (l < h && nums[h] >= pivot) 9 | --h; 10 | nums[l] = nums[h]; 11 | while (l < h && nums[l] <= pivot) 12 | ++l; 13 | nums[h] = nums[l]; 14 | } 15 | 16 | nums[l] = pivot; 17 | 18 | quickSort(nums, low, l-1); 19 | quickSort(nums, l+1, high); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Sort Algorithms/README.md: -------------------------------------------------------------------------------- 1 | ## 排序算法 2 | * 堆排序(最大堆,最小堆) 3 | * 归并排序(先拆,再归) 4 | * 快速排序(用基准划分数组) 5 | -------------------------------------------------------------------------------- /Week01-基础(C++ Basics)/README.md: -------------------------------------------------------------------------------- 1 | # 一些基础 2 | **裕哥:** 3 | * 首先,评测机有一系列数据std流,我们用`cin`(c++)或者`input`(python)来获取这个流中的数据,然后经过我们的处理,使用`cout`(c++)或者`print`(python)给评测机看我们的数据处理结果,若评测机认为你的处理正确,即完成了这题。 4 | * 单独使用`cin`对数据流输入是不够的,大家再试着看看`getline`的用法,同时注意`getline`和`cin`对换行符的不同处理。 5 | * 了解`freopen`的用法,了解这个函数是为了让你可以本地模拟评测机环境,我们建立一个`input.txt`然后用`freopen`导入`txt`中的数据给程序。 6 | 7 | **\[To learn C++: [Fast C++](https://github.com/Huixxi/Fast-C-plus-plus)\]** 8 | 9 | **习题:** 10 | * **[**[UVa1585:Score](https://vjudge.net/problem/UVA-1585)**]** **[**[Solution(C++)][1]**]** 11 | 12 | [1]: https://github.com/Huixxi/Algorithm-with-Cplusplus/blob/master/Week01-%E5%9F%BA%E7%A1%80/UVa1585_Score.cpp 13 | 14 | -------------------------------------------------------------------------------- /Week01-基础(C++ Basics)/UVa1585_Score.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | int n; 6 | cin >> n; 7 | cin.ignore(); 8 | string oxstr; 9 | while(n--) { 10 | getline(cin, oxstr); 11 | int total_score = 0, score = 0; 12 | for(char c : oxstr) { 13 | if(tolower(c) == 'o'){ 14 | score += 1; 15 | total_score += score; 16 | } 17 | else { 18 | score = 0; 19 | } 20 | } 21 | cout << total_score << endl; 22 | } 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /Week02-数组(Array)/README.md: -------------------------------------------------------------------------------- 1 | # 关于数组 2 | 熟练使用数组。 3 | Read more about array: [C++ Notes](https://github.com/Huixxi/Fast-C-plus-plus/blob/master/Part%20I%20The%20Basics/04%20Lesson4%20Notes.md) 4 | 5 | **习题:** 6 | * **[**[UVa1586:Molar mass](https://vjudge.net/problem/UVA-1586)**]** **[**[Solution(C++)][1]**]** 7 | * **[**[UVa1225:Digit Counting](https://vjudge.net/problem/UVA-1225)**]** **[**[Solution(C++)][2]**]** 8 | * **[**[UVa232:Crossword Answers](https://vjudge.net/problem/UVA-232)**]** **[**[Solution(C++)][3]**]** 9 | * **[**[UVa1588:Kickdown](https://vjudge.net/problem/UVA-1588)**]** **[**[Solution(C++)][4]**]** 10 | 11 | [1]: https://github.com/Huixxi/Algorithm-with-Cplusplus/blob/master/Week02-%E6%95%B0%E7%BB%84/UVa1586_Molar%20mass.cpp 12 | [2]: https://github.com/Huixxi/Algorithm-with-Cplusplus/blob/master/Week02-%E6%95%B0%E7%BB%84/UVa1225_Digit%20Counting.cpp 13 | [3]: https://github.com/Huixxi/Algorithm-with-Cplusplus/blob/master/Week02-%E6%95%B0%E7%BB%84/UVa232_Crossword%20Answers.cpp 14 | [4]: https://github.com/Huixxi/Algorithm-with-Cplusplus/blob/master/Week02-%E6%95%B0%E7%BB%84/Uva1588_Kickdown.cpp 15 | 16 | -------------------------------------------------------------------------------- /Week02-数组(Array)/UVa1225_Digit Counting.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | int t, n, j; 6 | cin >> t; 7 | while(t--) { 8 | cin >> n; 9 | int digits[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 10 | for(int i = 1; i <= n; ++i) { 11 | j = i; 12 | while(j >= 10) { 13 | ++digits[j%10]; 14 | j /= 10; 15 | } 16 | ++digits[j]; 17 | } 18 | for(int k = 0; k < 9; ++k) { 19 | cout << digits[k] << " "; 20 | } 21 | cout << digits[9] << endl; 22 | } 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /Week02-数组(Array)/UVa1586_Molar mass.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | map atom_mass = {{'C', 12.01}, {'H', 1.008}, {'O', 16.00}, {'N', 14.01}}; 5 | 6 | int main() { 7 | int n; 8 | cin >> n; 9 | cin.ignore(); 10 | string molecule; 11 | while(n--) { 12 | getline(cin, molecule); 13 | stringstream ss; 14 | ss << molecule; 15 | 16 | char atom; 17 | int num; 18 | float sum = 0.0; 19 | 20 | while(!ss.eof()) { 21 | ss >> atom; 22 | if(ss.eof()) 23 | break; 24 | if(!(ss >> num)) { 25 | sum += atom_mass[atom]; 26 | ss.clear(); 27 | } 28 | else { 29 | sum += num * atom_mass[atom]; 30 | } 31 | } 32 | cout << setprecision(3) << fixed; 33 | cout << sum << endl; 34 | } 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /Week02-数组(Array)/Uva1588_Kickdown.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | string s1, s2; 6 | while(cin >> s1 >> s2) { 7 | int l1 = s1.length(), l2 = s2.length(); 8 | int l = l1 + l2; 9 | /* 太尼玛难想了,艹!!! 10 | <-- i 11 | l1_ _ _0_ _ _ _-l2+1_____ (s1) 12 | (s2) 0_______l2-1 13 | j --> 14 | */ 15 | for(int i = -l2+1; i <= l1; ++i) { 16 | int flag = 0; 17 | for(int j = 0; j < l2; ++j) { 18 | if(i + j >= 0 && i + j < l1) { 19 | if((s1[i + j] - '0') + (s2[j] - '0') > 3) { 20 | flag = 1; 21 | break; 22 | } 23 | } 24 | } 25 | if(!flag) { 26 | l = min(l, max(l1, i + l2) - min(i, 0)); 27 | } 28 | } 29 | cout << l << endl; 30 | } 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /Week03-递归(Recursion)/README.md: -------------------------------------------------------------------------------- 1 | # 递归 2 | 最经典的应属“汉诺塔问题”了。 3 | 4 | **习题:** 5 | * **[**[UVa201:Squares](https://vjudge.net/problem/UVA-201)**]** **[**[Solution(C++)][1]**]** 6 | * **[**[UVa220:Othello](https://vjudge.net/problem/UVA-220)**]** **[**[Solution(C++)][1]**]** 7 | * **[**[UVa253:Cube painting](https://vjudge.net/problem/UVA-253)**]** **[**[Solution(C++)][1]**]** 8 | * **[**[UVa12108:Extraordinarily Tired Students](https://vjudge.net/problem/UVA-12108)**]** **[**[Solution(C++)][1]**]** 9 | 10 | [1]: https://github.com/Huixxi/Algorithm-with-Cplusplus/blob/master/Week01-%E5%9F%BA%E7%A1%80/UVa1585_Score.cpp 11 | -------------------------------------------------------------------------------- /Week04-STL(C++ STL)/README.md: -------------------------------------------------------------------------------- 1 | # 关于STL 2 | 熟练使用STL。 3 | Read more about STL: 4 | * [Learning the Standard Template Library (STL)](https://github.com/Huixxi/Fast-C-plus-plus/tree/master/Part%20III%20Learning%20the%20STL) 5 | * [More STL](https://github.com/Huixxi/Fast-C-plus-plus/tree/master/Part%20IV%20More%20STL) 6 | * [STL Source Code](https://github.com/microsoft/STL) 7 | 8 | **习题:** 9 | * **[**[UVa540:Team Queue](https://vjudge.net/problem/UVA-540)**]** **[**[Solution(C++)][1]**]** 10 | * **[**[UVa1592:Database](https://vjudge.net/problem/UVA-1592)**]** **[**[Solution(C++)][1]**]** 11 | * **[**[UVa207:PGA Tour Prize Money](https://vjudge.net/problem/UVA-207)**]** **[**[Solution(C++)][1]**]** 12 | 13 | [1]: lal.com 14 | -------------------------------------------------------------------------------- /Week04-STL(C++ STL)/STL_Queue.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int main(){ 6 | queue q; // FIFO(fast in first out) 7 | for(int i = 0; i < 10; ++i) 8 | q.push(i); 9 | while(!q.empty()){ 10 | int no = q.front(); 11 | q.pop(); 12 | cout << no << endl; 13 | } 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /Week04-STL(C++ STL)/STL_Stack.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int main(){ 6 | stack sta; // LIFO(last in first out) 7 | for(int i = 0; i < 10; ++i) 8 | sta.push(i); 9 | while(!sta.empty()){ 10 | int no = sta.top(); 11 | sta.pop(); 12 | cout << no << endl; 13 | } 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /Week05-并查集(Union-Find)/README.md: -------------------------------------------------------------------------------- 1 | # 并查集 2 | 3 | **习题:** 4 | * **[**[UVa793:Network Connections](https://vjudge.net/problem/UVA-793)**]** **[**[Solution(C++)][1]**]** 5 | * **[**[UVa10507:Waking up brain](https://vjudge.net/problem/UVA-10507)**]** **[**[Solution(C++)][1]**]** 6 | * **[**[UVa10227:Forests](https://vjudge.net/problem/UVA-10227)**]** **[**[Solution(C++)][1]**]** 7 | * **[**[UVa10158:War](https://vjudge.net/problem/UVA-10158)**]** **[**[Solution(C++)][1]**]** 8 | 9 | [1]: https://github.com/Huixxi/Algorithm-with-Cplusplus/blob/master/Week01-%E5%9F%BA%E7%A1%80/UVa1585_Score.cpp 10 | -------------------------------------------------------------------------------- /Week07-BFS&DFS(Graph)/README.md: -------------------------------------------------------------------------------- 1 | # BFS&DFS 2 | 有关图的遍历,拓扑排序,偶图判定,连通分量数判定等。 3 | 4 | Practice More: [Graph Problems For Practice](https://leetcode.com/discuss/general-discussion/655708/graph-for-beginners-problems-pattern-sample-solutions/562734) 5 | 6 | **习题:** 7 | * **[**[UVa11831:Sticker Collector Robot](https://vjudge.net/problem/UVA-11831)**]** **[**[Solution(C++)][1]**]** 8 | * **[**[UVa352:The Seasonal War](https://vjudge.net/problem/UVA-352)**]** **[**[Solution(C++)][1]**]** 9 | * **[**[UVa11060:Beverages](https://vjudge.net/problem/UVA-11060)**]** **[**[Solution(C++)][1]**]** 10 | * **[**[UVa11080:Place the Guards](https://vjudge.net/problem/UVA-11080)**]** **[**[Solution(C++)][1]**]** 11 | * **[**[UVa758:The Same Game](https://vjudge.net/problem/UVA-758)**]** **[**[Solution(C++)][1]**]** 12 | 13 | [1]: https://github.com/Huixxi/Algorithm-with-Cplusplus/blob/master/Week01-%E5%9F%BA%E7%A1%80/UVa1585_Score.cpp 14 | -------------------------------------------------------------------------------- /Week08-割点&桥(Cut-Vertex&Bridge)/README.md: -------------------------------------------------------------------------------- 1 | # 割点和桥 2 | 3 | **习题:** 4 | * **[**[UVa315:Network](https://vjudge.net/problem/UVA-315)**]** **[**[Solution(C++)][1]**]** 5 | * **[**[UVa796:Critical Links](https://vjudge.net/problem/UVA-796)**]** **[**[Solution(C++)][1]**]** 6 | * **[**[UVa10765:Doves and bombs](https://vjudge.net/problem/UVA-10765)**]** **[**[Solution(C++)][1]**]** 7 | 8 | [1]: https://github.com/Huixxi/Algorithm-with-Cplusplus/blob/master/Week01-%E5%9F%BA%E7%A1%80/UVa1585_Score.cpp 9 | -------------------------------------------------------------------------------- /Week09-暴力&贪心(Brute-Force&Greedy)/README.md: -------------------------------------------------------------------------------- 1 | # 暴力算法和贪心算法 2 | 3 | 4 | Practice More: [Greedy for Beginners](https://leetcode.com/discuss/general-discussion/669996/greedy-for-beginners-problems-sample-solutions) 5 | 6 | **习题(暴力):** 7 | * **[**[UVa10487:Closest Sums](https://vjudge.net/problem/UVA-10487)**]** **[**[Solution(C++)][1]**]** 8 | * **[**[UVa750:8 Queens Chess Problem](https://vjudge.net/problem/UVA-750)**]** **[**[Solution(C++)][1]**]** 9 | * **[**[UVa735:Dart-a-Mania](https://vjudge.net/problem/UVA-735)**]** **[**[Solution(C++)][1]**]** 10 | * **[**[UVa11236:Grocery store](https://vjudge.net/problem/UVA-11236)**]** **[**[Solution(C++)][1]**]** 11 | * **[**[UVa11553:Grid Game](https://vjudge.net/problem/UVA-11553)**]** **[**[Solution(C++)][1]**]** 12 | 13 | **习题(贪心):** 14 | * **[**[UVa12405:Scarecrow](https://vjudge.net/problem/UVA-12405)**]** **[**[Solution(C++)][1]**]** 15 | * **[**[UVa11292:Dragon of Loowater ](https://vjudge.net/problem/UVA-11292)**]** **[**[Solution(C++)][1]**]** 16 | * **[**[UVa10718:Bit Mask](https://vjudge.net/problem/UVA-10718)**]** **[**[Solution(C++)][1]**]** 17 | 18 | [1]: https://github.com/Huixxi/Algorithm-with-Cplusplus/blob/master/Week01-%E5%9F%BA%E7%A1%80/UVa1585_Score.cpp 19 | -------------------------------------------------------------------------------- /Week10-暴力&贪心2(Brute-Force&Greedy2)/README.md: -------------------------------------------------------------------------------- 1 | # 暴力算法和贪心算法2 2 | 3 | **习题:** 4 | * **[**[UVa1260:Sales](https://vjudge.net/problem/UVA-1260)**]** **[**[Solution(C++)][1]**]** 5 | * **[**[UVa416:LED Test](https://vjudge.net/problem/UVA-416)**]** **[**[Solution(C++)][1]**]** 6 | * **[**[UVa11157:Dynamic Frog ](https://vjudge.net/problem/UVA-11157)**]** **[**[Solution(C++)][1]**]** 7 | 8 | [1]: https://github.com/Huixxi/Algorithm-with-Cplusplus/blob/master/Week01-%E5%9F%BA%E7%A1%80/UVa1585_Score.cpp 9 | -------------------------------------------------------------------------------- /Week11-动态规划(Dynamic Programming)/UVa10684_The Jackpot.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | int n; 6 | while(cin >> n && n != 0) { 7 | int sum = 0, cur = 0, mx = 0; 8 | while (n--) { 9 | cin >> cur; 10 | sum += cur; 11 | mx = max(sum, mx); 12 | if(sum < 0) 13 | sum = 0; 14 | } 15 | if (mx > 0) 16 | cout << "The maximum winning streak is " << mx << ".\n"; 17 | else 18 | cout << "Losing streak.\n"; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Week13-TSP旅行商&区间DP/UVa10496_Collecting Beepers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int N; 5 | int dp[1<<11][11]; // space complexity: 2^n * n 6 | int dist[11][11]; // distance between each points pair 7 | int ans; 8 | struct coords { 9 | int x, y; 10 | } xy[11]; 11 | 12 | void TSP(int s, int i, int s_size) { 13 | // s_size = 0, 1, 2, ..., n 14 | if(s_size == N) { 15 | ans = min(dp[s][i] + dist[i][0], ans); 16 | return; 17 | } 18 | for(int j = 1; j <= N; ++j) { // 只走除0点以外的点 19 | if(!(s & (1 << j))) { 20 | // ss = s + {j}, bottom-up 21 | int ss = s | (1 << j); 22 | if(!dp[ss][j] || dp[s][i] + dist[i][j] < dp[ss][j]) { 23 | dp[ss][j] = dp[s][i] + dist[i][j]; 24 | TSP(ss, j, s_size+1); 25 | } 26 | } 27 | } 28 | } 29 | 30 | int main(){ 31 | int T, X, Y; 32 | cin >> T; 33 | while(T--) { 34 | cin >> X >> Y >> xy[0].x >> xy[0].y >> N; // N <= 10 35 | for(int i = 1; i <= N; ++i) { 36 | cin >> xy[i].x >> xy[i].y; 37 | } 38 | for(int i = 0; i < N; ++i) { 39 | for(int j = i+1; j <= N; ++j) { 40 | dist[i][j] = abs(xy[i].x - xy[j].x) + abs(xy[i].y - xy[j].y); 41 | dist[j][i] = dist[i][j]; 42 | } 43 | } 44 | ans = int(1e9); 45 | TSP(0, 0, 0); 46 | cout << "The shortest path has length " << ans << endl; 47 | } 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /Week13-TSP旅行商&区间DP/UVa10721_Bar Codes.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | long long dp[55][55]; // dp[i][j]: use i bars to compose j units 5 | 6 | int main(){ 7 | int n, k, m; 8 | while(cin >> n >> k >> m) { 9 | memset(dp, 0, sizeof(dp)); 10 | dp[0][0] = 1; 11 | for(int i = 1; i <= k; ++i) 12 | for(int j = 1; j <= n; ++j) 13 | for(int t = 1; t <= m && t <= j; ++t) 14 | dp[i][j] += dp[i-1][j-t]; 15 | cout << dp[k][n] << endl; 16 | } 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /Week13-TSP旅行商&区间DP/UVa10943_How do you add?.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define MODN 1000000 4 | 5 | int dp[101][101]; // dp[k][n] 6 | 7 | int main() { 8 | for(int k = 1; k <= 100; ++k) { 9 | dp[k][0] = 1; 10 | for(int n = 1; n <= 100; ++n) { 11 | dp[k][n] = (dp[k-1][n] + dp[k][n-1]) % MODN; 12 | } 13 | } 14 | int N, K; 15 | while(cin >> N >> K && N + K) { 16 | cout << dp[K][N] << endl; 17 | } 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /Week13-TSP旅行商&区间DP/Uva1261_String Popping.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | map mm; 5 | 6 | int dfs(string& s) { 7 | if(s == "") 8 | return 1; 9 | if(s.length() == 1) 10 | return 0; 11 | auto it = mm.find(s); 12 | if(it != mm.end()) 13 | return it->second; 14 | string sub; 15 | int i, j; 16 | int& res = mm[s]; 17 | for(i = 0; i < s.length(); ++i) { 18 | for(j = i; j < s.length(); ++j) { 19 | if(s[i] != s[j]) 20 | break; 21 | } 22 | if(j >= i + 2) { 23 | sub = s.substr(0, i) + s.substr(j); 24 | res |= dfs(sub); 25 | if(res) 26 | return res; 27 | i = j - 1; 28 | } 29 | } 30 | return res; 31 | } 32 | 33 | int main() { 34 | int n; 35 | cin >> n; 36 | string s; 37 | while(n--) { 38 | cin >> s; 39 | cout << dfs(s) << endl; 40 | } 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /Week14-基础数论(Basic Number Theory)/UVa10007_Count the Trees.py: -------------------------------------------------------------------------------- 1 | # Consider that 300! is too large to store in C++, which will make the code too complex, I use python this time. 2 | # a[n] = a[0]*a[n-1] + a[1]*a[n-2] + ... + a[n-1]*a[0] 3 | 4 | import math 5 | 6 | start = 0 7 | a = [0] * 300 8 | a[0] = 1 9 | while True: 10 | n = int(input()) 11 | if n == 0: 12 | break 13 | 14 | if a[n] != 0: 15 | print(a[n] * math.factorial(n)) 16 | 17 | else: 18 | for i in range(start+1, n+1): 19 | for j in range(i): 20 | a[i] += a[j] * a[i-j-1] 21 | start = n 22 | print(a[n] * math.factorial(n)) 23 | 24 | 25 | -------------------------------------------------------------------------------- /Week14-基础数论(Basic Number Theory)/UVa948_Fibonaccimal Base.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // find the nearest fib num 5 | int find_fib_leq_n(int n, vector& ids, int* id) { 6 | int f0 = 0, f1 = 1; 7 | int f; 8 | while(true) { 9 | f = f0 + f1; 10 | if(n < f) 11 | break; 12 | f0 = f1; 13 | f1 = f; 14 | ++(*id); 15 | } 16 | ids.push_back(*id); 17 | return f1; 18 | } 19 | 20 | void Fibonaccimal_Base_Uva948(int n, vector& ids, int id = 0) { 21 | int f = find_fib_leq_n(n, ids, &id); 22 | if(n == f) 23 | return; 24 | Fibonaccimal_Base_Uva948(n-f, ids); 25 | } 26 | 27 | int main() { 28 | int N; 29 | cin >> N; 30 | for(int x = 0; x < N; ++x) { 31 | int n; 32 | cin >> n; 33 | /* -----start----- */ 34 | vector ids; // to save ids where should be 1 35 | Fibonaccimal_Base_Uva948(n, ids); 36 | 37 | int fbits[ids[0]]; 38 | for(auto& i : fbits) { 39 | i = 0; // initialize each element to 0 40 | } 41 | for(auto i : ids) { 42 | fbits[ids[0]-i] = 1; 43 | } 44 | /* -----output----- */ 45 | cout << n << " = "; 46 | for(auto i : fbits) 47 | cout << i; 48 | cout << " (fib)" << endl; 49 | } 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /Week14-基础数论(Basic Number Theory)/UVa991_Safe Salutations.cpp: -------------------------------------------------------------------------------- 1 | // A easy one, just use "Catalan Equation", but can get "Presentation error"输出格式错误, be careful. 2 | 3 | #include 4 | using namespace std; 5 | 6 | int main() { 7 | int n, Case=0; 8 | while(cin >> n) { 9 | int c = 1; 10 | for(int i = 0; i < n; ++i) { 11 | c = (2 * (2*i+1) * c) / (i+2); // be careful, think why not c *= 2*(2*i+1)/(i+2); 12 | } 13 | if(Case++) 14 | cout << endl; 15 | cout << c << endl; 16 | } 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目01-10/01二维数组中的查找.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | bool Find(int target, vector > array) { 4 | int r, c, rows, cols; 5 | rows = array.size(); 6 | cols = array[0].size(); 7 | r = 0; 8 | c = cols - 1; 9 | while(r < rows && c >= 0) { 10 | if(array[r][c] == target) 11 | return true; 12 | if(array[r][c] > target) 13 | --c; 14 | else 15 | ++r; 16 | } 17 | return false; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目01-10/02替换空格.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | void replaceSpace(char *str, int length) { 4 | if (str == nullptr || length <= 0) 5 | return; 6 | int blanknum = 0, origlength = 0; 7 | for(int i = 0; str[i] != '\0'; ++i){ 8 | ++origlength; 9 | if(str[i] == ' ') 10 | ++blanknum; 11 | } 12 | int newlength = origlength + 2 * blanknum; 13 | for(int j = origlength; j >= 0 && j < newlength; --j){ 14 | if(str[j] != ' ') 15 | str[newlength--] = str[j]; 16 | else{ 17 | str[newlength--] = '0'; 18 | str[newlength--] = '2'; 19 | str[newlength--] = '%'; 20 | } 21 | } 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目01-10/03从头到尾打印链表.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * struct ListNode { 3 | * int val; 4 | * struct ListNode *next; 5 | * ListNode(int x) : 6 | * val(x), next(NULL) { 7 | * } 8 | * }; 9 | */ 10 | class Solution { 11 | public: 12 | vector res; 13 | vector printListFromTailToHead(ListNode* head) { 14 | if(head == NULL) 15 | return res; 16 | printListFromTailToHead(head->next); 17 | res.push_back(head->val); 18 | return res; 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目01-10/04重建二叉树.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for binary tree 3 | * struct TreeNode { 4 | * int val; 5 | * TreeNode *left; 6 | * TreeNode *right; 7 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 | * }; 9 | */ 10 | class Solution { 11 | public: 12 | TreeNode* reConstructBinaryTree(vector pre,vector vin) { 13 | TreeNode* root = new TreeNode(pre[0]); 14 | auto it = find(vin.begin(), vin.end(), pre[0]); 15 | int idx = distance(vin.begin(), it); 16 | vector lpre(pre.begin()+1, pre.begin()+idx+1); 17 | vector lvin(vin.begin(), it); 18 | vector rpre(pre.begin()+idx+1, pre.end()); 19 | vector rvin(it+1, vin.end()); 20 | if(vin.begin() != it) 21 | root->left = reConstructBinaryTree(lpre, lvin); 22 | if(it+1 != vin.end()) 23 | root->right = reConstructBinaryTree(rpre, rvin); 24 | return root; 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目01-10/05用两个栈实现队列.cpp: -------------------------------------------------------------------------------- 1 | class Solution 2 | { 3 | public: 4 | void push(int node) { 5 | while(!stack2.empty()) { 6 | stack1.push(stack2.top()); 7 | stack2.pop(); 8 | } 9 | stack1.push(node); 10 | } 11 | 12 | int pop() { 13 | while(!stack1.empty()) { 14 | stack2.push(stack1.top()); 15 | stack1.pop(); 16 | } 17 | int temp = stack2.top(); 18 | stack2.pop(); 19 | return temp; 20 | } 21 | 22 | private: 23 | stack stack1; 24 | stack stack2; 25 | }; 26 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目01-10/06斐波那契数列.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int Fibonacci(int n) { 4 | int a = 0, b = 1, c; 5 | if(n == 0) 6 | return a; 7 | if(n == 1) 8 | return b; 9 | while(n > 1 && n--) { 10 | c = a + b; 11 | a = b; 12 | b = c; 13 | } 14 | return c; 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目01-10/07旋转数组的最小数字.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int minNumberInRotateArray(vector& rotateArray) { 4 | const int n = rotateArray.size(); 5 | int l = 0, r = n - 1, mid = 0; 6 | while(l < r) { 7 | mid = l + (r - l) / 2; 8 | if(rotateArray[mid] < rotateArray[r]) 9 | r = mid; 10 | else 11 | l = mid + 1; 12 | } 13 | return rotateArray[l]; 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目01-10/08跳台阶.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int jumpFloor(int number) { 4 | if(number == 2) 5 | return 2; 6 | if(number == 1) 7 | return 1; 8 | return jumpFloor(number - 1) + jumpFloor(number - 2); 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目01-10/09变态跳台阶.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int jumpFloorII(int number) { 4 | if(number == 1) 5 | return 1; 6 | return 2 * jumpFloorII(number - 1); 7 | } 8 | // 循环解法 9 | /* 10 | int jumpFloorII(int number) { 11 | vector res; 12 | res.push_back(1); 13 | for(int i = 1; i < number; ++i) { 14 | int sum = 1; 15 | for(int j = i - 1; j >= 0; --j) 16 | sum += res[j]; 17 | res.push_back(sum); 18 | } 19 | return res[number-1]; 20 | } 21 | */ 22 | }; 23 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目01-10/10矩形覆盖.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int rectCover(int number) { 4 | int a = 1, b = 1, c; 5 | if(number == 0) 6 | return 0; 7 | if(number == 1) 8 | return b; 9 | for(int i = 2; i <= number; ++i) { 10 | c = a + b; 11 | a = b; 12 | b = c; 13 | } 14 | return c; 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目01-10/README.md: -------------------------------------------------------------------------------- 1 | #### 01 二维数组的查找(Easy,数组) 2 | > 此题目为有序二维数组查找问题,判断该二维数组中是否含有某个目标整数。 3 | 我们从最右上角元素开始查找判断,若该元素比目标整数小,则该行剩余元素均比目标小,下移一位;反之则该列剩余元素均比目标大,左移一位,直至找到目标元素或行列的某一下标越界。 4 | 5 | #### 02 替换空格(Easy,字符串) 6 | > 此题目为将一个字符串(char\*)中的所有空格**原地**替换为`%20`,不得定义另一辅助数组。 7 | 首先我们计算字符串中有多少个空格,得到新字符串的长度,将字符串中原有字符逐个后移。 8 | 9 | #### 03 从尾到头打印链表(Medium,链表,递归(回溯)) 10 | > 注意是**从尾到头**打印,我么可以利用递归或是回溯的算法思想,在回溯的过程中将值存放在一个全局数组里面。 11 | 12 | #### 04 重建二叉树(Medium,树,递归) 13 | > 此题目为根据一棵树的“前序遍历”和“中序遍历”结果(假设不含重复元素),重建该二叉树。 14 | 通过简单的递归可以解决,注意“前序遍历”的第一个元素即为根节点元素,“中序遍历”又根据根节点将结果分为左子数“中序遍历”和右子数“中序遍历”,这样便可以从根开始重构二叉树。 15 | 16 | #### 05 用两个栈实现队列(Easy,栈和队列) 17 | > 此题目为用两个栈(stack,先进后出FILO)实现队列(queue,先进先出FIFO)的功能。 18 | 见代码,略。 19 | 20 | #### 06 旋转数组的最小数字(Easy,查找和排序,二分查找(Binary Search)) 21 | > 此题目为寻找一个旋转数组中的最小数字。 22 | 通过遍历查找不满足递增顺序的接点处数字,算法复杂度为O(n);可以利用二分查找Binary Search将算法复杂度优化为O(logn),见代码。 23 | 24 | #### 07 斐波那契数列(Easy,斐波那契) 25 | > 简单利用斐波那契数列的生成规则,`f[n] = f[n-1] + f[n-2], f[0] = 0, f[1] = 1` 26 | 27 | #### 08 跳台阶(Medium,递归) 28 | > 此题目为青蛙一次可以跳1级也可以跳2级台阶,问跳上一个n级台阶共有多少种跳法。 29 | 我们通过递归来解决此题,两个基础情况`n=1`和`n=2`,然后通过递归统计两种情况的跳法之和。 30 | 31 | #### 09 变态跳台阶(Medium,递归,贪心,循环) 32 | > 此题目为青蛙一次可以跳1级也可以跳2级也可以跳n级台阶,问跳上一个n级台阶共有多少种跳法。 33 | 我可以发现`f(n) = 1(直接跳) + f(n-1) + f(n-2) + ... + f(1)`,因此可以用简单的循环来解决此问题,代码较长但容易理解;另一种通过递归实现贪心,我们发现规律`f(1) = 1, f(2) = 2, f(3) = 4, f(4) = 8, ... `即`f(n) = 2*f(n-1)`,当`n=1`时返回`1`,代码简洁。 34 | 35 | #### 10 矩形覆盖(Medium,递归,斐波那契) 36 | > 此题目为用`2*1`的矩形去覆盖一个`2*n`的大矩形总共有多少种方法。 37 | 我们每次有两种放法:当第一个竖着放,还剩下`2*(n-1)`尺寸的矩形;当第一个块横着放,而且它上面的空闲也只能横着放,这时剩下`2*(n-2)`尺寸的矩形。也就是说`f(n) = f(n-1) + f(n-2)`,然后我们看出它符合斐波那契的递推公式。 38 | 39 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目11-20/11二进制中1的个数.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int NumberOf1(int n) { 4 | // 计算机中的负数以补码形式存储 5 | int unit = 1, count = 0; 6 | while(unit) { 7 | if(n & unit) 8 | ++count; 9 | unit <<= 1; 10 | } 11 | return count; 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目11-20/12数值的整数次方.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | double Power(double base, int exponent) { 4 | // 快速幂,注意指数的正负 5 | double res = 1.0; 6 | int f = exponent > 0 ? 1 : -1; 7 | exponent = abs(exponent); 8 | while(exponent) { 9 | if(exponent & 1) 10 | res *= base; 11 | base *= base; 12 | exponent >>= 1; 13 | } 14 | return f == 1 ? res : double(1 / res); 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目11-20/13调整数组顺序使奇数位于偶数前面.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | void reOrderArray(vector &array) { 4 | int len = array.size(); 5 | vector a1, a2; 6 | for(int i = 0; i < len; ++i) { 7 | if(array[i] % 2 == 1) 8 | a1.push_back(array[i]); 9 | else 10 | a2.push_back(array[i]); 11 | } 12 | for(int i = 0; i < len; ++i) { 13 | if(i < a1.size()) 14 | array[i] = a1[i]; 15 | else 16 | array[i] = a2[i - a1.size()]; 17 | } 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目11-20/14链表中倒数第k个结点.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | struct ListNode { 3 | int val; 4 | struct ListNode *next; 5 | ListNode(int x) : 6 | val(x), next(NULL) { 7 | } 8 | };*/ 9 | class Solution { 10 | public: 11 | ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) { 12 | if(pListHead == NULL || k == 0) 13 | return NULL; 14 | ListNode* h = pListHead; 15 | ListNode* hk = pListHead; 16 | int count = 1; 17 | while(hk->next != NULL && count < k) { 18 | hk = hk->next; 19 | ++count; 20 | } 21 | if(count < k) 22 | return NULL; 23 | while(hk->next != NULL) { 24 | h = h->next; 25 | hk = hk->next; 26 | } 27 | return h; 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目11-20/15反转链表.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | struct ListNode { 3 | int val; 4 | struct ListNode *next; 5 | ListNode(int x) : 6 | val(x), next(NULL) { 7 | } 8 | };*/ 9 | class Solution { 10 | public: 11 | ListNode* ReverseList(ListNode* pHead) { 12 | ListNode* newHead = NULL; 13 | ListNode* temp = NULL; 14 | while(pHead != NULL) { 15 | temp = pHead->next; 16 | pHead->next = newHead; 17 | newHead = pHead; 18 | pHead = temp; 19 | } 20 | return newHead; 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目11-20/16合并两个排序的链表.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | struct ListNode { 3 | int val; 4 | struct ListNode *next; 5 | ListNode(int x) : 6 | val(x), next(NULL) { 7 | } 8 | };*/ 9 | class Solution { 10 | public: 11 | ListNode* Merge(ListNode* pHead1, ListNode* pHead2) 12 | { 13 | if(pHead1 == nullptr) 14 | return pHead2; 15 | if(pHead2 == nullptr) 16 | return pHead1; 17 | ListNode* head = nullptr; 18 | if(pHead1->val < pHead2->val) { 19 | head = pHead1; 20 | head->next = Merge(pHead1->next, pHead2); 21 | } 22 | else{ 23 | head = pHead2; 24 | head->next = Merge(pHead1, pHead2->next); 25 | } 26 | return head; 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目11-20/17树的子结构.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | struct TreeNode { 3 | int val; 4 | struct TreeNode *left; 5 | struct TreeNode *right; 6 | TreeNode(int x) : 7 | val(x), left(NULL), right(NULL) { 8 | } 9 | };*/ 10 | class Solution { 11 | public: 12 | bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2) 13 | { 14 | if(!pRoot1 || !pRoot2) 15 | return false; 16 | return dfs(pRoot1, pRoot2) || HasSubtree(pRoot1->left, pRoot2) || HasSubtree(pRoot1->right, pRoot2); 17 | } 18 | private: 19 | bool dfs(TreeNode* pRoot1, TreeNode* pRoot2) { 20 | if(!pRoot2) 21 | return true; 22 | if(!pRoot1) 23 | return false; 24 | if(pRoot1->val == pRoot2->val) 25 | return dfs(pRoot1->left, pRoot2->left) && dfs(pRoot1->right, pRoot2->right); 26 | else 27 | return false; 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目11-20/18二叉树的镜像.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | struct TreeNode { 3 | int val; 4 | struct TreeNode *left; 5 | struct TreeNode *right; 6 | TreeNode(int x) : 7 | val(x), left(NULL), right(NULL) { 8 | } 9 | };*/ 10 | class Solution { 11 | public: 12 | void Mirror(TreeNode *pRoot) { 13 | if(!pRoot) 14 | return; 15 | TreeNode* temp = pRoot->left; 16 | pRoot->left = pRoot->right; 17 | pRoot->right = temp; 18 | Mirror(pRoot->left); 19 | Mirror(pRoot->right); 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目11-20/19顺时针打印矩阵.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector spiralOrder(vector>& matrix) { 4 | vector res; 5 | int nr = matrix.size(); if(nr == 0) return res; 6 | int nc = matrix[0].size(); if(nc == 0) return res; 7 | vector> dirs{{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; 8 | vector nSteps{nc, nr - 1}; 9 | int idir = 0; 10 | int ir = 0, ic = -1; 11 | while(nSteps[idir % 2]) { // 偶数方向(左右)改变ic,奇数方向(上下)改变ir 12 | for(int i = 0; i < nSteps[idir % 2]; ++i) { 13 | ir += dirs[idir][0]; 14 | ic += dirs[idir][1]; 15 | res.push_back(matrix[ir][ic]); 16 | } 17 | --nSteps[idir % 2]; 18 | idir = (idir + 1) % 4; 19 | } 20 | return res; 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目11-20/20包含min函数的栈.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | // 为栈的每个状态都保存一个min值 4 | void push(int value) { 5 | data.push(value); 6 | if(dmin.empty()) 7 | dmin.push(value); 8 | else { 9 | if(value > dmin.top()) 10 | dmin.push(dmin.top()); 11 | else 12 | dmin.push(value); 13 | } 14 | } 15 | void pop() { 16 | data.pop(); 17 | dmin.pop(); 18 | } 19 | int top() { 20 | return data.top(); 21 | } 22 | int min() { 23 | return dmin.top(); 24 | } 25 | private: 26 | stack data; 27 | stack dmin; 28 | }; 29 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目11-20/README.md: -------------------------------------------------------------------------------- 1 | #### 11 二进制中1的个数(Medium,位运算) 2 | > 此题目为计算一个整数的二进制表示中1的个数,负数用补码表示。 3 | 首先,我们要知道什么是[补码及其表示方式](https://blog.csdn.net/zl10086111/article/details/80907428)。其次,要知道计算机中的负数以补码形式存储。我们将这个整数与1(00000001)做位运算:`&`,并将1循环左移`<<`,逐个计算1的个数。 4 | 5 | #### 12 数值的整数次方(Medium,快速幂) 6 | > 此题目为计算一个double类型浮点数的整数次幂。 7 | 我们使用**快速幂**算法,一种快速求幂的算法,`2^n = 2^(n/2) * 2^(n/2)`构成递推关系。注意这里指数的正负。 8 | 9 | #### 13 调整数组顺序使奇数位于偶数前面(Easy,数组) 10 | > 此题目为调整一个整数数组中的数字顺序,使所有奇数均位于偶数的前面,保持奇数之间和偶数之间的相对顺序不变(这里双指针无法解决)。 11 | 我使用的两个辅助数组,虽然看起来很傻但是AC了。 12 | 13 | #### 14 链表中倒数第k个结点(Medium,链表,快慢指针) 14 | > 此题目为返回一个链表的倒数第k个节点。 15 | 我们一下子就可以想到遍历一遍用一个vector存储然后直接输出倒数第k个节点,不过这样空间复杂度较高。本题的解法是利用两个指针(**快慢指针**),所谓的快慢指针就是定义两根指针,移动的速度一快一慢,以此来制造出自己想要的差值。这个差值可以让我们找到链表上相应的节点。以本题为例,我们先让快指针先“跑”k步,制造出这个插值k,然后快慢指针同时跑,当快指针再跑len-k步时到达链表尾,此时慢指针恰好跑到该链表的倒数第k个节点。 16 | 17 | #### 15 反转链表(Easy,链表) 18 | > 此题目为返回一个链表的反转链表的表头。 19 | 利用三个指针newHead, pHead, temp向前滚动反转即可解决。 20 | 21 | #### 16 合并两个排序的链表(Medium,链表,递归) 22 | > 此题目为合并两个有序链表,并返回新链表表头。 23 | 我们使用递归来解题,在每个递归中两个链表的较小的那个为newHead,而newHead的next即为下一个递归的返回值,见代码。 24 | 25 | #### 17 树的子结构(Medium,树,递归) 26 | > 此题目为给定两棵二叉树A,B,判断B是不是A的子结构(约定空树不是任一个树的子结构)。 27 | 我们使用递归来解题,递归遍历A的所有节点与B的根节点进行匹配,在每个匹配中再使用递归判断A节点左右节点与B节点的左右节点是否相匹配,见代码。 28 | 29 | #### 18 二叉树的镜像(Easy,树,递归) 30 | > 此题目为将给定的二叉树变换为其镜像二叉树。 31 | 通过简单的递归操作即可解决。 32 | 33 | #### 19 顺时针打印矩阵(Easy,数组) 34 | > 此题目为将一个二维数组顺时针打印出来。 35 | 思路很简单,就是写程序的时候有点绕,见代码。 36 | 37 | #### 20 包含min函数的栈(Medium,栈) 38 | > 此题目为定义栈(stack)的数据结构(FILO),并在`O(1)`时间内找到当前栈的最小值。 39 | 此题通过两个栈联合解决,其中dmin栈用于保存data栈中每个状态(push,pop)下的最小值,见代码。 40 | 41 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目21-30/21栈的压入、弹出序列.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | bool IsPopOrder(vector pushV, vector popV) { 4 | // 绝对顺序保持不变(方法一) 5 | // auto l = pushV.begin(); 6 | // for(auto i = popV.begin(); i < popV.end(); ++i) { 7 | // auto it = find(pushV.begin(), pushV.end(), *i); 8 | // if(it == pushV.end()) 9 | // return false; 10 | // if(it > l) { 11 | // auto temp = i; 12 | // for(auto j = it - 1; j >= l; --j) { 13 | // auto x = find(i, popV.end(), *j); 14 | // if(x < temp) 15 | // return false; 16 | // temp = x; 17 | // } 18 | // l = it + 1; 19 | // } 20 | // } 21 | // return true; 22 | 23 | // 模拟一遍(方法2) 24 | stack stk; 25 | int j = 0; 26 | for(auto& i : pushV) { 27 | stk.push(i); 28 | while(!stk.empty()) { 29 | if(stk.top() != popV[j]) 30 | break; 31 | stk.pop(); 32 | ++j; 33 | } 34 | } 35 | return j == pushV.size(); 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目21-30/22从上往下打印二叉树.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | struct TreeNode { 3 | int val; 4 | struct TreeNode *left; 5 | struct TreeNode *right; 6 | TreeNode(int x) : 7 | val(x), left(NULL), right(NULL) { 8 | } 9 | };*/ 10 | class Solution { 11 | public: 12 | vector PrintFromTopToBottom(TreeNode* root) { 13 | // 用queue实现广度优先搜索 14 | vector res; 15 | if(root == nullptr) 16 | return res; 17 | queue q; 18 | q.push(root); 19 | while(!q.empty()) { 20 | TreeNode* r = q.front(); 21 | res.push_back(r->val); 22 | q.pop(); 23 | if(r->left != nullptr) 24 | q.push(r->left); 25 | if(r->right != nullptr) 26 | q.push(r->right); 27 | } 28 | return res; 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目21-30/23二叉搜索树的后序遍历序列.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | bool VerifySquenceOfBST(vector sequence) { 4 | if(sequence.empty()) 5 | return false; 6 | return dfs(sequence, 0, sequence.size() - 1); 7 | } 8 | private: 9 | bool dfs(vector v, int start, int end) { 10 | if(start >= end) // if empty 11 | return true; 12 | int i; 13 | for(i = start; i < end; ++i) { 14 | if(v[i] > v[end]) 15 | break; 16 | } 17 | for(int j = i; j < end; ++j) 18 | if(v[j] < v[end]) 19 | return false; 20 | return dfs(v, start, i - 1) && dfs(v, i, end - 1); 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目21-30/24二叉树中和为某一值的路径.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | struct TreeNode { 3 | int val; 4 | struct TreeNode *left; 5 | struct TreeNode *right; 6 | TreeNode(int x) : 7 | val(x), left(NULL), right(NULL) { 8 | } 9 | };*/ 10 | class Solution { 11 | public: 12 | vector> FindPath(TreeNode* root,int expectNumber) { 13 | if(root) 14 | dfsFind(root, expectNumber); 15 | return res; 16 | } 17 | 18 | void dfsFind(TreeNode* node,int eNum) { 19 | v.push_back(node->val); 20 | if(!node->left && !node->right) { 21 | if(eNum - node->val == 0) 22 | res.push_back(v); 23 | } 24 | else { 25 | if(node->left) 26 | dfsFind(node->left, eNum - node->val); 27 | if(node->right) 28 | dfsFind(node->right, eNum - node->val); 29 | } 30 | if(!v.empty()) 31 | v.pop_back(); 32 | } 33 | private: 34 | vector> res; 35 | vector v; 36 | }; 37 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目21-30/25复杂链表的复制.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | struct RandomListNode { 3 | int label; 4 | struct RandomListNode *next, *random; 5 | RandomListNode(int x) : 6 | label(x), next(NULL), random(NULL) { 7 | } 8 | }; 9 | */ 10 | class Solution { 11 | public: 12 | RandomListNode* Clone(RandomListNode* pHead) 13 | { 14 | if(!pHead) 15 | return nullptr; 16 | // 复制 17 | RandomListNode* p = pHead; 18 | while(p) { 19 | RandomListNode* temp = new RandomListNode(p->label); 20 | temp->next = p->next; 21 | p->next = temp; 22 | p = temp->next; 23 | } 24 | // 赋值 25 | p = pHead; 26 | while(p) { 27 | if(p->random) 28 | p->next->random = p->random->next; 29 | p = p->next->next; 30 | } 31 | // 拆分 32 | RandomListNode* newHead = pHead->next; 33 | RandomListNode* temp = nullptr; 34 | p = pHead; 35 | while(p) { 36 | temp = p->next->next; 37 | if(temp != nullptr) 38 | p->next->next = temp->next; 39 | p->next = temp; 40 | p = p->next; 41 | } 42 | return newHead; 43 | } 44 | }; 45 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目21-30/26二叉搜索树与双向链表.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | struct TreeNode { 3 | int val; 4 | struct TreeNode *left; 5 | struct TreeNode *right; 6 | TreeNode(int x) : 7 | val(x), left(NULL), right(NULL) { 8 | } 9 | };*/ 10 | class Solution { 11 | public: 12 | TreeNode* Convert(TreeNode* pRootOfTree) 13 | { 14 | // 中序遍历 15 | if(pRootOfTree == nullptr) 16 | return nullptr; 17 | TreeNode* head = nullptr; 18 | InOrder(pRootOfTree, head); 19 | while(head->left != nullptr) 20 | head = head->left; 21 | return head; 22 | } 23 | 24 | void InOrder(TreeNode* node, TreeNode* &head) { 25 | if(node == nullptr) 26 | return; 27 | if(node->left != nullptr) 28 | InOrder(node->left, head); 29 | node->left = head; 30 | if(head != nullptr) 31 | head->right = node; 32 | head = node; 33 | if(node->right != nullptr) 34 | InOrder(node->right, head); 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目21-30/27字符串的排列.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector Permutation(string str) { 4 | if(str.length() == 0) 5 | return res; 6 | Permu(str, 0); 7 | sort(res.begin(), res.end()); 8 | return res; 9 | } 10 | 11 | void Permu(string& str, int begin) { 12 | if(begin == str.length() - 1) 13 | res.push_back(str); 14 | else { 15 | for(int p = begin; p < str.length(); ++p) { 16 | if(p != begin && str[p] == str[begin]) 17 | continue; 18 | // swap 19 | char t = str[begin]; 20 | str[begin] = str[p]; 21 | str[p] = t; 22 | Permu(str, begin + 1); 23 | // swap back 24 | t = str[begin]; 25 | str[begin] = str[p]; 26 | str[p] = t; 27 | } 28 | } 29 | } 30 | private: 31 | vector res; 32 | }; 33 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目21-30/28数组中出现次数超过一半的数字.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int MoreThanHalfNum_Solution(vector numbers) { 4 | // the most direct method is to use a map to count, but .. 5 | int majority = numbers[0], cnt = 1; 6 | for(int i = 1; i < numbers.size(); ++i) { 7 | if(numbers[i] == majority) 8 | ++cnt; 9 | else { 10 | if(--cnt == 0) { 11 | majority = numbers[i]; 12 | cnt = 1; 13 | } 14 | } 15 | } 16 | return majority; 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目21-30/29最小的K个数.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector GetLeastNumbers_Solution(vector input, int k) { 4 | vector res; 5 | if(k > input.size()) 6 | return res; 7 | priority_queue, less<>> maxheap; 8 | for(auto& x : input) { 9 | maxheap.push(x); 10 | if(maxheap.size() > k) 11 | maxheap.pop(); 12 | } 13 | while(!maxheap.empty()) { 14 | res.push_back(maxheap.top()); 15 | maxheap.pop(); 16 | } 17 | return res; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目21-30/30连续子数组的最大和.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int FindGreatestSumOfSubArray(vector array) { 4 | // 遇到和为负数就重新开始 5 | int mx = -1000, sum = 0; 6 | for(auto& i : array) { 7 | sum += i; 8 | mx = max(mx, sum); 9 | if(sum <= 0) 10 | sum = 0; 11 | } 12 | return mx; 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目31-40/31从1到n整数中1出现的次数.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int NumberOf1Between1AndN_Solution(int n) 4 | { 5 | int count = 0; 6 | while(n) { 7 | int i = n; 8 | while(i) { 9 | if(i % 10 == 1) 10 | ++count; 11 | i /= 10; 12 | } 13 | --n; 14 | } 15 | return count; 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目31-40/32把数组排成最小的数.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | static bool comp(int a, int b) { 4 | string A = to_string(a); // eg. 12 5 | string B = to_string(b); // eg. 2 6 | return A + B < B + A; // 122 < 212 7 | } 8 | string PrintMinNumber(vector numbers) { 9 | string res = ""; 10 | if(numbers.empty()) 11 | return res; 12 | sort(numbers.begin(), numbers.end(), comp); 13 | for(auto n : numbers) 14 | res += to_string(n); 15 | return res; 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目31-40/33丑数.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int GetUglyNumber_Solution(int index) { 4 | // 丑数: 2*2*2*...*3*3*3....*5*5*5 5 | // https://segmentfault.com/a/1190000015753301 屌 6 | if(index < 7) 7 | return index; 8 | vector res; 9 | res.push_back(1); 10 | int t1 = 0, t2 = 0, t3 = 0; 11 | for(int i = 1; i < index; ++i) { 12 | res.push_back(min(res[t1]*2, min(res[t2]*3, res[t3]*5))); 13 | if(res[i] == res[t1]*2) 14 | ++t1; 15 | if(res[i] == res[t2]*3) 16 | ++t2; 17 | if(res[i] == res[t3]*5) 18 | ++t3; 19 | } 20 | return res[index-1]; 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目31-40/34第一个只出现一次的字符.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int FirstNotRepeatingChar(string str) { 4 | map mm; 5 | for(auto& c : str) { 6 | if(mm.find(c) != mm.end()) 7 | ++mm[c]; 8 | else 9 | mm[c] = 1; 10 | } 11 | for(int i = 0; i < str.length(); ++i) { 12 | if(mm[str[i]] == 1) 13 | return i; 14 | } 15 | return -1; 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目31-40/35数组中的逆序对.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | // 归并排序算法思想: https://www.cnblogs.com/wanglei5205/p/8893700.html 4 | int count = 0; 5 | int InversePairs(vector data) { 6 | if(data.size()) { 7 | MergeSort(data, 0, data.size() - 1); 8 | } 9 | return count; 10 | } 11 | private: 12 | void MergeSort(vector& v, int l, int r) { 13 | if(l < r) { 14 | int m = (l + r) >> 1; 15 | MergeSort(v, l, m); 16 | MergeSort(v, m + 1, r); 17 | Merge(v, l, m, r); 18 | } 19 | } 20 | void Merge(vector& v, int l, int m, int r) { 21 | vector t; 22 | int i = l; 23 | int j = m + 1; 24 | while(i <= m && j <= r) { 25 | if(v[i] > v[j]) { 26 | t.push_back(v[j++]); 27 | count = (count + m - i + 1) % 1000000007; 28 | } 29 | else 30 | t.push_back(v[i++]); 31 | } 32 | while(i <= m) 33 | t.push_back(v[i++]); 34 | while(j <= r) 35 | t.push_back(v[j++]); 36 | for(i = 0; i < t.size(); ++i) 37 | v[l + i] = t[i]; 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目31-40/36两个链表的第一个公共结点.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * struct ListNode { 4 | * int val; 5 | * ListNode *next; 6 | * ListNode(int x) : val(x), next(NULL) {} 7 | * }; 8 | */ 9 | class Solution { 10 | public: 11 | ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { 12 | ListNode *p = headA, *q = headB; 13 | while(p != q) { 14 | p = p == nullptr ? headB : p->next; 15 | q = q == nullptr ? headA : q->next; 16 | } 17 | return q; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目31-40/37数字在排序数组中出现的次数.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int GetNumberOfK(vector data ,int k) { 4 | int count = 0; 5 | for(int i = 0; i < data.size() && data[i] <= k; ++i) 6 | if(data[i] == k) 7 | ++count; 8 | return count; 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目31-40/38二叉树的深度.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | struct TreeNode { 3 | int val; 4 | struct TreeNode *left; 5 | struct TreeNode *right; 6 | TreeNode(int x) : 7 | val(x), left(NULL), right(NULL) { 8 | } 9 | };*/ 10 | class Solution { 11 | public: 12 | int res = 0, m = 0; 13 | int TreeDepth(TreeNode* pRoot) 14 | { 15 | // dfs 16 | if(!pRoot) { 17 | m = max(m, res); 18 | return res; 19 | } 20 | ++res; 21 | TreeDepth(pRoot->left); 22 | TreeDepth(pRoot->right); 23 | --res; 24 | return m; 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目31-40/39平衡二叉树.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | bool IsBalanced_Solution(TreeNode* pRoot) { 4 | if(!pRoot) 5 | return true; 6 | int res = TreeDepth(pRoot); 7 | return res == -1 ? false : true; 8 | } 9 | private: 10 | int TreeDepth(TreeNode* pRoot) 11 | { 12 | // dfs 13 | if(!pRoot) 14 | return 0; 15 | int left = TreeDepth(pRoot->left); 16 | if(left == -1) 17 | return -1; 18 | int right = TreeDepth(pRoot->right); 19 | if(right == -1) 20 | return -1; 21 | return abs(left - right) > 1 ? -1 : max(left, right) + 1; 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目31-40/40数组中只出现一次的数字.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector singleNumber(vector& nums) { 4 | int a = 0, idx = 0, x = 0, y = 0; 5 | for(auto n : nums) a ^= n; 6 | while(!(a & (1 << idx))) ++idx; 7 | 8 | for(auto n : nums) { 9 | if(n & (1 << idx)) 10 | x ^= n; 11 | else 12 | y ^= n; 13 | } 14 | return vector{x, y}; 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目41-50/41和为S的连续正数序列.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector> res; 4 | vector > FindContinuousSequence(int sum) { 5 | if(sum < 3) 6 | return res; 7 | int low = 1, high = 2; 8 | while(high > low && high <= sum / 2 + 1) { 9 | int temp = (low + high) * (high - low + 1) / 2; 10 | if(temp < sum) 11 | ++high; 12 | if(temp > sum) 13 | ++low; 14 | if(temp == sum) { 15 | vector vec; 16 | for (int i = low; i <= high; ++i) 17 | vec.push_back(i); 18 | res.push_back(vec); 19 | ++low; 20 | } 21 | } 22 | return res; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目41-50/42和为S的两个数字.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector FindNumbersWithSum(vector array,int sum) { 4 | vector res; 5 | int i = 0, j = array.size() - 1; 6 | while(i < j) { 7 | if(array[j] == sum - array[i]) { 8 | res.push_back(array[i]); 9 | res.push_back(array[j]); 10 | return res; 11 | } 12 | if(array[j] > sum - array[i]) 13 | --j; 14 | else 15 | ++i; 16 | } 17 | return res; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目41-50/43左旋转字符串.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | 左旋转字符串 string LeftRotateString(string str, int n) { 4 | for(int i = 0; i < n; ++i) { 5 | str += str[i]; 6 | } 7 | return str.substr(n, str.length()); 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目41-50/44翻转单词顺序列.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | string ReverseSentence(string str) { 4 | stringstream ss; 5 | ss << str; 6 | string s, newstr; 7 | ss >> newstr; 8 | if(newstr.empty()) // 判断字符串是否全由空格组成 9 | return str; 10 | while(ss >> s) 11 | newstr = s + " " + newstr; 12 | return newstr; 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目41-50/45扑克牌顺子.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | bool IsContinuous( vector numbers ) { 4 | if(numbers.size() < 5) // 注意 5 | return false; 6 | sort(numbers.begin(), numbers.end()); 7 | int i, sum = 0; 8 | for(i = 4; i > 0 && numbers[i-1]; --i) { 9 | if(numbers[i] == numbers[i-1]) 10 | return false; 11 | sum += numbers[i] - numbers[i-1]; 12 | } 13 | if(sum > 4) 14 | return false; 15 | return true; 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目41-50/46孩子们的游戏(圆圈中最后剩下的数).cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | /* 4 | The position returned by josephus(n - 1, k) is adjusted because the recursive call 5 | josephus(n - 1, k) considers the original position k % n + 1 as position 1 */ 6 | int LastRemaining_Solution(int n, int m) { 7 | if (n == 0) 8 | return -1; 9 | if (n == 1) // LastRemaining_Solution(1, m) == 0,幸存者下标为0 10 | return 0; 11 | return (LastRemaining_Solution(n - 1, m) + m) % n; 12 | /* 13 | // 模拟过程 14 | if(n == 0) 15 | return -1; 16 | int tag[10000] = {0}, count = 0, i = 0, idx = 0; 17 | while(count != n - 1) { 18 | if(tag[idx % n] == 0) { 19 | if(i == m - 1) { 20 | tag[idx % n] = 1; 21 | ++count; 22 | i = 0; 23 | } 24 | else{ 25 | ++i; 26 | } 27 | } 28 | ++idx; 29 | } 30 | for(int i = 0; i < n; ++i) 31 | if(!tag[i]) 32 | return i; 33 | */ 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目41-50/47求1+2+3+...+n.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int Sum_Solution(int n) { 4 | int sum = n; 5 | bool ans = (n > 0) && (sum += Sum_Solution(n - 1)); 6 | return sum; 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目41-50/48不用加减乘除做加法.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int Add(int num1, int num2) 4 | { 5 | int sum, carry = 1; 6 | while(carry != 0) { 7 | sum = num1 ^ num2; 8 | carry = (num1 & num2) << 1; 9 | num1 = sum; 10 | num2 = carry; 11 | } 12 | return sum; 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目41-50/49把字符串转换成整数.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int StrToInt(string str) { 4 | // 注意32整型的范围: -2^31 ~ 2^31-1 5 | long sum = 0, flag = 0; 6 | if(str[0] == '+' || str[0] == '-') 7 | flag = 1; 8 | for(int i = flag; i < str.length(); ++i) { 9 | if(str[i] > '9' || str[i] < '0') 10 | return 0; 11 | sum = 10 * sum + str[i] - '0'; 12 | } 13 | if(flag == 1 && str[0] == '-') 14 | sum *= -1; 15 | if(sum < -(pow(2, 31)) || sum > pow(2, 31) - 1) 16 | return 0; 17 | return int(sum); 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目41-50/50数组中重复的数字.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | // Parameters: 4 | // numbers: an array of integers 5 | // length: the length of array numbers 6 | // duplication: (Output) the duplicated number in the array number 7 | // Return value: true if the input is valid, and there are some duplications in the array number 8 | // otherwise false 9 | bool duplicate(int numbers[], int length, int* duplication) { 10 | if(length <= 0) 11 | return false; 12 | for(int i = 0; i < length; ++i) { 13 | while(numbers[i] != i) { 14 | if(numbers[i] == numbers[numbers[i]]) { 15 | *duplication = numbers[i]; 16 | return true; 17 | } 18 | swap(numbers[i], numbers[numbers[i]]); 19 | } 20 | } 21 | return false; 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目51-60/51构建乘积数组.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector multiply(const vector& A) { 4 | vector B = {}; 5 | if(A.size() < 2) 6 | return B; 7 | int n = A.size(); 8 | int l = 1, r = 1; 9 | B.push_back(l); 10 | for(int i = 1; i < n; ++i) { 11 | l *= A[i-1]; 12 | B.push_back(l); 13 | } 14 | for(int j = n - 2; j >= 0; --j) { 15 | r *= A[j+1]; 16 | B[j] *= r; 17 | } 18 | return B; 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目51-60/52正则表达式匹配.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | bool match(char* str, char* pattern) 4 | { 5 | if(*str == '\0' && *pattern == '\0') 6 | return true; 7 | if(*str != '\0' && *pattern == '\0') 8 | return false; 9 | if(*(pattern + 1) == '*') { 10 | if(*str == *pattern || (*str != '\0' && *pattern == '.')) 11 | return match(str + 1, pattern) || match(str, pattern + 2); 12 | else 13 | return match(str, pattern + 2); 14 | } 15 | else { 16 | if(*str == *pattern || (*str != '\0' && *pattern == '.')) 17 | return match(str + 1, pattern + 1); 18 | else 19 | return false; 20 | } 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目51-60/53表示数值的字符串.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | bool isNumeric(char* string) 4 | { 5 | // 垃圾题,操! 6 | int flag = 0, nep = 0, eflag = 0, pflag = 0; 7 | if(string[flag] == '+' || string[flag] == '-') 8 | ++flag; 9 | if(string[flag] < '0' || string[flag] > '9') { 10 | if(string[flag] == '.') 11 | ++pflag; 12 | else 13 | return false; 14 | } 15 | ++flag; 16 | for(int i = flag; string[i] != '\0'; ++i) { 17 | if((string[i] != 'e' && string[i] != 'E' && string[i] != '.') && (string[i] < '0' || string[i] > '9')) 18 | return false; 19 | if(string[i] == 'e' || string[i] == 'E') { 20 | if(string[i + 1] == '\0') 21 | return false; 22 | if(string[i + 1] == '+' || string[i + 1] == '-') 23 | ++i; 24 | ++eflag; 25 | ++nep; 26 | } 27 | else if(string[i] == '.') { 28 | if(eflag || (string[i + 1] < '0' || string[i + 1] > '9')) 29 | return false; 30 | ++pflag; 31 | ++nep; 32 | } 33 | if(eflag > 1 || pflag > 1 || nep > 2) 34 | return false; 35 | } 36 | return true; 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目51-60/54字符流中第一个不重复的字符.cpp: -------------------------------------------------------------------------------- 1 | class Solution 2 | { 3 | public: 4 | // Insert one char from stringstream 5 | void Insert(char ch) 6 | { 7 | str += ch; 8 | ++count[ch]; 9 | } 10 | // return the first appearence once char in current stringstream 11 | char FirstAppearingOnce() 12 | { 13 | for(auto c : str) 14 | if(count[c] == 1) 15 | return c; 16 | return '#'; 17 | } 18 | private: 19 | string str = ""; 20 | char count[256] = {0}; 21 | }; 22 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目51-60/55链表中环的入口结点.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | struct ListNode { 3 | int val; 4 | struct ListNode *next; 5 | ListNode(int x) : 6 | val(x), next(NULL) { 7 | } 8 | }; 9 | */ 10 | class Solution { 11 | public: 12 | ListNode* EntryNodeOfLoop(ListNode* pHead) { 13 | ListNode *slow = pHead, *fast = pHead; 14 | if(!fast || !fast->next) 15 | return nullptr; 16 | while(fast && fast->next) { 17 | slow = slow->next; 18 | fast = fast->next->next; 19 | if(fast == slow) 20 | break; 21 | } 22 | if(slow != fast) 23 | return nullptr; 24 | slow = pHead; 25 | while(slow != fast) { 26 | slow = slow->next; 27 | fast = fast->next; 28 | } 29 | return slow; 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目51-60/56删除链表中重复的结点.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | struct ListNode { 3 | int val; 4 | struct ListNode *next; 5 | ListNode(int x) : 6 | val(x), next(NULL) { 7 | } 8 | }; 9 | */ 10 | class Solution { 11 | public: 12 | ListNode* deleteDuplication(ListNode* pHead) 13 | { 14 | map mm; 15 | ListNode* p = pHead; 16 | while(p) { 17 | if(mm.find(p->val) != mm.end()) 18 | ++mm[p->val]; 19 | else 20 | mm[p->val] = 1; 21 | p = p->next; 22 | } 23 | while(pHead) { 24 | if(mm[pHead->val] > 1) 25 | pHead = pHead->next; 26 | else 27 | break; 28 | } 29 | p = pHead; 30 | while(p && p->next) { 31 | if(mm[p->next->val] > 1) 32 | p->next = p->next->next; 33 | else 34 | p = p->next; 35 | } 36 | return pHead; 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目51-60/57二叉树的下一个结点.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | struct TreeLinkNode { 3 | int val; 4 | struct TreeLinkNode *left; 5 | struct TreeLinkNode *right; 6 | struct TreeLinkNode *next; 7 | TreeLinkNode(int x) :val(x), left(NULL), right(NULL), next(NULL) { 8 | 9 | } 10 | }; 11 | */ 12 | class Solution { 13 | public: 14 | TreeLinkNode* GetNext(TreeLinkNode* pNode) 15 | { 16 | if(pNode->right) { 17 | pNode = pNode->right; 18 | while(pNode->left) { 19 | pNode = pNode->left; 20 | } 21 | return pNode; 22 | } 23 | else if(pNode->next) { 24 | while(pNode->next && pNode->next->right == pNode) 25 | pNode = pNode->next; 26 | return pNode->next; 27 | } 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目51-60/58对称的二叉树.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | struct TreeNode { 3 | int val; 4 | struct TreeNode *left; 5 | struct TreeNode *right; 6 | TreeNode(int x) : 7 | val(x), left(NULL), right(NULL) { 8 | } 9 | }; 10 | */ 11 | class Solution { 12 | public: 13 | bool isSymmetrical(TreeNode* pRoot) 14 | { 15 | if(!pRoot) 16 | return true; 17 | return Compare(pRoot->left, pRoot->right); 18 | } 19 | private: 20 | bool Compare(TreeNode* lnode, TreeNode* rnode) { 21 | if(lnode == nullptr) 22 | return rnode == nullptr; 23 | if(rnode == nullptr) 24 | return false; 25 | if(lnode->val == rnode->val) 26 | return Compare(lnode->left, rnode->right) && Compare(lnode->right, rnode->left); 27 | return false; 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目51-60/59按之字形顺序打印二叉树.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | struct TreeNode { 3 | int val; 4 | struct TreeNode *left; 5 | struct TreeNode *right; 6 | TreeNode(int x) : 7 | val(x), left(NULL), right(NULL) { 8 | } 9 | }; 10 | */ 11 | class Solution { 12 | public: 13 | stack stk1; 14 | stack stk2; 15 | vector> Print(TreeNode* pRoot) { 16 | vector> res; 17 | if(!pRoot) 18 | return res; 19 | stk1.push(pRoot); 20 | while(!stk1.empty() || !stk2.empty()) { 21 | vector v; 22 | if(!stk1.empty()) 23 | while(!stk1.empty()) { 24 | if(stk1.top()->left) 25 | stk2.push(stk1.top()->left); 26 | if(stk1.top()->right) 27 | stk2.push(stk1.top()->right); 28 | v.push_back(stk1.top()->val); 29 | stk1.pop(); 30 | } 31 | else 32 | while(!stk2.empty()) { 33 | if(stk2.top()->right) 34 | stk1.push(stk2.top()->right); 35 | if(stk2.top()->left) 36 | stk1.push(stk2.top()->left); 37 | v.push_back(stk2.top()->val); 38 | stk2.pop(); 39 | } 40 | res.push_back(v); 41 | } 42 | return res; 43 | } 44 | }; 45 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目51-60/60把二叉树打印成多行.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | struct TreeNode { 3 | int val; 4 | struct TreeNode *left; 5 | struct TreeNode *right; 6 | TreeNode(int x) : 7 | val(x), left(NULL), right(NULL) { 8 | } 9 | }; 10 | */ 11 | class Solution { 12 | public: 13 | vector> Print(TreeNode* pRoot) { 14 | vector> res; 15 | vector v; 16 | if(!pRoot) 17 | return res; 18 | queue q; 19 | TreeNode* fr; 20 | q.push(pRoot); 21 | int next_level = 0; 22 | int curr_level = 1; 23 | while(!q.empty()) { 24 | fr = q.front(); 25 | v.push_back(fr->val); 26 | q.pop(); 27 | if(fr->left) { 28 | q.push(fr->left); 29 | ++next_level; 30 | } 31 | if(fr->right) { 32 | q.push(fr->right); 33 | ++next_level; 34 | } 35 | --curr_level; 36 | if(curr_level == 0) { 37 | curr_level = next_level; 38 | next_level = 0; 39 | res.push_back(v); 40 | v.clear(); 41 | } 42 | } 43 | return res; 44 | } 45 | }; 46 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目61-67/61序列化二叉树.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | struct TreeNode { 3 | int val; 4 | struct TreeNode *left; 5 | struct TreeNode *right; 6 | TreeNode(int x) : 7 | val(x), left(NULL), right(NULL) { 8 | } 9 | }; 10 | */ 11 | class Solution { 12 | public: 13 | char* Serialize(TreeNode *root) { 14 | // 前序遍历 15 | PreOrder(root); 16 | int* str = new int[v.size()]; 17 | for(int i = 0; i < v.size(); ++i) 18 | str[i] = v[i]; 19 | return (char*)str; 20 | } 21 | TreeNode* Deserialize(char *str) { 22 | int* p = (int*)str; 23 | return helper(p); 24 | } 25 | void PreOrder(TreeNode* root) { 26 | if(!root) { 27 | v.push_back(0xFFFFFFFF); 28 | return; 29 | } 30 | v.push_back(root->val); 31 | PreOrder(root->left); 32 | PreOrder(root->right); 33 | } 34 | TreeNode* helper(int*& str) { 35 | if(*str == 0xFFFFFFFF) { 36 | ++str; 37 | return nullptr; 38 | } 39 | TreeNode* root = new TreeNode(*str); 40 | ++str; 41 | root->left = helper(str); 42 | root->right = helper(str); 43 | return root; 44 | } 45 | private: 46 | vector v; 47 | }; 48 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目61-67/62二叉搜索树的第k个结点.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | struct TreeNode { 3 | int val; 4 | struct TreeNode *left; 5 | struct TreeNode *right; 6 | TreeNode(int x) : 7 | val(x), left(NULL), right(NULL) { 8 | } 9 | }; 10 | */ 11 | class Solution { 12 | public: 13 | TreeNode* KthNode(TreeNode* pRoot, int k) 14 | { 15 | if(!pRoot) 16 | return nullptr; 17 | dfs(pRoot); 18 | if(res.size() < k || k <= 0) // 注意k可能小于0 19 | return nullptr; 20 | return res[k-1]; 21 | } 22 | private: 23 | vector res; 24 | void dfs(TreeNode* node) { 25 | if(node) { 26 | dfs(node->left); 27 | res.push_back(node); 28 | dfs(node->right); 29 | } 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目61-67/63数据流中的中位数.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | // 最大堆和最小堆(通常为完全二叉树,故用数组存储) 4 | void Insert(int num) 5 | { 6 | if(count % 2 == 0) { 7 | maxheap.push(num); 8 | minheap.push(maxheap.top()); 9 | maxheap.pop(); 10 | } 11 | else { 12 | minheap.push(num); 13 | maxheap.push(minheap.top()); 14 | minheap.pop(); 15 | } 16 | ++count; 17 | } 18 | 19 | double GetMedian() 20 | { 21 | if(count % 2 == 1) 22 | return (double)minheap.top(); 23 | else 24 | return (double)(minheap.top() + maxheap.top()) / 2; 25 | } 26 | private: 27 | int count = 0; 28 | priority_queue, less> maxheap; 29 | priority_queue, greater> minheap; 30 | }; 31 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目61-67/64滑动窗口的最大值.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector maxInWindows(const vector& num, unsigned int size) 4 | { 5 | vector res; 6 | if(num.size() == 0 || size < 1 || size > num.size()) 7 | return res; 8 | deque dk; 9 | int i; 10 | for(i = 0; i < size; ++i) { 11 | while(!dk.empty() && num[i] > num[dk.back()]) 12 | dk.pop_back(); 13 | dk.push_back(i); 14 | } 15 | for(; i < num.size(); ++i) { 16 | res.push_back(num[dk.front()]); 17 | while(!dk.empty() && num[i] >= num[dk.back()]) 18 | dk.pop_back(); 19 | if(!dk.empty() && i - dk.front() >= size) 20 | dk.pop_front(); 21 | dk.push_back(i); 22 | } 23 | res.push_back(num[dk.front()]); 24 | return res; 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目61-67/65矩阵中的路径.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | bool hasPath(char* matrix, int rows, int cols, char* str) 4 | { 5 | if(matrix == NULL || rows < 1 || cols < 1 || str == NULL) 6 | return false; 7 | vector flags(rows * cols, 0); 8 | bool res = true; 9 | for(int i = 0; i < rows; ++i) 10 | for(int j = 0; j < cols; ++j) { 11 | if(dfs(matrix, flags, rows, cols, i, j, str)) 12 | return true; 13 | } 14 | return false; 15 | } 16 | private: 17 | bool dfs(char*& matrix, vector& flags, int& rows, int& cols, int i, int j, char*& str) { 18 | if(*str == '\0') 19 | return true; 20 | bool res = false; 21 | if(i >= 0 && i < rows && j >= 0 && j < cols && !flags[i * cols + j] && matrix[i * cols + j] == *str) { 22 | flags[i * cols + j] = 1; 23 | ++str; 24 | res = dfs(matrix, flags, rows, cols, i + 1, j, str) || 25 | dfs(matrix, flags, rows, cols, i - 1, j, str) || 26 | dfs(matrix, flags, rows, cols, i, j + 1, str) || 27 | dfs(matrix, flags, rows, cols, i, j - 1, str); 28 | if(!res) { 29 | --str; 30 | flags[i * cols + j] = 0; 31 | } 32 | } 33 | return res; 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目61-67/66机器人的运动范围.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int movingCount(int threshold, int rows, int cols) 4 | { 5 | vector vec(rows * cols, 0); 6 | return movingC(threshold, vec, 0, 0, rows, cols); 7 | } 8 | int movingC(int& threshold, vector& vec, int i, int j, int& rows, int& cols) { 9 | int count = 0; 10 | if(i >= 0 && i < rows && j >= 0 && j < cols && !vec[i * cols + j] && (getSum(i) + getSum(j)) <= threshold) { 11 | vec[i * cols + j] = 1; 12 | count += 1 + 13 | movingC(threshold, vec, i + 1, j, rows, cols) + 14 | movingC(threshold, vec, i - 1, j, rows, cols) + 15 | movingC(threshold, vec, i, j + 1, rows, cols) + 16 | movingC(threshold, vec, i, j - 1, rows, cols); 17 | } 18 | return count; 19 | } 20 | int getSum(int num) { 21 | int sum = 0; 22 | while(num > 0) { 23 | sum += num % 10; 24 | num /= 10; 25 | } 26 | return sum; 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目61-67/67剪绳子.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int cutRope(int number) { 4 | int dp[number + 1], MAXN; 5 | if(number == 2) 6 | return 1; 7 | if(number == 3) 8 | return 2; 9 | dp[1] = 1; 10 | dp[2] = 2; 11 | dp[3] = 3; 12 | for(int n = 4; n <= number; ++n) { 13 | MAXN = 0; 14 | for(int i = 1; i <= n / 2 + 1; ++i) 15 | MAXN = max(MAXN, dp[i] * dp[n - i]); 16 | dp[n] = MAXN; 17 | } 18 | return dp[number]; 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /剑☞Offer系列/题目61-67/README.md: -------------------------------------------------------------------------------- 1 | #### 61 序列化二叉树(Medium,树) 2 | > 此题目为二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串;二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。 3 | 使用“前序遍历”序列化和返序列化,将空节点记录为0xFFFFFFFF,见代码。 4 | 5 | #### 62 二叉搜索树的第k个结点(Easy,树,递归) 6 | > 此题目为给定一棵二叉搜索树,请找出其中的第k小的结点。 7 | 二叉搜索树的中序遍历是个递增序列,简单dfs做个中序遍历,储存每个节点,输出第k个节点。 8 | 9 | #### 63 数据流中的中位数(Medium,红黑树,最大堆,最小堆) 10 | > 此题目为得到一个数据流中的中位数? 11 | 利用红黑树,最大堆,最小堆的高效插入操作,将数据流分为最大堆最小堆,其中最大堆中的数都比最小堆中的小。最后取中位数的时候直接对两个堆堆顶元素进行处理。 12 | 13 | #### 64 滑动窗口的最大值(Hard,数组) 14 | > 此题目为给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。 15 | 使用双端队列存储每个数的下标。具体见代码。 16 | 17 | #### 65 矩阵中的路径(Hard,数组,递归,回溯,动态规划) 18 | > 此题目为请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。 19 | 与66题思路类似,但多了个回溯的操作,建议先做66题,具体见代码。 20 | 21 | #### 66 机器人的运动范围(Hard,数组,递归,动态规划) 22 | > 此题目为地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 23 | 见代码。 24 | 25 | #### 67 剪绳子(Hard,贪心,动态规划) 26 | > 此题目为给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],...,k[m]。请问k[0]xk[1]x...xk[m]可能的最大乘积是多少? 27 | 见代码。 28 | 29 | -------------------------------------------------------------------------------- /动态规划Top50/README.md: -------------------------------------------------------------------------------- 1 | 1. [GeeksforGeeks01](https://practice.geeksforgeeks.org/explore/?category%5b%5d=Dynamic%20Programming&page=1) 2 | 3 | -------------------------------------------------------------------------------- /算法博客(Algorithm Blogs)/Interval-Trees.md: -------------------------------------------------------------------------------- 1 | ## 区间树(Interval Trees) 2 | From http://www.dgp.toronto.edu/~jstewart/378notes/22intervals/ 3 | 4 | ### 1) 我们如何将这些时间间隔保存到一个数据结构里面呢? 5 | 我们可以将这些间隔(区间)保存到区间树中,区间树是自平衡二叉搜索树(BST)的扩展。 6 | 区间树中每个区间都有一个对应的叶子节点。在这些叶子节点上面构建了一个完全二叉树。每个中间节点都有一个key值,将这些区间分到它的左子树和右子树。叶子节点本身不不存放key值的,仅用于表示这些区间。 7 | 8 | ### 2) 我们如何存放重叠区间 9 | 区间树的每个节点(中间节点和叶子节点)都可以存放一个区间集合。我们可以将这些区间集合存储为链表。每个叶子节点将包含一个指向该所有包含该区间的区间集合的指针。但是这种存放方式存在问题,在当每个区间都非常长的时候,它们可能出现在每个叶子节点所指向的区间集合中,有n个叶子节点的时候,它的空间复杂度将是`O(n^2)`! 10 | 11 | ### 3) 优化空间 12 | 中间节点表示`span`其子树中区间的并集。我们不只把区间存放到每个单独的叶子节点,我们还会将区间存放在中间节点中。根据下面的准则,一个区间`[a, b]`被存放在节点x中,当且仅当: 13 | * `span(x)`完全被包含在区间`[a, b]`中 14 | * `span(parent(x))`不完全被包含在区间`[a, b]`中 15 | 16 | 这样每个区间在每层最多只被储存两次。这样空间复杂度则被降至`O(nlogn)`。 17 | 18 | ### 4) 查询一个区间(Query of Intervals) 19 | 20 | 21 | ### 5) 插入一个区间(Inserting an Interval) 22 | 23 | 24 | ### 6) 删除一个区间(Delete an Interval) 25 | -------------------------------------------------------------------------------- /算法博客(Algorithm Blogs)/README.md: -------------------------------------------------------------------------------- 1 | Record some algorithms in blog form. 2 | -------------------------------------------------------------------------------- /莱特扣的-系列/01.Pattern: Sliding Window/01 Maximum Sum Subarray of Size K.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int maxSum(vector nums, int k) { 5 | if(k > nums.size()) 6 | return -1; 7 | int j = k, msum = 0; 8 | for(int t = 0; t < k; ++t) 9 | msum += nums[t]; 10 | while(j < nums.size()) { 11 | msum = max(msum, msum + (nums[j] - nums[j - k])); 12 | ++j; 13 | } 14 | return msum; 15 | } 16 | -------------------------------------------------------------------------------- /莱特扣的-系列/01.Pattern: Sliding Window/02 Minimum Size Subarray Sum.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int minSubArrayLen(int s, vector& nums) { 4 | int i = 0, j = 0, sum = 0, l = 10000; 5 | if(nums.size() == 0) 6 | return 0; 7 | while(j < nums.size()) { 8 | while(sum < s && j < nums.size()) 9 | sum += nums[j++]; 10 | if(sum < s && l == 10000) 11 | return 0; 12 | while(sum >= s) 13 | sum -= nums[i++]; 14 | l = min(l, j - i + 1); 15 | } 16 | return l; 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /莱特扣的-系列/01.Pattern: Sliding Window/03 Longest Substring with At Most K Distinct Characters.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int lengthOfLongestSubstringKDistinct(string &s, int k) { 4 | // Maybe you also should check whether the number of unique characters in s is larger than k. 5 | if(k <= 0) 6 | return 0; 7 | unordered_map mm; 8 | int i = 0, j = 0, l = 0; 9 | while(j < s.length()) { 10 | if(mm.find(s[j]) == mm.end()) 11 | mm[s[j]] = 1; 12 | else 13 | ++mm[s[j]]; 14 | l = max(l, j - i); 15 | while(mm.size() > k) { 16 | if(mm[s[i]] > 1) 17 | --mm[s[i]]; 18 | else 19 | mm.erase(s[i]); 20 | ++i; 21 | } 22 | ++j; 23 | } 24 | return max(l, j - i); 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /莱特扣的-系列/01.Pattern: Sliding Window/04 Fruits into Baskets.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int totalFruit(vector& tree) { 4 | // Just the longest substring with at most two distinct characters 5 | int i = 0, j = 0, l = 0; 6 | unordered_map mm; 7 | while(j < tree.size()) { 8 | if(mm.find(tree[j]) != mm.end()) 9 | ++mm[tree[j]]; 10 | else 11 | mm[tree[j]] = 1; 12 | l = max(l, j - i); 13 | while(mm.size() > 2) { 14 | if(mm[tree[i]] > 1) 15 | --mm[tree[i]]; 16 | else 17 | mm.erase(tree[i]); 18 | ++i; 19 | } 20 | ++j; 21 | } 22 | return max(l, j - i); 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /莱特扣的-系列/01.Pattern: Sliding Window/05 Longest Substring Without Repeating Characters.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int lengthOfLongestSubstring(string s) { 4 | vector idx(96, -1); 5 | int i = 0, j = 0, l = 0; 6 | while(j < s.length()) { 7 | if(idx[s[j] - ' '] != -1) { 8 | l = max(l, j - i); 9 | i = max(i, idx[s[j] - ' '] + 1); 10 | } 11 | idx[s[j] - ' '] = j; 12 | ++j; 13 | } 14 | return max(l, j - i); 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /莱特扣的-系列/01.Pattern: Sliding Window/06 Maximum Length Substring Having All Same Characters after K Changes.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int findLen(string& s, int k, char c) { 5 | int i = 0, j = 0, l = 0, cnt = 0; 6 | while(j < s.length()) { 7 | if(s[j] != c) 8 | ++cnt; 9 | while(cnt > k) { 10 | if(s[i] != c) 11 | --cnt; 12 | ++i; 13 | } 14 | l = max(l, j - i + 1); 15 | ++j; 16 | } 17 | return l; 18 | } 19 | 20 | int main() { 21 | int maxlen; 22 | int t, n, k; 23 | string s; 24 | cin >> t; 25 | while(t > 0) { 26 | maxlen = 0; 27 | cin >> n >> k; 28 | cin >> s; 29 | for(int i = 0; i < 26; ++i) { 30 | maxlen = max(maxlen, findLen(s, k, 'A' + i)); 31 | maxlen = max(maxlen, findLen(s, k, 'a' + i)); 32 | } 33 | cout << maxlen << endl; 34 | --t; 35 | } 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /莱特扣的-系列/01.Pattern: Sliding Window/07 Longest Subsegment of ‘1’s Formed by Changing at Most K ‘0’s.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int findLen(vector& nums, int k) { 5 | int i = 0, j = 0, l = 0, cnt = 0; 6 | while(j < nums.size()) { 7 | if(nums[j] != 1) 8 | ++cnt; 9 | while(cnt > k) { 10 | if(nums[i] != 1) 11 | --cnt; 12 | ++i; 13 | } 14 | l = max(l, j - i + 1); 15 | ++j; 16 | } 17 | return l; 18 | } 19 | -------------------------------------------------------------------------------- /莱特扣的-系列/01.Pattern: Sliding Window/08. Sliding Window Maximum.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector maxSlidingWindow(vector& nums, int k) { 4 | vector maxSW; 5 | deque dq; 6 | for(int i = 0; i < nums.size(); ++i) { 7 | while(!dq.empty() && dq.front() < i - k + 1) 8 | dq.pop_front(); 9 | while(!dq.empty() && nums[i] > nums[dq.back()]) 10 | dq.pop_back(); 11 | dq.push_back(i); 12 | if(i >= k - 1) 13 | maxSW.push_back(nums[dq.front()]); 14 | } 15 | return maxSW; 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /莱特扣的-系列/01.Pattern: Sliding Window/09. Shortest Subarray with Sum at Least K.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int shortestSubarray(vector& A, int K) { 4 | int n = A.size(), miLen = n + 1; 5 | deque dq; 6 | for(int i = 0; i < n; ++i) { 7 | if(i > 0) 8 | A[i] += A[i-1]; 9 | if(A[i] >= K) 10 | miLen = min(miLen, i + 1); 11 | while(!dq.empty() && A[i] - A[dq.front()] >= K) 12 | miLen = min(miLen, i - dq.front()), dq.pop_front(); 13 | while(!dq.empty() && A[i] <= A[dq.back()]) 14 | dq.pop_back(); 15 | dq.push_back(i); 16 | } 17 | return miLen == n + 1 ? -1 : miLen; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /莱特扣的-系列/01.Pattern: Sliding Window/10. Max Consecutive Ones III.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int longestOnes(vector& A, int K) { 4 | int i = 0, j = 0, n = A.size(); 5 | for(j = 0; j < n; ++j) { 6 | if(A[j] == 0) --K; 7 | if(K < 0 && A[i++] == 0) ++K; 8 | } 9 | return j - i; 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /莱特扣的-系列/01.Pattern: Sliding Window/11. Replace the Substring for Balanced String.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int balancedString(string s) { 4 | unordered_map mp; 5 | for(auto c : s) { 6 | ++mp[c]; 7 | } 8 | int i = 0, n = s.length(), k = n/4, miLen = n; 9 | for(int j = 0; j < n; ++j) { 10 | --mp[s[j]]; 11 | while(i < n && mp['Q'] <= k && mp['W'] <= k && mp['E'] <= k && mp['R'] <= k) { 12 | miLen = min(miLen, j - i + 1); 13 | ++mp[s[i++]]; 14 | } 15 | } 16 | return miLen; 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /莱特扣的-系列/01.Pattern: Sliding Window/12. Count Number of Nice Subarrays.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int numberOfSubarrays(vector& nums, int k) { 4 | int n = nums.size(), res = 0; 5 | vector idx{-1}; 6 | for(int i = 0; i < n; ++i) { 7 | if(nums[i] & 1) 8 | idx.push_back(i); 9 | } 10 | idx.push_back(n); 11 | int m = idx.size(); 12 | for(int i = 1; i < m - k; ++i) { 13 | res += (idx[i] - idx[i-1]) * (idx[i+k] - idx[i+k-1]); 14 | } 15 | 16 | return res; 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /莱特扣的-系列/02.Pattern: Two Pointers/01 Two Sum.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector twoSum(vector& nums, int target) { 4 | vector res; 5 | unordered_map mm; 6 | for(int i = 0; i < nums.size(); ++i) { 7 | if(mm.find(nums[i]) != mm.end()) { 8 | res.push_back(mm[nums[i]]); 9 | res.push_back(i); 10 | return res; 11 | } 12 | else 13 | mm[target - nums[i]] = i; 14 | } 15 | return res; 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /莱特扣的-系列/02.Pattern: Two Pointers/02 Remove Duplicates from Sorted Array.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int removeDuplicates(vector& nums) { 4 | int length = 1; 5 | if(nums.size() < 2) 6 | return nums.size(); 7 | for(int i = 0; i < nums.size() - 1; ++i) { 8 | if(nums[i] != nums[i + 1]) { 9 | nums[length] = nums[i + 1]; 10 | ++length; 11 | } 12 | } 13 | return length; 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /莱特扣的-系列/02.Pattern: Two Pointers/03 Squares of a Sorted Array.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector sortedSquares(vector& A) { 4 | vector res(A.size()); 5 | int i = 0, j = A.size() - 1, t = A.size() - 1; 6 | while(t >= 0) { 7 | if(A[i]*A[i] < A[j]*A[j]) { 8 | res[t] = A[j]*A[j]; 9 | --j; 10 | } 11 | else { 12 | res[t] = A[i]*A[i]; 13 | ++i; 14 | } 15 | --t; 16 | } 17 | return res; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /莱特扣的-系列/02.Pattern: Two Pointers/04 3Sum.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector> threeSum(vector& nums) { 4 | vector> res; 5 | int nz = nums.size(); 6 | if(nz < 3) 7 | return res; 8 | sort(nums.begin(), nums.end()); 9 | int l, r; 10 | vector vec(3); 11 | for(int i = 0; i < nz - 2 && nums[i] <= 0; ++i) { 12 | if(i != 0 && nums[i] == nums[i-1]) 13 | continue; 14 | l = i + 1; 15 | r = nums.size() - 1; 16 | while(l < r) { 17 | if(nums[l] + nums[r] == -nums[i]) { 18 | vec[0] = nums[i]; 19 | vec[1] = nums[l]; 20 | vec[2] = nums[r]; 21 | if(res.empty() || vec != res.back()) 22 | res.push_back(vec); 23 | ++l; 24 | --r; 25 | } 26 | else if(nums[l] + nums[r] < -nums[i]) 27 | ++l; 28 | else 29 | --r; 30 | } 31 | } 32 | return res; 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /莱特扣的-系列/02.Pattern: Two Pointers/05 3Sum Closest.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int threeSumClosest(vector& nums, int target) { 4 | int len = nums.size(); 5 | sort(nums.begin(), nums.end()); 6 | int sum, minn = 10000; 7 | for(int i = 0; i < len - 2; ++i) { 8 | int l = i + 1; 9 | int r = len - 1; 10 | while(l < r) { 11 | if(minn == 0) 12 | break; 13 | if(abs(target - nums[i] - nums[l] - nums[r]) < minn) { 14 | minn = abs(target - nums[i] - nums[l] - nums[r]); 15 | sum = nums[i] + nums[l] + nums[r]; 16 | } 17 | if(nums[l] + nums[r] > target - nums[i]) 18 | --r; 19 | else 20 | ++l; 21 | } 22 | } 23 | return sum; 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /莱特扣的-系列/02.Pattern: Two Pointers/06 3Sum Smaller.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | /** 4 | * @param nums: an array of n integers 5 | * @param target: a target 6 | * @return: the number of index triplets satisfy the condition nums[i] + nums[j] + nums[k] < target 7 | */ 8 | int threeSumSmaller(vector &nums, int target) { 9 | // Write your code here 10 | if(nums.size() < 3) 11 | return 0; 12 | sort(nums.begin(), nums.end()); 13 | int count = 0; 14 | for(int i = 0; i < nums.size() - 2; ++i) { 15 | if((target >= 0 && nums[i] > target) || (target < 0 && nums[i] >= 0)) 16 | break; 17 | int l = i + 1; 18 | int r = nums.size() - 1; 19 | while(l < r) { 20 | if(nums[i] + nums[l] + nums[r] < target) { 21 | count += r - l; 22 | ++l; 23 | } 24 | else 25 | --r; 26 | } 27 | } 28 | return count; 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /莱特扣的-系列/02.Pattern: Two Pointers/07 Subarray Product Less Than K.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int numSubarrayProductLessThanK(vector& nums, int k) { 4 | int pro = 1, cnt = 0; 5 | for(int l = 0, r = 0; r < nums.size(); ++r) { 6 | pro *= nums[r]; 7 | while(l <= r && pro >= k) { 8 | pro /= nums[l++]; 9 | } 10 | cnt += r - l + 1; 11 | } 12 | return cnt; 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /莱特扣的-系列/02.Pattern: Two Pointers/08 Sort Colors.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | void sortColors(vector &nums) { 4 | int r = 0, w = 0, b = nums.size() - 1; 5 | while(w <= b) { 6 | int temp = nums[w]; 7 | if(nums[w] == 0) { 8 | nums[w] = nums[r]; 9 | nums[r] = temp; 10 | ++r; 11 | ++w; 12 | } 13 | else if(nums[w] == 2) { 14 | nums[w] = nums[b]; 15 | nums[b] = temp; 16 | --b; 17 | } 18 | else 19 | ++w; 20 | } 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /莱特扣的-系列/02.Pattern: Two Pointers/README.md: -------------------------------------------------------------------------------- 1 | #### Pattern 2 : Two Pointers (双指针类型) 2 | 1. [Pair with Target Sum (easy) -- LeetCode](https://leetcode.com/problems/two-sum/) 3 | 2. [Remove Duplicates (easy) -- LeetCode](https://leetcode.com/problems/remove-duplicates-from-sorted-array/) 4 | 3. [Squaring a Sorted Array (easy) -- LeetCode](https://leetcode.com/problems/squares-of-a-sorted-array/) 5 | 4. [Triplet Sum to Zero (medium) -- LeetCode](https://leetcode.com/problems/3sum) 6 | 5. [Triplet Sum Close to Target (medium) -- LeetCode](https://leetcode.com/problems/3sum-closest/) 7 | 6. [Triplets with Smaller Sum (medium, google) -- LintCode](https://www.lintcode.com/problem/3sum-smaller/description) 8 | 7. [Subarrays with Product Less than a Target (medium) -- LeetCode](https://leetcode.com/problems/subarray-product-less-than-k/) 9 | 8. [Dutch National Flag Problem (medium) -- LeetCode](https://leetcode.com/problems/sort-colors/) 10 | 11 | -------------------------------------------------------------------------------- /莱特扣的-系列/03.Pattern: Fast&Slow Pointers/01 Linked List Cycle.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * struct ListNode { 4 | * int val; 5 | * ListNode *next; 6 | * ListNode(int x) : val(x), next(NULL) {} 7 | * }; 8 | */ 9 | class Solution { 10 | public: 11 | bool hasCycle(ListNode *head) { 12 | ListNode *fast = head, *slow = head; 13 | while(fast != nullptr && fast->next != nullptr) { 14 | slow = slow->next; 15 | fast = fast->next->next; 16 | if(fast == slow) 17 | return true; 18 | } 19 | return false; 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /莱特扣的-系列/03.Pattern: Fast&Slow Pointers/02 Middle of the Linked List.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * struct ListNode { 4 | * int val; 5 | * ListNode *next; 6 | * ListNode(int x) : val(x), next(NULL) {} 7 | * }; 8 | */ 9 | class Solution { 10 | public: 11 | ListNode* middleNode(ListNode* head) { 12 | ListNode *p = head, *mid = head; 13 | while(p != nullptr && p->next != nullptr) { 14 | mid = mid->next; 15 | p = p->next->next; 16 | } 17 | return mid; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /莱特扣的-系列/03.Pattern: Fast&Slow Pointers/03 Happy Number.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | bool isHappy(int n) { 4 | int fast = n, slow = n; 5 | do { 6 | slow = squareSum(slow); 7 | fast = squareSum(squareSum(fast)); 8 | } while(slow != fast); 9 | return slow == 1; 10 | } 11 | int squareSum(int n) { 12 | int sum = 0; 13 | while(n > 0) { 14 | sum += (n % 10) * (n % 10); 15 | n /= 10; 16 | } 17 | return sum; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /莱特扣的-系列/03.Pattern: Fast&Slow Pointers/04 Linked List Cycle II.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * struct ListNode { 4 | * int val; 5 | * ListNode *next; 6 | * ListNode(int x) : val(x), next(NULL) {} 7 | * }; 8 | */ 9 | class Solution { 10 | public: 11 | ListNode *detectCycle(ListNode *head) { 12 | ListNode *fast = head, *slow = head; 13 | int len = 0, flag = 0; 14 | while(fast != nullptr && fast->next != nullptr) { 15 | slow = slow->next; 16 | fast = fast->next->next; 17 | if(flag == 1) 18 | ++len; 19 | if(fast == slow) { 20 | if(flag == 0) 21 | flag = 1; 22 | else 23 | break; 24 | } 25 | } 26 | if(len != 0) { 27 | fast = head; 28 | slow = head; 29 | while(len > 0) { 30 | fast = fast->next; 31 | --len; 32 | } 33 | while(fast != slow) { 34 | fast = fast->next; 35 | slow = slow->next; 36 | } 37 | return fast; 38 | } 39 | else 40 | return nullptr; 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /莱特扣的-系列/03.Pattern: Fast&Slow Pointers/README.md: -------------------------------------------------------------------------------- 1 | #### Pattern 3 : Fast&Slow Pointers (快慢指针类型) 2 | 1. [LinkedList Cycle (easy) -- LeetCode](https://leetcode.com/problems/linked-list-cycle/) 3 | 2. [Middle of the LinkedList (easy) -- LeetCode](https://leetcode.com/problems/middle-of-the-linked-list/) 4 | 3. [Happy Number (medium) -- LeetCode](https://leetcode.com/problems/happy-number/) 5 | 4. [Start of LinkedList Cycle (medium) -- LeetCode](https://leetcode.com/problems/linked-list-cycle-ii/) 6 | 7 | -------------------------------------------------------------------------------- /莱特扣的-系列/04.Pattern: Merge Intervals/01 Merge Intervals.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector> merge(vector>& intervals) { 4 | if(intervals.size() < 2) 5 | return intervals; 6 | vector> res; 7 | sort(intervals.begin(), intervals.end()); 8 | int i; 9 | for(i = 1; i < intervals.size(); ++i) { 10 | while(i < intervals.size() && intervals[i][0] <= intervals[i-1][1]) { 11 | intervals[i][0] = intervals[i-1][0]; 12 | intervals[i][1] = max(intervals[i][1], intervals[i-1][1]); 13 | ++i; 14 | } 15 | res.push_back(intervals[i-1]); 16 | } 17 | if(intervals.back() != res.back()) 18 | res.push_back(intervals.back()); 19 | return res; 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /莱特扣的-系列/04.Pattern: Merge Intervals/02 Insert Interval.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector> insert(vector>& intervals, vector& newInterval) { 4 | vector> res; 5 | vector tmp; 6 | int i = 0; 7 | while(i < intervals.size() && intervals[i][1] < newInterval[0]) { 8 | res.push_back(intervals[i++]); 9 | } 10 | tmp = newInterval; 11 | for(; i < intervals.size(); ++i) { 12 | if(tmp[0] <= intervals[i][1] && tmp[1] >= intervals[i][0]) { 13 | tmp[0] = min(tmp[0], intervals[i][0]); 14 | tmp[1] = max(tmp[1], intervals[i][1]); 15 | } 16 | else { 17 | res.push_back(tmp); 18 | tmp = intervals[i]; 19 | } 20 | } 21 | res.push_back(tmp); 22 | return res; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /莱特扣的-系列/04.Pattern: Merge Intervals/03 Interval List Intersections.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector> intervalIntersection(vector>& A, vector>& B) { 4 | vector> res; 5 | int i = 0, j = 0; 6 | while(i < A.size() && j < B.size()) { 7 | int lo = max(A[i][0], B[j][0]); 8 | int hi = min(A[i][1], B[j][1]); 9 | if(lo <= hi) { 10 | vector temp{lo, hi}; 11 | res.push_back(temp); 12 | } 13 | if(A[i][1] <= B[j][1]) 14 | ++i; 15 | else 16 | ++j; 17 | } 18 | return res; 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /莱特扣的-系列/04.Pattern: Merge Intervals/05 Non-overlapping Intervals.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int eraseOverlapIntervals(vector>& intervals) { 4 | const int ll = intervals.size(); 5 | int res = 0; 6 | if(ll == 0) 7 | return res; 8 | sort(intervals.begin(), intervals.end()); 9 | int end = intervals[0][1]; 10 | for(int i = 1; i < ll; ++i) { 11 | if(end > intervals[i][0]) { 12 | intervals[i][1] = min(intervals[i][1], end); 13 | ++res; 14 | } 15 | end = intervals[i][1]; 16 | } 17 | return res; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /莱特扣的-系列/04.Pattern: Merge Intervals/README.md: -------------------------------------------------------------------------------- 1 | #### Pattern 4 : Merge Intervals (区间合并类型) 2 | 1. [Merge Intervals (medium) -- LeetCode](https://leetcode.com/problems/merge-intervals/) 3 | 2. [Insert Interval (medium) -- LeetCode](https://leetcode.com/problems/insert-interval/) 4 | 3. [Intervals Intersection (medium) -- LeetCode](https://leetcode.com/problems/interval-list-intersections/) 5 | 4. [Conflicting Appointments (medium) -- GeeksforGeeks](https://www.geeksforgeeks.org/given-n-appointments-find-conflicting-appointments/) 6 | 5. [Non-overlapping Intervals (medium) -- LeetCode](https://leetcode.com/problems/non-overlapping-intervals/) 7 | 6. [Data Stream as Disjoint Intervals -- LeetCode](https://leetcode.com/problems/data-stream-as-disjoint-intervals/) 8 | 7. [Range Module -- LeetCode](https://leetcode.com/problems/range-module/) 9 | 10 | -------------------------------------------------------------------------------- /莱特扣的-系列/05.Pattern: Cyclic Sort/02 Missing Number.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int missingNumber(vector& nums) { 4 | const int l = nums.size(); 5 | for(int i = 0; i < l; ++i) { 6 | while(nums[i] != 0 && nums[nums[i] - 1] != nums[i]) { 7 | int temp = nums[nums[i] - 1]; 8 | nums[nums[i] - 1] = nums[i]; 9 | nums[i] = temp; 10 | } 11 | } 12 | for(int i = 0; i < l; ++i) { 13 | if(nums[i] == 0) 14 | return i + 1; 15 | } 16 | return 0; 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /莱特扣的-系列/05.Pattern: Cyclic Sort/03 Find All Numbers Disappeared in an Array.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector findDisappearedNumbers(vector& nums) { 4 | const int l = nums.size(); 5 | vector res; 6 | res.reserve(l); 7 | for(int i = 0; i < l; ++i) { 8 | while(nums[nums[i] - 1] != nums[i]) { 9 | int temp = nums[nums[i] - 1]; 10 | nums[nums[i] - 1] = nums[i]; 11 | nums[i] = temp; 12 | } 13 | } 14 | for(int i = 0; i < l; ++i) { 15 | if(nums[i] != i + 1) 16 | res.push_back(i + 1); 17 | } 18 | return res; 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /莱特扣的-系列/05.Pattern: Cyclic Sort/04 Find the Duplicate Number.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int findDuplicate(vector& nums) { 4 | int slow = nums[0], fast = nums[nums[0]]; 5 | while(slow != fast) { 6 | slow = nums[slow]; 7 | fast = nums[nums[fast]]; 8 | } 9 | fast = 0; 10 | while(slow != fast) { 11 | slow = nums[slow]; 12 | fast = nums[fast]; 13 | } 14 | return slow; 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /莱特扣的-系列/05.Pattern: Cyclic Sort/05 Find All Duplicates in an Array.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector findDuplicates(vector& nums) { 4 | const int l = nums.size(); 5 | vector res; 6 | res.reserve(l); 7 | for(int i = 0; i < l; ++i) { 8 | while(nums[nums[i] - 1] != nums[i]) { 9 | int temp = nums[nums[i] - 1]; 10 | nums[nums[i] - 1] = nums[i]; 11 | nums[i] = temp; 12 | } 13 | } 14 | for(int i = 0; i < l; ++i) { 15 | if(nums[i] != i + 1) 16 | res.push_back(nums[i]); 17 | } 18 | return res; 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /莱特扣的-系列/05.Pattern: Cyclic Sort/README.md: -------------------------------------------------------------------------------- 1 | #### Pattern 5 : Cyclic Sort (循环排序) 2 | 1. [Cyclic Sort (easy) -- Wikipedia](https://en.wikipedia.org/wiki/Cycle_sort) 3 | 2. [Find the Missing Number (easy) -- LeetCode](https://leetcode.com/problems/missing-number/) 4 | 3. [Find all Missing Numbers (easy) -- LeetCode](https://leetcode.com/problems/find-all-numbers-disappeared-in-an-array/) 5 | 4. [Find the Duplicate Number (medium) -- LeetCode](https://leetcode.com/problems/find-the-duplicate-number/) 6 | 5. [Find all Duplicate Numbers (medium) -- LeetCode](https://leetcode.com/problems/find-all-duplicates-in-an-array/) 7 | 8 | -------------------------------------------------------------------------------- /莱特扣的-系列/06.Pattern: In-place Reversal of a LinkedList/01 Reverse Linked List.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * struct ListNode { 4 | * int val; 5 | * ListNode *next; 6 | * ListNode(int x) : val(x), next(NULL) {} 7 | * }; 8 | */ 9 | class Solution { 10 | public: 11 | ListNode* reverseList(ListNode* head) { 12 | ListNode* newHead = head; 13 | if(head->next != NULL) 14 | reverseList(head->next)->next = newHead; 15 | newHead->next = NULL; 16 | return newHead; 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /莱特扣的-系列/06.Pattern: In-place Reversal of a LinkedList/02 Reverse Linked List II.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * struct ListNode { 4 | * int val; 5 | * ListNode *next; 6 | * ListNode(int x) : val(x), next(NULL) {} 7 | * }; 8 | */ 9 | class Solution { 10 | public: 11 | ListNode* reverseBetween(ListNode* head, int m, int n) { 12 | int cnt = 1; 13 | ListNode* p = head; 14 | while(p != NULL && p->next != NULL) { 15 | if(cnt < m - 1) { 16 | p = p->next; 17 | ++cnt; 18 | continue; 19 | } 20 | ListNode* q = p; 21 | ListNode* temp2 = p->next; 22 | if(m != 1) { 23 | p = p->next; 24 | temp2 = p->next; 25 | ++cnt; 26 | } 27 | while(cnt < n && p != NULL && p->next != NULL) { 28 | ListNode* temp = temp2->next; 29 | temp2->next = p; 30 | p = temp2; 31 | temp2 = temp; 32 | ++cnt; 33 | } 34 | if(m == 1) { 35 | q->next = temp2; 36 | head = p; 37 | } 38 | else{ 39 | q->next->next = temp2; 40 | q->next = p; 41 | } 42 | break; 43 | } 44 | return head; 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /莱特扣的-系列/06.Pattern: In-place Reversal of a LinkedList/03 Reverse Nodes in k-Group.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * struct ListNode { 4 | * int val; 5 | * ListNode *next; 6 | * ListNode(int x) : val(x), next(NULL) {} 7 | * }; 8 | */ 9 | class Solution { 10 | public: 11 | ListNode* reverseKGroup(ListNode* head, int k) { 12 | ListNode* p = head; 13 | int len = 0; 14 | while(p != NULL) { 15 | p = p->next; 16 | ++len; 17 | } 18 | p = head; 19 | int tol = len / k; 20 | ListNode* mid = p->next; 21 | ListNode *s1 = NULL, *s2 = NULL; 22 | ListNode *e1 = NULL, *e2 = NULL; 23 | int flag = 0; 24 | while(flag < tol) { 25 | int cnt = 1; 26 | flag % 2 == 0 ? e1 = p : e2 = p; 27 | while(cnt < k) { 28 | ListNode* temp = mid->next; 29 | mid->next = p; 30 | p = mid; 31 | mid = temp; 32 | ++cnt; 33 | } 34 | flag % 2 == 0 ? s1 = p : s2 = p; 35 | 36 | if(e2 != NULL) { 37 | flag % 2 == 0 ? e2->next = s1 : e1->next = s2; 38 | } 39 | if(flag == 0) 40 | head = p; 41 | p = mid; 42 | if(p != NULL) 43 | mid = p->next; 44 | ++flag; 45 | } 46 | flag % 2 == 0 ? e2->next = p : e1->next = p; 47 | return head; 48 | } 49 | }; 50 | -------------------------------------------------------------------------------- /莱特扣的-系列/06.Pattern: In-place Reversal of a LinkedList/README.md: -------------------------------------------------------------------------------- 1 | #### Pattern 6 : In-place Reversal of a LinkedList (链表翻转) 2 | 1. [Reverse a LinkedList (easy) -- LeetCode](https://leetcode.com/problems/reverse-linked-list/) 3 | 2. [Reverse a Sub-list (medium) -- LeetCode](https://leetcode.com/problems/reverse-linked-list-ii/) 4 | 3. [Reverse every K-element Sub-list (hard) -- LeetCode](https://leetcode.com/problems/reverse-nodes-in-k-group/) 5 | -------------------------------------------------------------------------------- /莱特扣的-系列/07.Pattern: Tree Breadth First Search/01 Binary Tree Level Order Traversal.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * struct TreeNode { 4 | * int val; 5 | * TreeNode *left; 6 | * TreeNode *right; 7 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 | * }; 9 | */ 10 | class Solution { 11 | public: 12 | vector> levelOrder(TreeNode* root) { 13 | vector> res; 14 | queue q1; 15 | queue q2; 16 | if(root != NULL) 17 | q1.push(root); 18 | vector temp; 19 | TreeNode* frt; 20 | while(!q1.empty() || !q2.empty()) { 21 | while(!q1.empty()) { 22 | frt = q1.front(); 23 | q1.pop(); 24 | if(frt->left) 25 | q2.push(frt->left); 26 | if(frt->right) 27 | q2.push(frt->right); 28 | temp.push_back(frt->val); 29 | } 30 | res.push_back(temp); 31 | temp.clear(); 32 | while(!q2.empty()) { 33 | frt = q2.front(); 34 | q2.pop(); 35 | if(frt->left) 36 | q1.push(frt->left); 37 | if(frt->right) 38 | q1.push(frt->right); 39 | temp.push_back(frt->val); 40 | } 41 | if(!temp.empty()) 42 | res.push_back(temp); 43 | temp.clear(); 44 | } 45 | return res; 46 | } 47 | }; 48 | -------------------------------------------------------------------------------- /莱特扣的-系列/07.Pattern: Tree Breadth First Search/02 Binary Tree Level Order Traversal II.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * struct TreeNode { 4 | * int val; 5 | * TreeNode *left; 6 | * TreeNode *right; 7 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 | * }; 9 | */ 10 | class Solution { 11 | public: 12 | vector> res; 13 | void levelTraversal(TreeNode* root, int level) { 14 | if(res.size() <= level) { 15 | vector temp{root->val}; 16 | res.push_back(temp); 17 | } 18 | else 19 | res[level].push_back(root->val); 20 | 21 | if(root->left) 22 | levelTraversal(root->left, level + 1); 23 | if(root->right) 24 | levelTraversal(root->right, level + 1); 25 | } 26 | vector> levelOrderBottom(TreeNode* root) { 27 | if(root != NULL) 28 | levelTraversal(root, 0); 29 | reverse(res.begin(), res.end()); 30 | return res; 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /莱特扣的-系列/07.Pattern: Tree Breadth First Search/03 Minimum Depth of Binary Tree.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * struct TreeNode { 4 | * int val; 5 | * TreeNode *left; 6 | * TreeNode *right; 7 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 | * }; 9 | */ 10 | class Solution { 11 | public: 12 | int res = 0, m = 10000; 13 | int minDepth(TreeNode* root) { 14 | if(!root) 15 | return 0; 16 | if(!root->left && !root->right) { 17 | m = min(m, res + 1); 18 | return m; 19 | } 20 | ++res; 21 | if(root->left) 22 | minDepth(root->left); 23 | if(root->right) 24 | minDepth(root->right); 25 | --res; 26 | return m; 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /莱特扣的-系列/07.Pattern: Tree Breadth First Search/05 Level Order Successor of a node in Binary Tree.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * struct TreeNode { 4 | * int val; 5 | * TreeNode *left; 6 | * TreeNode *right; 7 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 | * }; 9 | */ 10 | TreeNode* levelOrderSuccessor(TreeNode* root, TreeNode* key) { 11 | // Base Case 12 | if(root == NULL) 13 | return NULL; 14 | 15 | // If root equals to key 16 | if(root == key) { 17 | // If left child exists it will be 18 | // the Postorder Successor 19 | if (root->left) 20 | return root->left; 21 | 22 | // Else if right child exists it will be 23 | // the Postorder Successor 24 | else if (root->right) 25 | return root->right; 26 | else 27 | return NULL; // No Successor 28 | } 29 | 30 | // Create an empty queue for level order traversal 31 | queue q; 32 | 33 | // Enqueue Root 34 | q.push(root); 35 | 36 | while(!q.empty()) { 37 | TreeNode* nd = q.front(); 38 | q.pop(); 39 | 40 | if(nd->left != NULL) { 41 | q.push(nd->left); 42 | } 43 | 44 | if(nd->right != NULL) { 45 | q.push(nd->right); 46 | } 47 | 48 | if(nd == key) 49 | break; 50 | } 51 | if(q.empty()) 52 | return NULL; 53 | return q.front(); 54 | } 55 | -------------------------------------------------------------------------------- /莱特扣的-系列/07.Pattern: Tree Breadth First Search/06 Binary Tree Zigzag Level Order Traversal.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * struct TreeNode { 4 | * int val; 5 | * TreeNode *left; 6 | * TreeNode *right; 7 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 | * }; 9 | */ 10 | class Solution { 11 | public: 12 | vector> zigzagLevelOrder(TreeNode* root) { 13 | vector> res; 14 | stack s1; 15 | stack s2; 16 | if(root != NULL) 17 | s1.push(root); 18 | vector temp; 19 | TreeNode* tp; 20 | while(!s1.empty() || !s2.empty()) { 21 | while(!s1.empty()) { 22 | tp = s1.top(); 23 | s1.pop(); 24 | if(tp->left) 25 | s2.push(tp->left); 26 | if(tp->right) 27 | s2.push(tp->right); 28 | temp.push_back(tp->val); 29 | } 30 | res.push_back(temp); 31 | temp.clear(); 32 | while(!s2.empty()) { 33 | tp = s2.top(); 34 | s2.pop(); 35 | if(tp->right) 36 | s1.push(tp->right); 37 | if(tp->left) 38 | s1.push(tp->left); 39 | temp.push_back(tp->val); 40 | } 41 | if(!temp.empty()) 42 | res.push_back(temp); 43 | temp.clear(); 44 | } 45 | return res; 46 | } 47 | }; 48 | -------------------------------------------------------------------------------- /莱特扣的-系列/07.Pattern: Tree Breadth First Search/07 Populating Next Right Pointers in Each Node.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | // Definition for a Node. 3 | class Node { 4 | public: 5 | int val; 6 | Node* left; 7 | Node* right; 8 | Node* next; 9 | 10 | Node() : val(0), left(NULL), right(NULL), next(NULL) {} 11 | 12 | Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {} 13 | 14 | Node(int _val, Node* _left, Node* _right, Node* _next) 15 | : val(_val), left(_left), right(_right), next(_next) {} 16 | }; 17 | */ 18 | class Solution { 19 | public: 20 | Node* connect(Node* root) { 21 | if(!root || !root->left) 22 | return root; 23 | root->left->next = root->right; 24 | Node* l = root->left; 25 | Node* r = root->right; 26 | while(l->right && r->left) { 27 | l = l->right; 28 | r = r->left; 29 | l->next = r; 30 | } 31 | connect(root->left); 32 | connect(root->right); 33 | return root; 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /莱特扣的-系列/07.Pattern: Tree Breadth First Search/README.md: -------------------------------------------------------------------------------- 1 | #### Pattern 7 : Tree Breadth First Search (树上的BFS) 2 | 1. [Binary Tree Level Order Traversal (easy) -- LeetCode](https://leetcode.com/problems/binary-tree-level-order-traversal/) 3 | 2. [Reverse Level Order Traversal (easy) -- LeetCode](https://leetcode.com/problems/binary-tree-level-order-traversal-ii/) 4 | 3. [Minimum Depth of a Binary Tree (easy) -- Leetcode](https://leetcode.com/problems/minimum-depth-of-binary-tree/) 5 | 4. [Level Averages in a Binary Tree (easy) -- LeetCode](https://leetcode.com/problems/average-of-levels-in-binary-tree/) 6 | 5. [Level Order Successor (easy) -- GeeksforGeeks](https://www.geeksforgeeks.org/level-order-successor-of-a-node-in-binary-tree/) 7 | 6. [Zigzag Traversal (medium) -- LeetCode](https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/) 8 | 7. [Connect Level Order Siblings (medium) -- LeetCode](https://leetcode.com/problems/populating-next-right-pointers-in-each-node/) 9 | 10 | -------------------------------------------------------------------------------- /莱特扣的-系列/08.Pattern: Tree Depth First Search/01 Path Sum.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * struct TreeNode { 4 | * int val; 5 | * TreeNode *left; 6 | * TreeNode *right; 7 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 | * }; 9 | */ 10 | class Solution { 11 | public: 12 | bool hasPathSum(TreeNode* root, int sum) { 13 | if(root == NULL) 14 | return false; 15 | if(root->left == NULL && root->right == NULL && sum == root->val) 16 | return true; 17 | return hasPathSum(root->left, sum - root->val) || hasPathSum(root->right, sum - root->val); 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /莱特扣的-系列/08.Pattern: Tree Depth First Search/02 Path Sum II.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * struct TreeNode { 4 | * int val; 5 | * TreeNode *left; 6 | * TreeNode *right; 7 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 | * }; 9 | */ 10 | class Solution { 11 | public: 12 | vector> res; 13 | vector temp; 14 | vector> pathSum(TreeNode* root, int sum) { 15 | helper(root, sum); 16 | return res; 17 | } 18 | void helper(TreeNode* root, int sum) { 19 | if(root == NULL) 20 | return; 21 | temp.push_back(root->val); 22 | if(root->left == NULL && root->right == NULL && sum == root->val) { 23 | res.push_back(temp); 24 | temp.pop_back(); 25 | return; 26 | } 27 | helper(root->left, sum - root->val); 28 | helper(root->right, sum - root->val); 29 | temp.pop_back(); 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /莱特扣的-系列/08.Pattern: Tree Depth First Search/03 Sum Root to Leaf Numbers.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * struct TreeNode { 4 | * int val; 5 | * TreeNode *left; 6 | * TreeNode *right; 7 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 | * }; 9 | */ 10 | class Solution { 11 | public: 12 | int res = 0, temp = 0; 13 | int sumNumbers(TreeNode* root) { 14 | if(root == NULL) 15 | return res; 16 | temp = temp * 10 + root->val; 17 | if(root->left == NULL && root->right == NULL) { 18 | res += temp; 19 | temp /= 10; 20 | return res; 21 | } 22 | sumNumbers(root->left); 23 | sumNumbers(root->right); 24 | temp /= 10; 25 | return res; 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /莱特扣的-系列/08.Pattern: Tree Depth First Search/04 Path With Given Sequence.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * struct TreeNode { 4 | * int val; 5 | * TreeNode *left; 6 | * TreeNode *right; 7 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 | * }; 9 | */ 10 | class Solution { 11 | public: 12 | bool existPath(TreeNode* root, int seq[], int n, int idx) { 13 | if(root == NULL) 14 | return (n == 0); 15 | if(root->left == NULL && root->right == NULL && root->val == seq[idx] && idx == n - 1) 16 | return true; 17 | return (idx < n && root->val == seq[idx] && 18 | (existPath(root->left, seq, n, idx + 1) || existPath(root->right, seq, n, idx + 1))); 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /莱特扣的-系列/08.Pattern: Tree Depth First Search/05 Path Sum III.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * struct TreeNode { 4 | * int val; 5 | * TreeNode *left; 6 | * TreeNode *right; 7 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 | * }; 9 | */ 10 | class Solution { 11 | public: 12 | int pathSum(TreeNode* root, int sum) { 13 | int res = 0; 14 | unordered_map mm; 15 | helper(root, sum, mm, 0, res); 16 | return res; 17 | } 18 | void helper(TreeNode* root, int sum, unordered_map& mm, int s, int& res) { 19 | if(root) { 20 | if(s + root->val == sum) 21 | ++res; 22 | res += mm[s + root->val - sum]; 23 | ++mm[s + root->val]; 24 | helper(root->left, sum, mm, s + root->val, res); 25 | helper(root->right, sum, mm, s + root->val, res); 26 | --mm[s + root->val]; 27 | } 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /莱特扣的-系列/08.Pattern: Tree Depth First Search/README.md: -------------------------------------------------------------------------------- 1 | #### Pattern 8 : Tree Depth First Search (树上的DFS) 2 | 1. [Binary Tree Path Sum (easy) -- LeetCode](https://leetcode.com/problems/path-sum/) 3 | 2. [All Paths for a Sum (medium) -- LeetCode](https://leetcode.com/problems/path-sum-ii/) 4 | 3. [Sum of Path Numbers (medium) -- LeetCode](https://leetcode.com/problems/sum-root-to-leaf-numbers/) 5 | 4. [Path With Given Sequence (medium) -- GeeksforGeeks](https://www.geeksforgeeks.org/check-root-leaf-path-given-sequence/) 6 | 5. [Count Paths for a Sum (medium) -- LeetCode](https://leetcode.com/problems/path-sum-iii/) 7 | -------------------------------------------------------------------------------- /莱特扣的-系列/09.Pattern: Two Heaps/01 Find Median from Data Stream.cpp: -------------------------------------------------------------------------------- 1 | class MedianFinder { 2 | public: 3 | /** initialize your data structure here. */ 4 | int cnt; 5 | priority_queue, less> maxheap; 6 | priority_queue, greater> minheap; 7 | MedianFinder() { 8 | cnt = 0; 9 | } 10 | 11 | void addNum(int num) { 12 | if(cnt % 2 == 0) { 13 | maxheap.push(num); 14 | minheap.push(maxheap.top()); 15 | maxheap.pop(); 16 | } 17 | else { 18 | minheap.push(num); 19 | maxheap.push(minheap.top()); 20 | minheap.pop(); 21 | } 22 | ++cnt; 23 | } 24 | 25 | double findMedian() { 26 | if(cnt % 2 == 0) 27 | return (double)(maxheap.top() + minheap.top()) / 2; 28 | else 29 | return minheap.top(); 30 | } 31 | }; 32 | 33 | /** 34 | * Your MedianFinder object will be instantiated and called as such: 35 | * MedianFinder* obj = new MedianFinder(); 36 | * obj->addNum(num); 37 | * double param_2 = obj->findMedian(); 38 | */ 39 | -------------------------------------------------------------------------------- /莱特扣的-系列/09.Pattern: Two Heaps/03 IPO.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int findMaximizedCapital(int k, int W, vector& Profits, vector& Capital) { 4 | const int l = Profits.size(); 5 | priority_queue, less> maxheap; 6 | priority_queue, vector>, greater>> minheap; 7 | for(int i = 0; i < l; ++i) { 8 | if(Profits[i] > 0) { 9 | if(Capital[i] <= W) 10 | maxheap.push(Profits[i]); 11 | else 12 | minheap.emplace(Capital[i], Profits[i]); 13 | } 14 | } 15 | while(k-- && !maxheap.empty()) { 16 | W += maxheap.top(); 17 | maxheap.pop(); 18 | while(!minheap.empty() && minheap.top().first <= W) { 19 | maxheap.push(minheap.top().second); 20 | minheap.pop(); 21 | } 22 | } 23 | return W; 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /莱特扣的-系列/09.Pattern: Two Heaps/README.md: -------------------------------------------------------------------------------- 1 | #### Pattern 9 : Two Heaps (双堆类型) 2 | 1. [Find the Median of a Number Stream (medium) -- LeetCode](https://leetcode.com/problems/find-median-from-data-stream/) 3 | 2. [Sliding Window Median (hard) -- LeetCode](https://leetcode.com/problems/sliding-window-median/) 4 | 3. [Maximize Capital (hard) -- LeetCode](https://leetcode.com/problems/ipo/) 5 | 6 | -------------------------------------------------------------------------------- /莱特扣的-系列/10.Pattern: Subsets/01 Subsets.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector> res; 4 | vector> subsets(vector& nums) { 5 | helper(0, nums, {}); 6 | return res; 7 | } 8 | 9 | void helper(int i, vector& nums, vector subset) { 10 | res.push_back(subset); 11 | for(int j = i; j < nums.size(); ++j) { 12 | subset.push_back(nums[j]); 13 | helper(j + 1, nums, subset); 14 | subset.pop_back(); 15 | } 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /莱特扣的-系列/10.Pattern: Subsets/02 Subsets II.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector> subsetsWithDup(vector& nums) { 4 | vector> res = {{}}; 5 | sort(nums.begin(), nums.end()); 6 | int start; 7 | for(int i = 0; i < nums.size(); ++i) { 8 | if(i == 0 || nums[i] != nums[i-1]) start = 0; 9 | for(int end = res.size(); start < end; ++start) { 10 | vector tmp = res[start]; 11 | tmp.push_back(nums[i]); 12 | res.push_back(move(tmp)); 13 | } 14 | } 15 | return res; 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /莱特扣的-系列/10.Pattern: Subsets/03 Permutations.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector> permute(vector& nums) { 4 | vector> res; 5 | helper(nums, 0, res); 6 | return res; 7 | } 8 | 9 | void helper(vector& nums, int i, vector>& res) { 10 | if(i >= nums.size()) { 11 | res.push_back(nums); 12 | return; 13 | } 14 | for(int j = i; j < nums.size(); ++j) { 15 | swap(nums[i], nums[j]); 16 | helper(nums, i + 1, res); 17 | swap(nums[i], nums[j]); 18 | } 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /莱特扣的-系列/10.Pattern: Subsets/04 Letter Case Permutation.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Input : ab 3 | Output : AB Ab ab aB 4 | 5 | Input : ABC 6 | Output : abc Abc aBc ABc abC AbC aBC ABC 7 | */ 8 | 9 | vector letterCasePermutation(string S) { 10 | vector res; 11 | int n = S.length(); 12 | int maxn = 1 << n; 13 | transform(S.begin(), S.end(), S.begin(), ::tolower); 14 | for(int i = 0; i < maxn; ++i) { 15 | string tmp = S; 16 | for(int j = 0; j < n; ++j) { 17 | if((i >> j) & 1) 18 | tmp[j] = toupper(S[j]); 19 | } 20 | res.push_back(tmp); 21 | } 22 | return res; 23 | } 24 | -------------------------------------------------------------------------------- /莱特扣的-系列/10.Pattern: Subsets/05 Minimum Remove to Make Valid Parentheses.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | string minRemoveToMakeValid(string s) { 4 | stack stk; 5 | string res; 6 | for(int i = 0; i < s.length(); ++i) { 7 | if(s[i] == '(') 8 | stk.push(i); 9 | if(s[i] == ')') { 10 | if(!stk.empty()) 11 | stk.pop(); 12 | else 13 | s[i] = '*'; 14 | } 15 | } 16 | while(!stk.empty()) { 17 | s[stk.top()] = '*'; 18 | stk.pop(); 19 | } 20 | for(auto& c : s) { 21 | if(c != '*') 22 | res += c; 23 | } 24 | return res; 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /莱特扣的-系列/10.Pattern: Subsets/07 Generalized Abbreviation.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | /** 4 | * @param word: the given word 5 | * @return: the generalized abbreviations of a word 6 | */ 7 | vector generateAbbreviations(string &word) { 8 | int n = word.length(); 9 | int maxN = 1 << n; 10 | vector res; 11 | res.reserve(maxN); 12 | for(int i = 0; i < maxN; ++i) { 13 | string tmps; 14 | int t = 0; 15 | for(int j = 0; j < n; ++j) { 16 | if((i >> j) & 1 == 1) 17 | ++t; 18 | else { 19 | if(t != 0) { 20 | tmps += to_string(t); 21 | t = 0; 22 | } 23 | tmps += word[j]; 24 | } 25 | } 26 | if(t != 0) 27 | tmps += to_string(t); 28 | res.push_back(tmps); 29 | } 30 | return res; 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /莱特扣的-系列/10.Pattern: Subsets/README.md: -------------------------------------------------------------------------------- 1 | #### Pattern 10 : Subsets (子集类型,一般都是使用多重DFS) 2 | 1. [Subsets (easy) -- LeetCode](https://leetcode.com/problems/subsets/) 3 | 2. [Subsets With Duplicates (easy) -- LeetCode](https://leetcode.com/problems/subsets-ii/) 4 | 3. [Permutations (medium) -- LeetCode](https://leetcode.com/problems/permutations/) 5 | 4. [String Permutations by changing case (medium) -- GeeksforGeeks](https://www.geeksforgeeks.org/permute-string-changing-case/) 6 | 5. [Minimum Remove to Make Valid Parentheses (medium) -- LeetCode](https://leetcode.com/problems/minimum-remove-to-make-valid-parentheses/) 7 | 6. [Balanced Parentheses (hard) -- LeetCode](https://bradfieldcs.com/algos/stacks/balanced-parentheses/) 8 | 7. [Unique Generalized Abbreviations (hard) -- LintCode](https://www.lintcode.com/problem/generalized-abbreviation/) 9 | 10 | -------------------------------------------------------------------------------- /莱特扣的-系列/11.Pattern: Modified Binary Search/1. Maximum sum Bi-tonic Sub-sequence.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int maxSumBitonicSubArr(int arr[], int n) { 5 | int msis[n], msds[n]; 6 | msis[0] = arr[0]; 7 | msds[n-1] = arr[n-1]; 8 | for(int i = 1; i < n; ++i) { 9 | if(arr[i] > arr[i-1]) 10 | msis[i] = msis[i-1] + arr[i]; 11 | else 12 | msis[i] = arr[i]; 13 | } 14 | for(int i = n-2; i >= 0; --i) { 15 | if(arr[i] > arr[i+1] 16 | msds[i] = msds[i+1] + arr[i]; 17 | else 18 | msds[i] = arr[i]; 19 | } 20 | for (int i = 0; i < n; ++i) 21 | max_sum = max(max_sum, msis[i] + msds[i] - arr[i]); 22 | 23 | return max_sum; 24 | } 25 | -------------------------------------------------------------------------------- /莱特扣的-系列/11.Pattern: Modified Binary Search/2. Order-Agnostic Binary Search.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int binarySearch(int arr[], int key) { 5 | int n = sizeof(arr) / sizeof(arr[0]); 6 | int start = 0, end = n - 1; 7 | bool isAscending = arr[n-1] > arr[0]; 8 | while(start <= end) { 9 | // the safest way to find the middle of two numbers without getting an overflow 10 | int mid = start + (end - start) / 2; 11 | 12 | if(arr[mid] == key) 13 | return mid; 14 | 15 | if(isAscending) { 16 | if(key > arr[mid]) 17 | start = mid + 1; 18 | else 19 | end = mid - 1; 20 | } 21 | else { 22 | if(key < arr[mid]) 23 | start = mid + 1; 24 | else 25 | end = mid - 1; 26 | } 27 | } 28 | return -1; 29 | } 30 | -------------------------------------------------------------------------------- /莱特扣的-系列/11.Pattern: Modified Binary Search/3. Ceiling of a Number.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | string minimizeError(vector& prices, int target) { 4 | int n = prices.size(); 5 | double ceil_sum = 0.0, floor_sum = 0.0; 6 | vector diffs; 7 | for(auto& str : prices) { 8 | double tmp = stod(str); 9 | ceil_sum += ceil(tmp); 10 | floor_sum += floor(tmp); 11 | diffs.push_back(tmp - floor(tmp)); 12 | } 13 | if(ceil_sum < target || floor_sum > target) 14 | return "-1"; 15 | sort(diffs.begin(), diffs.end()); 16 | target = n + floor_sum - target; 17 | double res = 0.0; 18 | for(int i = 0; i < n; ++i) { 19 | if(i < target) 20 | res += diffs[i]; 21 | else 22 | res += 1 - diffs[i]; 23 | } 24 | return to_string(res); 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /莱特扣的-系列/11.Pattern: Modified Binary Search/4. Find Smallest Letter Greater Than Target.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | char nextGreatestLetter(vector& letters, char target) { 4 | const int n = letters.size(); 5 | if(target < letters[0] || target > letters[n - 1]) 6 | return letters[0]; 7 | 8 | int start = 0, end = n - 1, mid = 0; 9 | while(start <= end) { 10 | mid = start + (end - start) / 2; 11 | if(letters[mid] == target) 12 | break; 13 | if(target > letters[mid]) 14 | start = mid + 1; 15 | else 16 | end = mid - 1; 17 | } 18 | while(mid < n) { 19 | if(letters[mid] > target) 20 | return letters[mid]; 21 | ++mid; 22 | } 23 | return letters[0]; 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /莱特扣的-系列/11.Pattern: Modified Binary Search/5. Find First and Last Position of Element in Sorted Array.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector searchRange(vector& nums, int target) { 4 | vector res(2, -1); 5 | const int n = nums.size(); 6 | if(n == 0) return res; 7 | // lower_bound of target 8 | int low = lower_bound(nums, target); 9 | // lower_bound of target + 1 10 | int high = lower_bound(nums, target + 1) - 1; 11 | 12 | if(low < n && nums[low] == target) 13 | return vector{low, high}; 14 | return res; 15 | } 16 | 17 | int lower_bound(vector& nums, int target) { 18 | int start = 0, end = nums.size() - 1; 19 | while(start <= end) { 20 | int mid = start + (end - start) / 2; 21 | if(nums[mid] < target) 22 | start = mid + 1; 23 | else 24 | end = mid - 1; 25 | } 26 | return start; 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /莱特扣的-系列/11.Pattern: Modified Binary Search/6. Search in a Sorted Infinite Array.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int binarySearch(int arr[], int key) { 5 | // find the lower_bound and upper_bound 6 | int start = 0, end = 1; 7 | while(arr[end] < key) { 8 | start = end; 9 | end = 2 * start; 10 | } 11 | while(start <= end) { 12 | // the safest way to find the middle of two numbers without getting an overflow 13 | int mid = start + (end - start) / 2; 14 | 15 | if(arr[mid] == key) 16 | return mid; 17 | 18 | if(key > arr[mid]) 19 | start = mid + 1; 20 | else 21 | end = mid - 1; 22 | } 23 | return -1; 24 | } 25 | -------------------------------------------------------------------------------- /莱特扣的-系列/11.Pattern: Modified Binary Search/7. Kth Smallest Element in a Sorted Matrix.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int kthSmallest(vector>& matrix, int k) { 4 | int n = matrix.size(); 5 | int low = matrix[0][0], high = matrix[n - 1][n - 1]; 6 | while(low <= high) { 7 | int mid = low + (high - low) / 2; 8 | int num = 0, j = n - 1; 9 | for (int i = 0; i < n; ++i) { 10 | while(j >= 0 && matrix[i][j] > mid) 11 | --j; 12 | num += j + 1; 13 | } 14 | if(num < k) { 15 | low = mid + 1; 16 | } 17 | else { 18 | high = mid - 1; 19 | } 20 | } 21 | return low; 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /莱特扣的-系列/11.Pattern: Modified Binary Search/8. Median of Two Sorted Arrays.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | double findMedianSortedArrays(vector& nums1, vector& nums2) { 4 | if(nums1.size() > nums2.size()) 5 | return findMedianSortedArrays(nums2, nums1); 6 | int x = nums1.size(); 7 | int y = nums2.size(); 8 | int l = 0; 9 | int r = x; 10 | while(l <= r) { 11 | int leftpartX = l + (r - l) / 2; 12 | int leftpartY = (x + y + 1) / 2 - leftpartX; 13 | 14 | int maxleftX = leftpartX == 0 ? INT_MIN : nums1[leftpartX - 1]; 15 | int minrightX = leftpartX == x ? INT_MAX : nums1[leftpartX]; 16 | 17 | int maxleftY = leftpartY == 0 ? INT_MIN : nums2[leftpartY - 1]; 18 | int minrightY = leftpartY == y ? INT_MAX : nums2[leftpartY]; 19 | 20 | if(maxleftX <= minrightY && maxleftY <= minrightX) { 21 | if((x + y) % 2 == 0) 22 | return double((max(maxleftX, maxleftY) + min(minrightX, minrightY))) / 2; 23 | else 24 | return max(maxleftX, maxleftY); 25 | } 26 | else if(maxleftX > minrightY) 27 | r = leftpartX - 1; 28 | else 29 | l = leftpartX + 1; 30 | } 31 | return 0.0; 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /莱特扣的-系列/11.Pattern: Modified Binary Search/README.md: -------------------------------------------------------------------------------- 1 | #### Pattern 11 : Modified Binary Search (改造过的二分) 2 | 1. [Bitonic Array Maximum (easy) -- GeeksforGeeks](https://www.geeksforgeeks.org/maximum-sum-bitonic-subarray/) 3 | 2. [Order-agnostic Binary Search (easy) -- Medium Blog](https://medium.com/better-programming/three-smart-ways-to-use-binary-search-in-coding-interviews-250ba296cb82) 4 | 3. [Ceiling of a Number (medium) -- LeetCode](https://github.com/openset/leetcode/tree/master/problems/minimize-rounding-error-to-meet-target) 5 | 4. [Next Letter (medium) -- LeetCode](https://leetcode.com/problems/find-smallest-letter-greater-than-target/) 6 | 5. [Number Range (medium) -- LeetCode](https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/) 7 | 6. [Search in a Sorted Infinite Array (medium) -- GeeksforGeeks](https://www.geeksforgeeks.org/find-position-element-sorted-array-infinite-numbers/) 8 | 7. [Kth Smallest Element in a Sorted Matrix (medium) -- LeetCode](https://leetcode.com/problems/kth-smallest-element-in-a-sorted-matrix/) 9 | 8. [Median of Two Sorted Arrays (hard) -- LeetCode](https://leetcode.com/problems/median-of-two-sorted-arrays/) 10 | -------------------------------------------------------------------------------- /莱特扣的-系列/12.Pattern: Top ‘K’ Elements/1. K Closest Points to Origin.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector> kClosest(vector>& points, int K) { 4 | vector> res; 5 | priority_queue, vector>, comp> pq; 6 | for(auto& p : points) { 7 | pq.push(p); 8 | if(pq.size() > K) 9 | pq.pop(); 10 | } 11 | while(!pq.empty()) { 12 | res.push_back(pq.top()); 13 | pq.pop(); 14 | } 15 | return res; 16 | } 17 | 18 | struct comp { 19 | bool operator() (vector& a, vector& b) { 20 | return a[0] * a[0] + a[1] * a[1] < b[0] * b[0] + b[1] * b[1]; 21 | } 22 | }; 23 | }; 24 | -------------------------------------------------------------------------------- /莱特扣的-系列/12.Pattern: Top ‘K’ Elements/2. Min Cost to Connect Ropes.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int minCost(vector& ropes) { 4 | int tolCost = 0; 5 | priority_queue, greater<>> pq; // min-heap 6 | for(auto& rope : ropes) 7 | pq.push(rope); 8 | while(pq.size() > 1) { 9 | int a = pq.top(); 10 | pq.pop(); 11 | int b = pq.top(); 12 | pq.pop(); 13 | tolCost += a + b; 14 | pq.push(a + b); 15 | } 16 | return tolCost; 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /莱特扣的-系列/12.Pattern: Top ‘K’ Elements/3. Top K Frequent Elements.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector topKFrequent(vector& nums, int k) { 4 | unordered_map mm; 5 | for(auto& n : nums) { 6 | ++mm[n]; 7 | } 8 | priority_queue< pair, vector>, greater_comp > pq; 9 | for(auto& x : mm) { 10 | pq.push(x); 11 | if(pq.size() > k) 12 | pq.pop(); 13 | } 14 | vector res; 15 | while(!pq.empty()) { 16 | res.push_back(pq.top().first); 17 | pq.pop(); 18 | } 19 | return res; 20 | } 21 | 22 | struct greater_comp { 23 | bool operator() (pair& a, pair& b) { 24 | return a.second > b.second; 25 | } 26 | }; 27 | }; 28 | -------------------------------------------------------------------------------- /莱特扣的-系列/12.Pattern: Top ‘K’ Elements/4. Sort Characters By Frequency.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | string frequencySort(string s) { 4 | int l = s.length(); 5 | unordered_map mm; 6 | for(auto& c : s) 7 | ++mm[c]; 8 | priority_queue< pair, vector>, less_comp > pq; 9 | for(auto& x : mm) 10 | pq.push(x); 11 | 12 | string res; 13 | while(!pq.empty()) { 14 | for(int i = 0; i < pq.top().second; ++i) 15 | res += pq.top().first; 16 | pq.pop(); 17 | } 18 | return res; 19 | } 20 | 21 | struct less_comp { 22 | bool operator() (pair& a, pair& b) { 23 | return a.second < b.second; 24 | } 25 | }; 26 | }; 27 | -------------------------------------------------------------------------------- /莱特扣的-系列/12.Pattern: Top ‘K’ Elements/5. Kth Largest Element in an Array.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int findKthLargest(vector& nums, int k) { 4 | priority_queue< int, vector, greater<> > pq; // min-heap 5 | for(auto& x : nums) { 6 | pq.push(x); 7 | if(pq.size() > k) 8 | pq.pop(); 9 | } 10 | return pq.top(); 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /莱特扣的-系列/12.Pattern: Top ‘K’ Elements/6. Find K Closest Elements.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector findClosestElements(vector& arr, int k, int x) { 4 | int l = 0, r = arr.size() - k; 5 | while(l < r) { 6 | int mid = l + (r - l) / 2; 7 | if(x - arr[mid] > arr[mid + k] - x) 8 | l = mid + 1; 9 | else 10 | r = mid; 11 | } 12 | return vector(arr.begin() + l, arr.begin() + l + k); 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /莱特扣的-系列/12.Pattern: Top ‘K’ Elements/8. Reorganize String.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | string reorganizeString(string S) { 4 | unordered_map mm; 5 | for(auto& c : S) 6 | ++mm[c]; 7 | priority_queue< pair, vector>, less<> > pq; 8 | for(auto& m : mm) 9 | pq.push(make_pair(m.second, m.first)); 10 | 11 | string res; 12 | while(!pq.empty()) { 13 | auto t = pq.top(); 14 | pq.pop(); 15 | while(t.first > 0 && !pq.empty()) { 16 | res += t.second; 17 | auto p = pq.top(); 18 | pq.pop(); 19 | res += p.second; 20 | --p.first; 21 | if(p.first != 0) 22 | pq.push(p); 23 | --t.first; 24 | } 25 | if(t.first > 0) { 26 | if (t.first >= 2 || t.second == res.back()) 27 | return ""; 28 | else 29 | res += t.second; 30 | } 31 | } 32 | return res; 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /莱特扣的-系列/12.Pattern: Top ‘K’ Elements/README.md: -------------------------------------------------------------------------------- 1 | #### Pattern 12 : Top ‘K’ Elements -- Heap (前K个系列) 2 | 1. [‘K’ Closest Points to the Origin (easy) -- LeetCode](https://leetcode.com/problems/k-closest-points-to-origin/) 3 | 2. [Connect Ropes (easy) -- LeetCode](https://leetcode.com/discuss/interview-question/344677/Amazon-or-Online-Assessment-2019-or-Min-Cost-to-Connect-Ropes) 4 | 3. [Top ‘K’ Frequent Numbers (medium) -- LeetCode](https://leetcode.com/problems/top-k-frequent-elements/) 5 | 4. [Frequency Sort (medium) -- LeetCode](https://leetcode.com/problems/sort-characters-by-frequency/) 6 | 5. [Kth Largest Number in a Stream (medium) - LeetCode](https://leetcode.com/problems/kth-largest-element-in-an-array/) 7 | 6. [‘K’ Closest Numbers (medium) -- LeetCode](https://leetcode.com/problems/find-k-closest-elements/) 8 | 7. [Maximum Distinct Elements (medium) -- GeeksforGeeks](https://www.geeksforgeeks.org/maximum-distinct-elements-removing-k-elements/) 9 | 8. [Rearrange String (medium) -- LeetCode](https://leetcode.com/problems/reorganize-string/) 10 | -------------------------------------------------------------------------------- /莱特扣的-系列/13.Pattern: K-Way Merge/1. Merge k Sorted Lists.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * struct ListNode { 4 | * int val; 5 | * ListNode *next; 6 | * ListNode(int x) : val(x), next(NULL) {} 7 | * }; 8 | */ 9 | class Solution { 10 | public: 11 | ListNode* mergeKLists(vector& lists) { 12 | priority_queue< int, vector, greater<> > pq; 13 | for(auto& head : lists) { 14 | while(head != nullptr) { 15 | pq.push(head->val); 16 | head = head->next; 17 | } 18 | } 19 | if(pq.empty()) 20 | return nullptr; 21 | ListNode* p = new ListNode(pq.top()); 22 | ListNode* res = p; 23 | pq.pop(); 24 | while(!pq.empty()) { 25 | p->next = new ListNode(pq.top()); 26 | pq.pop(); 27 | p = p->next; 28 | } 29 | return res; 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /莱特扣的-系列/13.Pattern: K-Way Merge/3, Kth Smallest Element in a Sorted Matrix.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int kthSmallest(vector>& matrix, int k) { 4 | // Binary Search 5 | int n = matrix.size(); 6 | int low = matrix[0][0], high = matrix[n - 1][n - 1]; 7 | while(low <= high) { 8 | int mid = low + (high - low) / 2; 9 | int num = 0, j = n - 1; 10 | for(int i = 0; i < n; ++i) { 11 | while(j >= 0 && matrix[i][j] > mid) 12 | --j; 13 | num += j + 1; 14 | } 15 | if(num < k) { 16 | low = mid + 1; 17 | } 18 | else { 19 | high = mid - 1; 20 | } 21 | } 22 | return low; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /莱特扣的-系列/13.Pattern: K-Way Merge/4. Smallest Range Covering Elements from K Lists.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector smallestRange(vector>& nums) { 4 | typedef vector::iterator vi; 5 | 6 | struct comp { 7 | bool operator()(pair p1, pair p2) { 8 | return *p1.first > *p2.first; 9 | } 10 | }; 11 | 12 | int lo = INT_MAX, hi = INT_MIN; 13 | priority_queue< pair, vector >, comp> pq; // min-heap 14 | for(auto& row : nums) { 15 | lo = min(lo, row[0]); 16 | hi = max(hi, row[0]); 17 | pq.push({row.begin(), row.end()}); 18 | } 19 | vector res{lo, hi}; 20 | while(!pq.empty()) { 21 | auto p = pq.top(); 22 | cout << *p.first << " "; 23 | pq.pop(); 24 | ++p.first; 25 | if(p.first == p.second) 26 | break; 27 | pq.push(p); 28 | lo = *(pq.top().first); 29 | hi = max(hi, *p.first); 30 | if (hi - lo < res[1] - res[0]) 31 | res = {lo, hi}; 32 | } 33 | return res; 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /莱特扣的-系列/13.Pattern: K-Way Merge/README.md: -------------------------------------------------------------------------------- 1 | #### Pattern 13 : K-Way Merge -- Heap (多路归并) 2 | 1. [Merge K Sorted Lists (hard) -- LeetCode](https://leetcode.com/problems/merge-k-sorted-lists/) 3 | 2. [Kth Smallest Number in M Sorted Lists (medium) -- GeeksforGeeks](https://www.geeksforgeeks.org/find-m-th-smallest-value-in-k-sorted-arrays/) 4 | 3. [Kth Smallest Number in a Sorted Matrix (medium) -- LeetCode](https://leetcode.com/problems/kth-smallest-element-in-a-sorted-matrix/) 5 | 4. [Smallest Number Range (Hard) -- LeetCode](https://leetcode.com/problems/smallest-range-covering-elements-from-k-lists/) 6 | 7 | -------------------------------------------------------------------------------- /莱特扣的-系列/14.Pattern: 01 Knapsack (Dynamic Programming)/2. Partition Equal Subset Sum.cpp: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/problems/partition-equal-subset-sum/discuss/90592/01-knapsack-detailed-explanation 2 | class Solution { 3 | public: 4 | bool canPartition(vector& nums) { 5 | int sum = 0; 6 | 7 | for (auto& num : nums) 8 | sum += num; 9 | 10 | if ((sum & 1) == 1) 11 | return false; 12 | 13 | sum /= 2; 14 | 15 | int n = nums.size(); 16 | bool dp[sum + 1]; 17 | memset(dp, false, sum + 1); 18 | dp[0] = true; 19 | 20 | for (int& num : nums) { 21 | for (int i = sum; i >= num; --i) { 22 | dp[i] = dp[i] || dp[i - num]; 23 | } 24 | } 25 | 26 | return dp[sum]; 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /莱特扣的-系列/14.Pattern: 01 Knapsack (Dynamic Programming)/4. Constrained Subset Sum.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int constrainedSubsetSum(vector& nums, int k) { 4 | int n = nums.size(); 5 | int dp[n]; 6 | int M = INT_MIN; 7 | deque dk; // sliding window maximum 8 | 9 | for(int i = 0; i < n; ++i) { 10 | dp[i] = nums[i] + max(0, dk.empty() ? 0 : dp[dk.front()]); 11 | while(!dk.empty() && dk.front() < i - k + 1) 12 | dk.pop_front(); 13 | while(!dk.empty() && dp[i] > dp[dk.back()]) 14 | dk.pop_back(); 15 | dk.push_back(i); 16 | M = max(M, dp[i]); 17 | } 18 | 19 | return M; 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /莱特扣的-系列/14.Pattern: 01 Knapsack (Dynamic Programming)/5. Minimum Partition.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | /** 4 | * @param nums: the given array 5 | * @return: the minimum difference between their sums 6 | */ 7 | int findMin(vector &nums) { 8 | int sum = 0; 9 | 10 | for (auto& num : nums) 11 | sum += num; 12 | 13 | int M = sum / 2; 14 | 15 | int n = nums.size(); 16 | vector dp(M + 1, false); 17 | dp[0] = true; 18 | 19 | for (int& num : nums) { 20 | for (int i = M; i >= num; --i) { 21 | dp[i] = dp[i] || dp[i - num]; 22 | } 23 | } 24 | 25 | for (int j = M; j >= 0; --j) { 26 | if (dp[j] == true) { 27 | sum -= 2 * j; 28 | break; 29 | } 30 | } 31 | return sum; 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /莱特扣的-系列/14.Pattern: 01 Knapsack (Dynamic Programming)/README.md: -------------------------------------------------------------------------------- 1 | #### Pattern 14 : 0/1 Knapsack (Dynamic Programming) (0/1背包类型) 2 | 1. [0/1 Knapsack (medium) -- GeeksforGeeks](https://www.geeksforgeeks.org/0-1-knapsack-problem-dp-10/) 3 | 2. [Equal Subset Sum Partition (medium) -- LeetCode](https://leetcode.com/problems/partition-equal-subset-sum/) 4 | 3. [Subset Sum (medium) -- GeeksforGeeks](https://www.geeksforgeeks.org/subset-sum-problem-dp-25/) 5 | 4. [Constrained Subset Sum (hard) -- LeetCode](https://leetcode.com/problems/constrained-subset-sum/) 6 | 5. [Minimum Partition (hard) -- LintCode](https://www.lintcode.com/problem/minimum-partition/description) 7 | 6. [Minimum Subset Sum Difference (hard) -- GeeksforGeeks](https://www.geeksforgeeks.org/partition-a-set-into-two-subsets-such-that-the-difference-of-subset-sums-is-minimum/) 8 | 9 | -------------------------------------------------------------------------------- /莱特扣的-系列/15.Pattern: Topological Sort (Graph)/1. Topological Sort.cpp: -------------------------------------------------------------------------------- 1 | void TopologicalSortUnit(int v, vector>& adjList, vector& visited, stack& stk) { 2 | visited[v] = true; 3 | for(auto x : adjList[v]) { 4 | if(!visited[x]) 5 | TopologicalSortUnit(x, adjList, visited, stk); 6 | } 7 | stk.push(v); 8 | } 9 | 10 | void TopologicalSort(vector>& adjList) { 11 | stack stk; 12 | const int n = adjList.size(); 13 | vector visited(n, false); 14 | for(int v = 0; v < n; ++v) { 15 | if(!visited[v]) 16 | TopologicalSortUnit(v, adjList, visited, stk); 17 | } 18 | while(!stk.empty()) { 19 | cout << stk.top() << " "; 20 | stk.pop(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /莱特扣的-系列/15.Pattern: Topological Sort (Graph)/2. Course Schedule.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | bool canFinish(int numCourses, vector>& prerequisites) { 4 | // topological sort 5 | vector> adjList(numCourses, vector()); 6 | vector inDegree(numCourses, 0); 7 | for(auto& p : prerequisites) { 8 | adjList[p[1]].push_back(p[0]); 9 | ++inDegree[p[0]]; // in-degree + 1 10 | } 11 | queue q; 12 | for(int i = 0; i < numCourses; ++i) 13 | if(inDegree[i] == 0) 14 | q.push(i); 15 | 16 | while(!q.empty()) { 17 | int cur = q.front(); 18 | q.pop(); 19 | --numCourses; 20 | for(auto v : adjList[cur]) { 21 | if(--inDegree[v] == 0) 22 | q.push(v); 23 | } 24 | } 25 | return numCourses == 0; 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /莱特扣的-系列/15.Pattern: Topological Sort (Graph)/3. Course Schedule II.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector findOrder(int numCourses, vector>& prerequisites) { 4 | vector res; 5 | vector inDegree(numCourses, 0); 6 | vector> adjList(numCourses, vector()); 7 | for(auto& p : prerequisites) { 8 | adjList[p[1]].push_back(p[0]); 9 | ++inDegree[p[0]]; 10 | } 11 | queue q; 12 | for(int i = 0; i < numCourses; ++i) { 13 | if(inDegree[i] == 0) 14 | q.push(i); 15 | } 16 | while(!q.empty()) { 17 | int cur = q.front(); 18 | res.push_back(cur); 19 | q.pop(); 20 | --numCourses; 21 | for(auto v : adjList[cur]) { 22 | if(--inDegree[v] == 0) 23 | q.push(v); 24 | } 25 | } 26 | return numCourses == 0 ? res : vector(); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /莱特扣的-系列/15.Pattern: Topological Sort (Graph)/README.md: -------------------------------------------------------------------------------- 1 | #### Pattern 15 : Topological Sort(Graph) (拓扑排序类型) 2 | 1. [Topological Sort (medium) -- GeeksforGeeks](https://www.geeksforgeeks.org/topological-sorting/) 3 | 2. [Tasks Scheduling (medium) -- LeetCode](https://leetcode.com/problems/course-schedule/) 4 | 3. [Tasks Scheduling Order (medium) -- LeetCode](https://leetcode.com/problems/course-schedule-ii/) 5 | 4. [All Tasks Scheduling Orders (hard) -- GeeksforGeeks](https://www.geeksforgeeks.org/find-the-ordering-of-tasks-from-given-dependencies/)(the same as "Tasks Scheduling Order") 6 | 5. [Alien Dictionary (hard) -- LintCode](https://www.lintcode.com/problem/alien-dictionary/description) 7 | -------------------------------------------------------------------------------- /莱特扣的-系列/16.Pattern: Design a XXX/2. Design Hit Counter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | class HitCounter { 5 | vector times, hits; 6 | int during; 7 | 8 | public: 9 | HitCounter(int n) : during(n) { 10 | times.resize(n); 11 | hits.resize(n); 12 | } 13 | 14 | void hit(int timestamp) { 15 | int idx = timestamp % during; 16 | if(times[idx] != timestamp) { 17 | times[idx] = timestamp; 18 | hits[idx] = 1; 19 | } 20 | else 21 | ++hits[idx]; 22 | } 23 | 24 | int getHits(int timestamp) { 25 | int res = 0; 26 | for(int i = 0; i < during; ++i) { 27 | if(timestamp - times[i] < during) 28 | res += hits[i]; 29 | } 30 | return res; 31 | } 32 | }; 33 | 34 | int main() { 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /莱特扣的-系列/16.Pattern: Design a XXX/README.md: -------------------------------------------------------------------------------- 1 | #### Design a XXX 2 | * [Design LRU Cache](https://leetcode.com/problems/lru-cache/) 3 | * [Design Twitter -- LeetCode](https://leetcode.com/problems/design-twitter/) 4 | * [Design Hit Counter -- LeetCode](https://leetcode.com/problems/design-hit-counter/) 5 | * [Design Circular Queue -- LeetCode](https://leetcode.com/problems/design-circular-queue/) 6 | 7 | -------------------------------------------------------------------------------- /莱特扣的-系列/README.md: -------------------------------------------------------------------------------- 1 | ## LeetCode系列-按类型刷题 2 | [Grokking the Coding Interview: Patterns for Coding Questions](https://www.educative.io/courses/grokking-the-coding-interview?aff=K7qB) 3 | 4 | --------------------------------------------------------------------------------