├── .gitignore ├── Algorithm ├── graph │ ├── 3.最小生成树.md │ └── 4.最短路径.md ├── math │ ├── 2.前缀和差分.md │ └── 约瑟夫问题.md ├── sort │ ├── mySort.h │ └── mySort_Demo.cpp ├── Search │ └── Search.cpp ├── TicTacToe │ ├── Demo.png │ ├── main.cpp │ ├── Makefile │ ├── ReadMe.md │ ├── TicTacToe.h │ └── ChessBoard.h ├── UnionFind │ ├── UnionFind.cpp │ └── union-find.md ├── ShortestPaths │ ├── Dijkstra.cpp │ ├── Bellman-Ford.cpp │ └── Floyed-Warshall.cpp ├── MinimumSpanningTree │ └── Kruskal.cpp ├── 常见问题.md └── knapsack_problem │ └── 0_1.cpp ├── programming ├── tree │ ├── 1026.cpp │ ├── 998.cpp │ ├── 617.合并二叉树.cpp │ ├── 814.二叉树剪枝.cpp │ ├── 收藏题目&解法.md │ ├── 965.cpp │ ├── 538.把二叉搜索树转换为累加树.cpp │ ├── 1325.删除给定叶子结点值.cpp │ ├── 2331.计算二叉树的布尔值.cpp │ ├── 1448.好节点的个数.cpp │ ├── 951.翻转等价二叉树cpp │ ├── 树题目分类总结.md │ ├── 530.二叉搜索树的最小绝对差.cpp │ ├── 508.出现次数最多的子树和.cpp │ ├── 1110.删点成林cpp │ ├── 110.平衡二叉树.cpp │ ├── 637.二叉树的平均值.cpp │ ├── binary_tree_deep.cpp │ ├── 1457.二叉树中的伪回文路径.cpp │ ├── 572.另一个树的子树.cpp │ ├── balance_tree.cpp │ ├── 230.二叉搜索树第k小的数.cpp │ ├── 145.二叉树的后序遍历.cpp │ ├── 700.二叉搜索树中的搜索.cpp │ ├── 99.恢复二叉搜索树.cpp │ ├── 113.路径总和-ii.cpp │ ├── 199.二叉树的右视图.cpp │ ├── 106.从中序与后序遍历序列构造二叉树.cpp │ ├── 958.二叉树的完全性检验.cpp │ ├── 102.二叉树的层次遍历.cpp │ ├── 114.二叉树展开为链表.cpp │ ├── 107.二叉树的层次遍历-ii.cpp │ ├── 109.有序链表转换二叉搜索树.cpp │ └── 173.二叉搜索树迭代器.cpp ├── data-structure │ ├── 数组模拟栈.md │ ├── 数组模拟链表.md │ ├── 收藏题目&总结.md │ ├── 2770.分割数组的方案.cpp │ ├── 数据结构总结.md │ ├── 0071.简化路径.cpp │ ├── 0032.最长有效括号.cpp │ ├── 3066.cpp │ ├── 238-除自身以外其他元素乘积.cpp │ ├── 239.滑动窗口最大值.cpp │ ├── 滑动窗口.cpp │ └── 295.数据流的中位数.cpp ├── dynamic-programming │ ├── dynamic-programming.md │ ├── 746.cpp │ ├── 2320.cpp │ ├── 1749.cpp │ ├── 2826.cpp │ ├── 1186.cpp │ ├── 152.cpp │ ├── 377.cpp │ ├── 122.买卖股票的最佳时机-ii.cpp │ ├── 2140.cpp │ ├── 96.不同的二叉搜索树.cpp │ ├── 2321.cpp │ ├── 213.cpp │ ├── 740.cpp │ ├── 1458.cpp │ ├── 718.cpp │ ├── 139.cpp │ ├── 2466.cpp │ ├── 123.买卖股票的最佳时机-iii.cpp │ ├── 2606.cpp │ ├── 279.cpp │ ├── 1035.cpp │ ├── 1964.cpp │ ├── 416.cpp │ ├── 120.三角形最小路径和.cpp │ ├── 583.cpp │ ├── 3290.cpp │ ├── 712.cpp │ ├── 2707.字符串中的额外字符.cpp │ ├── 918.cpp │ ├── 322.cpp │ ├── 174.地下城游戏.cpp │ ├── 2111.cpp │ ├── 1191.cpp │ ├── 1143.最长公共子序列.cpp │ ├── 115.cpp │ ├── 0064.最小路径和.cpp │ ├── 2266.cpp │ ├── 2369.cpp │ ├── 494.cpp │ ├── 115.不同的子序列.cpp │ ├── 132.cpp │ ├── 198.打家劫舍.cpp │ ├── 97.交错字符串.cpp │ ├── 91.解码方法.cpp │ ├── 1671.cpp │ ├── 0044.通配符匹配.cpp │ ├── 300.cpp │ ├── 63.不同路径-ii.cpp │ └── 0070.爬楼梯.cpp ├── greedy │ ├── greedy.md │ ├── 455.分发饼干.cpp │ ├── 605.种花问题.cpp │ ├── 134.加油站.cpp │ ├── 763.划分字母区间.cpp │ ├── 435.无重叠区间.cpp │ ├── 452.用最少数量的箭引爆气球.cpp │ └── 135.分发糖果.cpp ├── bit-manipulation │ ├── cpp位运算函数.md │ ├── 201.数字范围按位与.cpp │ ├── 判断字符是否唯一.cpp │ ├── 137.只出现一次的数字-ii.cpp │ ├── 位运算题型总结.md │ ├── 位运算总结.md │ ├── 169.多数元素.cpp │ ├── 0461.汉明距离.cpp │ ├── 3226.使两个整数相等的位更改次数.cpp │ └── 位插入.cpp ├── divide-and-conquer │ └── 1. 第k小的数.md ├── slide-window │ ├── 定长滑动窗口.md │ ├── 不定长滑动窗口.md │ ├── 209.cpp │ ├── 3090.cpp │ ├── 2958.最多k个重复元素的子数组.cpp │ ├── 2090.cpp │ ├── slide-window.md │ ├── 1493.cpp │ ├── 643.子数组最大平均数 I.cpp │ ├── 2379.cpp │ ├── 1343.cpp │ ├── 2904.cpp │ ├── 1456. 定长子串中元音的最大数目.cpp │ ├── 567.字符串的排列cpp │ ├── 438.找到字符串中所有字母异位词.cpp │ ├── 3697_3698.cpp │ ├── 76.最小覆盖子串.cpp │ └── 0076.最小覆盖子串.cpp ├── two-pointers │ ├── two_pointers.md │ ├── 283.移动零.cpp │ ├── 21.奇数在偶数前.md │ ├── 88.合并两个有序数组.cpp │ ├── 125.验证回文串.cpp │ └── 209.长度最小的子数组.cpp ├── 969.煎饼排序.cpp ├── array │ ├── array.md │ ├── readme.md │ ├── 119.杨辉三角-ii.cpp │ ├── 1047.删除字符串中的所有相邻重复项.cpp │ ├── 240.搜索二维矩阵2.cpp │ ├── 118.杨辉三角.cpp │ ├── 75.颜色分类.cpp │ ├── 4.二维数组中的查找.md │ ├── 119.杨辉三角-ii.py │ ├── 31.下一个排列.cpp │ ├── 167.两数之和-ii-输入有序数组.cpp │ ├── 3164.优质对数对.cpp │ ├── 1209.删除字符串中的所有相邻重复项-ii.cpp │ ├── 3162.优质对数对.cpp │ ├── 3.数组中重复的数字.md │ └── 189.旋转数组.cpp ├── hash-table │ ├── 218.存在重复元素.cpp │ ├── 187.重复的dna序列.cpp │ ├── 205.同构字符串.cpp │ ├── 219.存在重复元素.cpp │ └── 128.最长连续序列.cpp ├── math │ ├── math.md │ ├── 172.阶乘后的零.cpp │ ├── 171.excel表列序号.cpp │ ├── 168.excel表列名称.cpp │ ├── 343.整数拆分.cpp │ ├── 470.用-rand-7-实现-rand-10.cpp │ ├── 202.快乐数.cpp │ ├── 89.格雷编码.cpp │ ├── 204.计数质数.cpp │ ├── 0009.回文数.cpp │ ├── 大数运算.md │ └── 65.有效数字.cpp ├── string │ ├── 392.判断子序列.cpp │ ├── string.md │ ├── 383.赎金信.cpp │ ├── 38.报数.cpp │ ├── URL化.cpp │ ├── 68.文本左右对齐.py │ ├── 165.比较版本号.cpp │ ├── 93.复原ip地址.cpp │ └── 0058.最后一个单词的长度.cpp ├── 365.水壶问题.cpp ├── favorite │ ├── 熟练度练习.md │ └── readme.md ├── 263.丑数.cpp ├── 343.整数拆分.cpp ├── backtrack │ ├── 3566.cpp │ ├── 77.组合.cpp │ ├── 0077.组合.cpp │ ├── 回溯题型总结.md │ ├── 1836.找出所有子集的异或总和再求和.cpp │ ├── 216.组合总数3.cpp │ ├── 1593.拆分字符串使唯一子字符串的数目最大.cpp │ ├── 87.扰乱字符串.cpp │ ├── 2689.cpp │ ├── 131.分割回文串.cpp │ └── 842.cpp ├── sort │ ├── 179.最大数.cpp │ ├── 56.合并区间.cpp │ └── 51. 数组中的逆序对.md ├── binary-search │ ├── 153.寻找旋转排序数组中的最小值.cpp │ ├── 154.寻找旋转排序数组中的最小值-ii.cpp │ ├── 88.合并两个有序数组.cpp │ ├── 162.寻找峰值.cpp │ ├── 300.最长上升子序列.cpp │ └── 81.搜索旋转排序数组-ii.cpp ├── linked_list │ ├── 160.相交链表.cpp │ ├── 141.环形链表.cpp │ ├── 83.删除排序链表中的重复元素.cpp │ ├── 24.两两交换链表中的节点.cpp │ ├── 92.反转链表-ii.cpp │ ├── 61.旋转链表.cpp │ ├── 0061.旋转链表.cpp │ ├── 82.删除排序链表中的重复元素-ii.cpp │ ├── 203.移除链表元素.cpp │ ├── 86.分隔链表.cpp │ ├── 25.k-个一组翻转链表.cpp │ ├── 链表相交.cpp │ └── 234.回文链表.cpp ├── 876.链表的中间结点.cpp ├── 409.最长回文串.cpp ├── 213.打家劫舍-ii.cpp ├── 836.矩形重叠.cpp ├── 1160.拼写单词.cpp ├── 328.奇偶链表.cpp ├── search │ ├── 129.求根到叶子节点数字之和.cpp │ └── 785.判断二分图.cpp ├── 1248.统计「优美子数组」.cpp ├── 945.使数组唯一的最小增量.cpp ├── 1071.字符串的最大公因子.cpp └── 695.岛屿的最大面积.cpp ├── DataStructure ├── Graph │ ├── Graph.h │ └── Graph_Demo.cpp ├── String │ ├── String.h │ └── String.cpp ├── PolyAdd │ ├── PolyAdd.h │ ├── PolyAdd.cpp │ └── PolyAdd_Demo.h ├── vector │ ├── myVector.h │ └── myVector_Demo.cpp ├── LinkList │ ├── LinkList.h │ └── LinkList_Demo.cpp ├── Stack │ ├── Stack_Demo.cpp │ └── Stack.h ├── binarySearchTree │ ├── binarySearchTree.h │ └── binarySearchTree_Demo.cpp ├── Queue │ ├── Queue_Demo.cpp │ └── Queue.h └── vectorAndMap │ └── convert.cpp └── algorithm ├── newton_iterative_method └── newton_iterative_method.md └── search └── resource └── path.png /.gitignore: -------------------------------------------------------------------------------- 1 | README.md -------------------------------------------------------------------------------- /Algorithm/graph/3.最小生成树.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Algorithm/graph/4.最短路径.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Algorithm/math/2.前缀和差分.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /programming/tree/1026.cpp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /programming/tree/998.cpp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /programming/tree/617.合并二叉树.cpp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /programming/tree/814.二叉树剪枝.cpp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /programming/data-structure/数组模拟栈.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /programming/data-structure/数组模拟链表.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /programming/dynamic-programming/dynamic-programming.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /programming/data-structure/收藏题目&总结.md: -------------------------------------------------------------------------------- 1 | 2 | # 收藏题目 3 | - 560 , 子数组想到前缀和 -------------------------------------------------------------------------------- /programming/greedy/greedy.md: -------------------------------------------------------------------------------- 1 | # 贪心相关算法 2 | 3 | | Title | Solution | Source| 4 | | ---- | -------|------| -------------------------------------------------------------------------------- /Algorithm/sort/mySort.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqtaowhu/DataStructureAndAlgorithm/HEAD/Algorithm/sort/mySort.h -------------------------------------------------------------------------------- /Algorithm/Search/Search.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqtaowhu/DataStructureAndAlgorithm/HEAD/Algorithm/Search/Search.cpp -------------------------------------------------------------------------------- /Algorithm/TicTacToe/Demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqtaowhu/DataStructureAndAlgorithm/HEAD/Algorithm/TicTacToe/Demo.png -------------------------------------------------------------------------------- /DataStructure/Graph/Graph.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqtaowhu/DataStructureAndAlgorithm/HEAD/DataStructure/Graph/Graph.h -------------------------------------------------------------------------------- /DataStructure/String/String.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqtaowhu/DataStructureAndAlgorithm/HEAD/DataStructure/String/String.h -------------------------------------------------------------------------------- /DataStructure/PolyAdd/PolyAdd.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqtaowhu/DataStructureAndAlgorithm/HEAD/DataStructure/PolyAdd/PolyAdd.h -------------------------------------------------------------------------------- /DataStructure/String/String.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqtaowhu/DataStructureAndAlgorithm/HEAD/DataStructure/String/String.cpp -------------------------------------------------------------------------------- /DataStructure/vector/myVector.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqtaowhu/DataStructureAndAlgorithm/HEAD/DataStructure/vector/myVector.h -------------------------------------------------------------------------------- /algorithm/newton_iterative_method/newton_iterative_method.md: -------------------------------------------------------------------------------- 1 | # 牛顿法 2 | 3 | 牛顿-拉弗森方法提出来的思路就是利用切线是曲线的线性逼近这个思想。 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /programming/tree/收藏题目&解法.md: -------------------------------------------------------------------------------- 1 | # 收藏题目 & 解法 2 | 3 | - [114. 二叉树展开为链表](./114.二叉树展开为链表.cpp) 4 | - [124.二叉树的最大路径和](./124.二叉树中的最大路径和.cpp) -------------------------------------------------------------------------------- /Algorithm/UnionFind/UnionFind.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqtaowhu/DataStructureAndAlgorithm/HEAD/Algorithm/UnionFind/UnionFind.cpp -------------------------------------------------------------------------------- /DataStructure/Graph/Graph_Demo.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqtaowhu/DataStructureAndAlgorithm/HEAD/DataStructure/Graph/Graph_Demo.cpp -------------------------------------------------------------------------------- /DataStructure/LinkList/LinkList.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqtaowhu/DataStructureAndAlgorithm/HEAD/DataStructure/LinkList/LinkList.h -------------------------------------------------------------------------------- /DataStructure/PolyAdd/PolyAdd.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqtaowhu/DataStructureAndAlgorithm/HEAD/DataStructure/PolyAdd/PolyAdd.cpp -------------------------------------------------------------------------------- /DataStructure/Stack/Stack_Demo.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqtaowhu/DataStructureAndAlgorithm/HEAD/DataStructure/Stack/Stack_Demo.cpp -------------------------------------------------------------------------------- /algorithm/search/resource/path.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqtaowhu/DataStructureAndAlgorithm/HEAD/algorithm/search/resource/path.png -------------------------------------------------------------------------------- /Algorithm/ShortestPaths/Dijkstra.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqtaowhu/DataStructureAndAlgorithm/HEAD/Algorithm/ShortestPaths/Dijkstra.cpp -------------------------------------------------------------------------------- /DataStructure/PolyAdd/PolyAdd_Demo.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqtaowhu/DataStructureAndAlgorithm/HEAD/DataStructure/PolyAdd/PolyAdd_Demo.h -------------------------------------------------------------------------------- /programming/bit-manipulation/cpp位运算函数.md: -------------------------------------------------------------------------------- 1 | # cpp位运算函数 2 | 3 | - bit_width((uint32_t) n) : 求二进制的宽度,最大1的位置 4 | - __builtin_popcount : 计算二进制中1的个数 -------------------------------------------------------------------------------- /DataStructure/vector/myVector_Demo.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqtaowhu/DataStructureAndAlgorithm/HEAD/DataStructure/vector/myVector_Demo.cpp -------------------------------------------------------------------------------- /Algorithm/MinimumSpanningTree/Kruskal.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqtaowhu/DataStructureAndAlgorithm/HEAD/Algorithm/MinimumSpanningTree/Kruskal.cpp -------------------------------------------------------------------------------- /Algorithm/ShortestPaths/Bellman-Ford.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqtaowhu/DataStructureAndAlgorithm/HEAD/Algorithm/ShortestPaths/Bellman-Ford.cpp -------------------------------------------------------------------------------- /DataStructure/LinkList/LinkList_Demo.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqtaowhu/DataStructureAndAlgorithm/HEAD/DataStructure/LinkList/LinkList_Demo.cpp -------------------------------------------------------------------------------- /Algorithm/ShortestPaths/Floyed-Warshall.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqtaowhu/DataStructureAndAlgorithm/HEAD/Algorithm/ShortestPaths/Floyed-Warshall.cpp -------------------------------------------------------------------------------- /DataStructure/binarySearchTree/binarySearchTree.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yqtaowhu/DataStructureAndAlgorithm/HEAD/DataStructure/binarySearchTree/binarySearchTree.h -------------------------------------------------------------------------------- /programming/divide-and-conquer/1. 第k小的数.md: -------------------------------------------------------------------------------- 1 | # 有序数组第k小的数 2 | 3 | 4 | # 两个有序数组第k小的数 5 | 6 | 7 | 参考资料: 8 | 9 | - https://www.acwing.com/solution/LeetCode/content/50/ -------------------------------------------------------------------------------- /Algorithm/常见问题.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 稳定的排序算法 4 | 5 | 稳定排序算法: 假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变 6 | 7 | - 不稳定: 堆排序、快速排序、希尔排序、直接选择排序 8 | - 稳定: 基数排序、冒泡排序、直接插入排序、折半插入排序、归并排序 -------------------------------------------------------------------------------- /programming/slide-window/定长滑动窗口.md: -------------------------------------------------------------------------------- 1 | # 定长滑动窗口 2 | 3 | 其基本的思想是初始化窗口 4 | - insert 5 | - update 6 | - delete 7 | 8 | 9 | - 模板套用即可 10 | 1145, 643, 1343, 2379 11 | 同样是模板,但是注意索引的位置即可 12 | 2090 13 | 14 | -------------------------------------------------------------------------------- /programming/two-pointers/two_pointers.md: -------------------------------------------------------------------------------- 1 | # 双指针相关算法练习题 2 | 3 | | Title | Solution | Source| 4 | | ---- | -------|------| 5 | |无重复字符的最长子串|[3无重复字符的最长子串 ](1.../3.无重复字符的最长子串.cpp)|[3.无重复字符的最长子串](https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/)| -------------------------------------------------------------------------------- /programming/969.煎饼排序.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=969 lang=cpp 3 | * 4 | * [969] 煎饼排序 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | vector pancakeSort(vector& A) { 11 | 12 | } 13 | }; 14 | // @lc code=end 15 | 16 | -------------------------------------------------------------------------------- /Algorithm/TicTacToe/main.cpp: -------------------------------------------------------------------------------- 1 | #include"ChessBoard.h" 2 | #include "TicTacToe.h" 3 | int main() { 4 | while (1) { 5 | TicTacToe game; 6 | game.start(); 7 | cout << "play again(Y or y):" << endl; 8 | char c; 9 | cin >> c; 10 | if (c != 'y'&&c !='Y') 11 | break; 12 | } 13 | } -------------------------------------------------------------------------------- /programming/array/array.md: -------------------------------------------------------------------------------- 1 | # 数组相关算法练习题 2 | 3 | | Title | Solution | Source| 4 | | ---- | -------|------| 5 | |两数之和|[1.两数之和](1.两数之和.cpp)|[1.两数之和](https://leetcode-cn.com/problems/two-sum/)| 6 | |寻找两个有序数组的中位数|[4.寻找两个有序数组的中位数](4.寻找两个有序数组的中位数.cpp)|[4.寻找两个有序数组的中位数](https://leetcode-cn.com/problems/median-of-two-sorted-arrays/)| -------------------------------------------------------------------------------- /programming/array/readme.md: -------------------------------------------------------------------------------- 1 | # 数组相关算法练习题 2 | 3 | | Title | Solution | Source| 4 | | ---- | -------|------| 5 | |两数之和|[1.两数之和](1.两数之和.cpp)|[1.两数之和](https://leetcode-cn.com/problems/two-sum/)| 6 | |寻找两个有序数组的中位数|[4.寻找两个有序数组的中位数](4.寻找两个有序数组的中位数.cpp)|[4.寻找两个有序数组的中位数](https://leetcode-cn.com/problems/median-of-two-sorted-arrays/)| -------------------------------------------------------------------------------- /DataStructure/Queue/Queue_Demo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Queue.h" 3 | using namespace std; 4 | int main() { 5 | Queue que; 6 | que.enQueue(1); 7 | que.enQueue(2); 8 | 9 | cout< &cost) { 4 | int n = cost.size(); 5 | vector f(n + 1); 6 | for (int i = 2; i <= n; i++) { 7 | f[i] = min(f[i - 1] + cost[i - 1], f[i - 2] + cost[i - 2]); 8 | } 9 | return f[n]; 10 | } 11 | }; -------------------------------------------------------------------------------- /programming/hash-table/218.存在重复元素.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | bool containsDuplicate(vector& nums) { 4 | unordered_map hash; 5 | for(auto &i : nums) { 6 | hash[i]++; 7 | if(hash[i] >= 2) { 8 | return true; 9 | } 10 | } 11 | return false; 12 | } 13 | }; -------------------------------------------------------------------------------- /programming/math/math.md: -------------------------------------------------------------------------------- 1 | # 数组相关算法练习题 2 | 3 | | Title | Solution | Source| 4 | | ---- | -------|------| 5 | |整数反转|[7.整数反转](7.整数反转.cpp)|[整数反转](https://leetcode-cn.com/problems/reverse-integer/) 6 | |字符串转整数|[8.字符串转整数](8.字符串转换整数.cpp)|[字符串转整数](https://leetcode-cn.com/problems/string-to-integer-atoi/) 7 | |回文数|[9.回文数](9.回文数.cpp)|[回文数](https://leetcode-cn.com/problems/palindrome-number/) 8 | 9 | -------------------------------------------------------------------------------- /programming/string/392.判断子序列.cpp: -------------------------------------------------------------------------------- 1 | // 遍历即可 2 | class Solution { 3 | public: 4 | bool isSubsequence(string s, string t) { 5 | int m = s.size(), n = t.size(); 6 | int i=0, j = 0; 7 | while(i < m && j < n) { 8 | if(s[i] == t[j]) { 9 | i++; 10 | } 11 | j++; 12 | } 13 | return i == m; 14 | } 15 | }; -------------------------------------------------------------------------------- /programming/dynamic-programming/2320.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int countHousePlacements(int n) { 4 | int mod = 1e9 + 7; 5 | vector dp(n + 1, 0); 6 | dp[0]= 1; 7 | dp[1]= 2; 8 | for(int i=2; i <= n; i++) { 9 | dp[i] = (dp[i-2] + dp[i-1]) % mod; 10 | } 11 | return dp[n] * dp[n] % mod; 12 | } 13 | }; -------------------------------------------------------------------------------- /programming/math/172.阶乘后的零.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=172 lang=cpp 3 | * 4 | * [172] 阶乘后的零 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | int trailingZeroes(int n) { 11 | int res = 0; 12 | while(n) { 13 | res += n/5; 14 | n /= 5; 15 | } 16 | return res; 17 | } 18 | }; 19 | // @lc code=end 20 | 21 | -------------------------------------------------------------------------------- /programming/tree/965.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | bool dfs(TreeNode* root, int target) { 4 | if(!root) return true; 5 | if(root->val != target) return false; 6 | return dfs(root->left, target) && dfs(root->right, target); 7 | 8 | } 9 | 10 | bool isUnivalTree(TreeNode* root) { 11 | if(!root) return true; 12 | return dfs(root, root->val); 13 | } 14 | }; -------------------------------------------------------------------------------- /Algorithm/TicTacToe/Makefile: -------------------------------------------------------------------------------- 1 | #Objects : 2 | OBJS = main.o TicTacToe.o ChessBoard.o 3 | 4 | #Complier: 5 | CC=g++ -std=c++11 6 | 7 | TicTacToe : $(OBJS) 8 | $(CC) -o TicTacToe $(OBJS) 9 | main.o : main.cpp 10 | $(CC) -c main.cpp 11 | TicTacToe.o : TicTacToe.cpp 12 | $(CC) -c TicTacToe.cpp 13 | ChessBoard.o : ChessBoard.cpp 14 | $(CC) -c ChessBoard.cpp 15 | clear : 16 | rm $(OBJS) 17 | run : 18 | ./TicTacToe 19 | -------------------------------------------------------------------------------- /programming/tree/538.把二叉搜索树转换为累加树.cpp: -------------------------------------------------------------------------------- 1 | // 把二叉搜索树转换为累加树 2 | 3 | 4 | // 反序中序遍历 5 | class Solution { 6 | public: 7 | int sum = 0; 8 | 9 | TreeNode* convertBST(TreeNode* root) { 10 | if (root != nullptr) { 11 | convertBST(root->right); 12 | sum += root->val; 13 | root->val = sum; 14 | convertBST(root->left); 15 | } 16 | return root; 17 | } 18 | }; -------------------------------------------------------------------------------- /programming/string/string.md: -------------------------------------------------------------------------------- 1 | # 字符串相关算法练习题 2 | 3 | | Title | Solution | Source| 4 | | ---- | -------|------| 5 | |无重复字符的最长子串|[3无重复字符的最长子串 ](3.两数之和.cpp)|[3.无重复字符的最长子串](https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/)| 6 | |最长回文子串|[5.最长回文子串](5.最长回文子串.cpp)|[5.最长回文子串](https://leetcode-cn.com/problems/longest-palindromic-substring/) 7 | |Z 字形变换|[6.Z字形变换](6.z-字形变换.cpp|[6.Z字形变换](https://leetcode-cn.com/problems/zigzag-conversion/) -------------------------------------------------------------------------------- /programming/dynamic-programming/1749.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int maxAbsoluteSum(vector& nums) { 4 | // 两次dp结果 5 | int ans = 0, f_max = 0, f_min = 0; 6 | for(int i = 0; i < nums.size(); i++) { 7 | f_max = max(f_max + nums[i], nums[i]); 8 | f_min = min(f_min + nums[i], nums[i]); 9 | ans = max(ans, max(f_max, -f_min)); 10 | } 11 | return ans; 12 | } 13 | }; -------------------------------------------------------------------------------- /programming/dynamic-programming/2826.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int minimumOperations(vector& nums) { 4 | vector g; 5 | for (int x : nums) { 6 | auto it = ranges::upper_bound(g, x); 7 | if (it == g.end()) { 8 | g.push_back(x); 9 | } else { 10 | *it = x; 11 | } 12 | } 13 | return nums.size() - g.size(); 14 | } 15 | }; -------------------------------------------------------------------------------- /programming/365.水壶问题.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=365 lang=cpp 3 | * 4 | * [365] 水壶问题 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | bool canMeasureWater(int x, int y, int z) { 11 | // ax + by = z 有解条件是z是x,y最大公约数的倍数 12 | if (x + y < z) return false; 13 | if (x == 0 || y == 0) return z == 0 || x + y == z; 14 | return z % gcd(x, y) == 0; 15 | } 16 | }; 17 | // @lc code=end 18 | 19 | -------------------------------------------------------------------------------- /programming/tree/1325.删除给定叶子结点值.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | TreeNode* removeLeafNodes(TreeNode* root, int target) { 4 | if(!root) return nullptr; 5 | root->left = removeLeafNodes(root->left, target); 6 | root->right = removeLeafNodes(root->right, target); 7 | if(!root->left && !root->right && root->val == target) { 8 | return nullptr; 9 | } 10 | return root; 11 | 12 | } 13 | }; -------------------------------------------------------------------------------- /programming/tree/2331.计算二叉树的布尔值.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | 4 | bool evaluateTree(TreeNode* root) { 5 | if(!root) return true; 6 | // 叶子结点 7 | if(!root->left) return root->val; 8 | bool l = evaluateTree(root->left); 9 | bool r = evaluateTree(root->right); 10 | if(root->val == 2) { 11 | return l | r; 12 | } else { 13 | return l & r; 14 | } 15 | 16 | } 17 | }; -------------------------------------------------------------------------------- /programming/slide-window/不定长滑动窗口.md: -------------------------------------------------------------------------------- 1 | # 模板 2 | 3 | int left = 0, right = 0; 4 | 5 | while (right < s.size()) { 6 | // 增大窗口 7 | window.add(s[right]); 8 | right++; 9 | 10 | while (window needs shrink) { 11 | // 缩小窗口 12 | window.remove(s[left]); 13 | left++; 14 | } 15 | } 16 | 17 | 18 | # 不定长滑动窗口 19 | 20 | 一般有至多、至少子串,子数组等 21 | 22 | 最多k个重复元素的子数组 23 | - 2958,3090,1493(有细微变化) 24 | 25 | 26 | 27 | ### 求解最长最短 28 | - 209 29 | - 2094 -------------------------------------------------------------------------------- /programming/two-pointers/283.移动零.cpp: -------------------------------------------------------------------------------- 1 | // 简单题 2 | // 两种做法,一种是交换,一种是赋值,下面是交换的做法 3 | class Solution { 4 | public: 5 | void moveZeroes(vector& nums) { 6 | int size = nums.size(); 7 | if(size == 0) return; 8 | int left = 0, right = 0; 9 | while(right < size) { 10 | if(nums[right]) { 11 | swap(nums[right], nums[left]); 12 | left++; 13 | } 14 | right++; 15 | } 16 | } 17 | }; -------------------------------------------------------------------------------- /programming/math/171.excel表列序号.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=171 lang=cpp 3 | * 4 | * [171] Excel表列序号 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | int titleToNumber(string s) { 11 | int res=0,i=0; 12 | while (s[i]==' ') i++; 13 | for (;ival >= x) { 7 | ans += 1; 8 | } 9 | x = max(x, root->val); 10 | dfs(root->left, x); 11 | dfs(root->right, x); 12 | } 13 | int goodNodes(TreeNode* root) { 14 | if(!root) return 0; 15 | dfs(root, root->val); 16 | return ans; 17 | } 18 | }; -------------------------------------------------------------------------------- /programming/math/168.excel表列名称.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=168 lang=cpp 3 | * 4 | * [168] Excel表列名称 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | string convertToTitle(int n) { 11 | string res; 12 | char tmp; 13 | while(n){ 14 | n -= 1; 15 | tmp = 'A' + n % 26; 16 | res = tmp + res; 17 | n /= 26; 18 | } 19 | return res; 20 | } 21 | }; 22 | // @lc code=end 23 | 24 | -------------------------------------------------------------------------------- /programming/slide-window/209.cpp: -------------------------------------------------------------------------------- 1 | // 长度最小的子数组 2 | class Solution { 3 | public: 4 | int minSubArrayLen(int target, vector& nums) { 5 | int size = nums.size(); 6 | int sum = 0, res = INT_MAX; 7 | for(int i=0, j=0; j < size; j++) { 8 | sum += nums[j]; 9 | while(sum >= target) { 10 | res = min(j-i+1, res); 11 | sum -= nums[i++]; 12 | } 13 | } 14 | return res == INT_MAX ? 0 : res; 15 | } 16 | }; -------------------------------------------------------------------------------- /programming/tree/951.翻转等价二叉树cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | bool flipEquiv(TreeNode* root1, TreeNode* root2) { 4 | if(!root1 || !root2) { 5 | return root1 == root2; 6 | } 7 | if(root1->val != root2->val) { 8 | return false; 9 | } 10 | return (flipEquiv(root1->left, root2->left) && flipEquiv(root1->right, root2->right)) 11 | || (flipEquiv(root1->left, root2->right) && flipEquiv(root1->right, root2->left)); 12 | } 13 | }; -------------------------------------------------------------------------------- /programming/slide-window/3090.cpp: -------------------------------------------------------------------------------- 1 | 2 | // 和2958一样,就是改个条件 3 | class Solution { 4 | public: 5 | int maximumLengthSubstring(string s) { 6 | int size = s.size(), res = 0; 7 | unordered_map map; 8 | for(int i=0, j=0; j < size; j++) { 9 | map[s[j]]++; 10 | // 窗口不符合条件 11 | while(map[s[j]] > 2) { 12 | map[s[i++]]--; 13 | } 14 | res = max(res, j-i+1); 15 | } 16 | return res; 17 | } 18 | }; -------------------------------------------------------------------------------- /Algorithm/TicTacToe/ReadMe.md: -------------------------------------------------------------------------------- 1 | # Tic-Tac-Toe AI game 2 | This is a AI Tic-Tac-Toe game,written by c++,using mimmax algorithm and alpha-beta punting 3 | 4 | ## How To Run 5 | 6 | Linux: 7 | ``` 8 | git clone https://github.com/yqtaowhu/DataStructureAndAlgorithm 9 | cd DataStructureAndAlgorithm/Algorithm/TicTacToe/ 10 | make run 11 | ``` 12 | 13 | Windows: 14 | 15 | Compile and run with Visual Studio 16 | 17 | ##Demo 18 | ![](Demo.png) 19 | 20 | ## License 21 | 22 | Copyright 2016 yqtao 23 | -------------------------------------------------------------------------------- /DataStructure/binarySearchTree/binarySearchTree_Demo.cpp: -------------------------------------------------------------------------------- 1 | #include "binarySearchTree.h" 2 | #include 3 | int main() { 4 | vector v = { 15,20,4,1,16 ,24}; 5 | BST bst; 6 | for (auto c : v) 7 | bst.insert(c); //insert 8 | 9 | bst.inorder(); //inorder traveral 10 | bst.morris_inorder(); 11 | bst.breadFirst(); //level traveral 12 | //delete 13 | bst.findAndDelete(15); 14 | bst.breadFirst(); 15 | //search 16 | BSTNode* node=bst.search(16); 17 | cout << node->val << endl; 18 | } -------------------------------------------------------------------------------- /programming/dynamic-programming/1186.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int maximumSum(vector &arr) { 4 | int ans = INT_MIN, n = arr.size(); 5 | vector> f(n + 1, vector(2, INT_MIN / 2)); // 除 2 防止负数相加溢出 6 | for (int i = 0; i < n; i++) { 7 | f[i + 1][0] = max(f[i][0], 0) + arr[i]; 8 | f[i + 1][1] = max(f[i][1] + arr[i], f[i][0]); 9 | ans = max(ans, max(f[i + 1][0], f[i + 1][1])); 10 | } 11 | return ans; 12 | } 13 | }; -------------------------------------------------------------------------------- /programming/dynamic-programming/152.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | // 和最大子数组类似,但是因为有负数,导致最大最小颠倒 4 | int maxProduct(vector& nums) { 5 | int max_s = INT_MIN; 6 | int max_f = 1, min_f = 1; 7 | for(const auto x:nums) { 8 | if(x < 0) { 9 | swap(max_f, min_f); 10 | } 11 | max_f = max(max_f * x, x); 12 | min_f = min(min_f * x, x); 13 | max_s = max(max_s, max_f); 14 | } 15 | return max_s; 16 | } 17 | }; -------------------------------------------------------------------------------- /programming/favorite/熟练度练习.md: -------------------------------------------------------------------------------- 1 | 2 | # leetcode 熟练度练习 3 | 4 | | Title | Comment|important|similiary| 5 | | ---- | -------|---|---| 6 | |1.两数之和| 哈希表| low| 7 | |2.两数相加| 模拟加法| low| 8 | |3.无重复最长子串| 双指针算法| mid| 9 | |4.两个有序数组中位数| 寻找两个数组的第k小的数| high| 10 | |5.最长回文子串| 遍历,中心扩展法 | mid| 11 | |6.z变化| 字符串直接实现| low| 12 | |7.整数反转| long long直接定义反转| low| 13 | |8.字符串转整数| 空格、正负号的考虑| mid| 14 | |9.回文数| res == x, res == x/10, 注意溢出| high| 15 | |10.正则表达式| 递归解决 | high| 16 | |11.承最多水的容器| 双指针 | low| 17 | |12.数字转罗马| 从大到小构建| mid | 18 | |13.罗马转数字| 简单实现题 | mid| -------------------------------------------------------------------------------- /programming/263.丑数.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=263 lang=cpp 3 | * 4 | * [263] 丑数 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | bool isUgly(int num) { 11 | if(num < 1) return false; 12 | while(num % 2 == 0) { 13 | num /= 2; 14 | } 15 | while(num % 3 == 0) { 16 | num /= 3; 17 | } 18 | while(num % 5 ==0 ) { 19 | num /=5; 20 | } 21 | return num == 1; 22 | } 23 | }; 24 | // @lc code=end 25 | 26 | -------------------------------------------------------------------------------- /programming/dynamic-programming/377.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int combinationSum4(vector& nums, int target) { 4 | // 使用 unsigned 可以让溢出不报错 5 | // 对于溢出的数据,不会影响答案的正确性(题目保证) 6 | vector f(target + 1); 7 | f[0] = 1; 8 | for (int i = 1; i <= target; i++) { 9 | for (int x : nums) { 10 | if (x <= i) { 11 | f[i] += f[i - x]; 12 | } 13 | } 14 | } 15 | return f[target]; 16 | } 17 | }; -------------------------------------------------------------------------------- /programming/tree/树题目分类总结.md: -------------------------------------------------------------------------------- 1 | # 树题目分类总结 2 | 3 | 4 | 5 | ## 自顶向下 6 | 在「递」的过程中维护值。 7 | - 104 : 二叉树的深度, 同时可以使用自底向上的方法 8 | - 111 : bfs, dfs都可以, 9 | - 112 : 路径总和 10 | - 129 : 根到叶子节点的和 11 | - 1448: 记录当前最大值,自顶向下 12 | - 1457: 使用hash记录状态,记得要回溯状态 13 | - 1315: bfs, dfs都可以 14 | - 998: 很自然的想法是记录从根到叶子的路径,自顶下下 15 | - 1026: 在递归的过程中,维护最大最小值 16 | 17 | ## 自底向上 18 | 在「归」的过程中计算。 19 | 20 | - 965 21 | - 100 22 | - 101 23 | - 951: 翻转等价二叉树 24 | - 1379: 需要做一下,有一个是真实的,选择问题,不是&& 25 | - 110 26 | - 226 27 | - 617: 合并二叉树 28 | - 2331:计算二叉树的布尔值 29 | - 508: 边遍历边记录,一定要回的题目 -------------------------------------------------------------------------------- /programming/bit-manipulation/201.数字范围按位与.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=201 lang=cpp 3 | * 4 | * [201] 数字范围按位与 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | int rangeBitwiseAnd(int m, int n) { 11 | // 等价于求m,n从低位开始,位数相同的高位 12 | if(m == 0) return 0; 13 | int moveFactor = 1; 14 | while(m != n){ 15 | m >>= 1; 16 | n >>= 1; 17 | moveFactor <<= 1; 18 | } 19 | return m * moveFactor; 20 | } 21 | }; 22 | // @lc code=end 23 | 24 | -------------------------------------------------------------------------------- /programming/dynamic-programming/122.买卖股票的最佳时机-ii.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=122 lang=cpp 3 | * 4 | * [122] 买卖股票的最佳时机 II 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | int maxProfit(vector& prices) { 11 | int dp_i_0 = 0, dp_i_1 = INT_MIN; 12 | for(int i=0; i getRow(int rowIndex) { 4 | // 第i行由第i-1行得到 5 | // 1 3 3 1 -> 1 4 6 4 1 6 | vector res(rowIndex+1, 1); 7 | for(int i=2; i <= rowIndex; i++) { 8 | vector tmp(i+1, 1); 9 | for(int j=1; j < i; j++) { 10 | tmp[j] = res[j-1] + res[j]; 11 | } 12 | res = tmp; 13 | } 14 | return res; 15 | 16 | } 17 | }; 18 | 19 | 20 | # @lc code=end 21 | 22 | -------------------------------------------------------------------------------- /programming/dynamic-programming/2140.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | // 这里需要思考左到右是不行的 dp[i]: 到i时最大的分数 4 | // 从右到左,dp[i]: i往后得到的最大分数 5 | long long mostPoints(vector>& questions) { 6 | int n = questions.size(); 7 | vector dp(n + 1, 0); // 解决每道题及以后题目的最大分数 8 | for (int i = n - 1; i >= 0; --i) { 9 | int p = questions[i][0]; 10 | int b = questions[i][1]; 11 | dp[i] = max(dp[i + 1], p + dp[min(n, i + b + 1)]); 12 | } 13 | return dp[0]; 14 | } 15 | }; -------------------------------------------------------------------------------- /programming/dynamic-programming/96.不同的二叉搜索树.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=96 lang=cpp 3 | * 4 | * [96] 不同的二叉搜索树 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | //https://leetcode-cn.com/problems/unique-binary-search-trees/solution/bu-tong-de-er-cha-sou-suo-shu-by-leetcode/ 11 | vector cnts(n + 1, 0); 12 | cnts[0] = cnts[1] = 1; 13 | for (int i = 2;i <= n;i++) 14 | for (int j = 1;j <= i;j++) { 15 | cnts[i] += cnts[j - 1] * cnts[i - j]; 16 | } 17 | return cnts[n];} 18 | }; 19 | // @lc code=end 20 | 21 | -------------------------------------------------------------------------------- /programming/slide-window/2958.最多k个重复元素的子数组.cpp: -------------------------------------------------------------------------------- 1 | 2 | // 标准模板题 3 | // 维护窗口,直到满足条件的窗口 4 | class Solution { 5 | public: 6 | int maxSubarrayLength(vector& nums, int k) { 7 | int size = nums.size(), res = 0; 8 | unordered_map map; 9 | for(int i=0, j=0; j < size; j++) { 10 | map[nums[j]]++; 11 | // 窗口不符合条件 12 | while(map[nums[j]] > k) { 13 | map[nums[i++]]--; 14 | } 15 | res = max(res, j-i+1); 16 | } 17 | return res; 18 | } 19 | }; -------------------------------------------------------------------------------- /programming/data-structure/2770.分割数组的方案.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int waysToSplitArray(vector& nums) { 4 | // 前缀和问题 5 | int size = nums.size(); 6 | vector sum(size + 1, 0); 7 | for (int i = 1; i <= size; i++) { 8 | sum[i] = sum[i - 1] + nums[i - 1]; 9 | } 10 | int res = 0; 11 | for(int i = 1; i < size; i++) { 12 | if (sum[i] >= sum[size] - sum[i]) { 13 | res++; 14 | } 15 | } 16 | return res; 17 | } 18 | }; -------------------------------------------------------------------------------- /programming/dynamic-programming/2321.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | int solve(vector& nums1, vector& nums2) { 3 | int s1 = 0, max_sum = 0, f = 0; 4 | for (int i = 0; i < nums1.size(); i++) { 5 | s1 += nums1[i]; 6 | f = max(f, 0) + nums2[i] - nums1[i]; 7 | max_sum = max(max_sum, f); 8 | } 9 | return s1 + max_sum; 10 | } 11 | 12 | public: 13 | int maximumsSplicedArray(vector& nums1, vector& nums2) { 14 | return max(solve(nums1, nums2), solve(nums2, nums1)); 15 | } 16 | }; -------------------------------------------------------------------------------- /programming/343.整数拆分.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=343 lang=cpp 3 | * 4 | * [343] 整数拆分 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | int integerBreak(int n) { 11 | if(n == 2) return 1; 12 | if(n == 3) return 2; 13 | int res = 0, div = n / 3, dov = n % 3; 14 | if(dov == 0) { 15 | return pow(3, div); 16 | } else if(dov == 1) { 17 | return pow(3, div-1)*4; 18 | } else { 19 | return pow(3, div)*2; 20 | } 21 | } 22 | }; 23 | // @lc code=end 24 | 25 | -------------------------------------------------------------------------------- /programming/math/343.整数拆分.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=343 lang=cpp 3 | * 4 | * [343] 整数拆分 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | int integerBreak(int n) { 11 | if(n == 2) return 1; 12 | if(n == 3) return 2; 13 | int res = 0, div = n / 3, dov = n % 3; 14 | if(dov == 0) { 15 | return pow(3, div); 16 | } else if(dov == 1) { 17 | return pow(3, div-1)*4; 18 | } else { 19 | return pow(3, div)*2; 20 | } 21 | } 22 | }; 23 | // @lc code=end 24 | 25 | -------------------------------------------------------------------------------- /programming/dynamic-programming/213.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int help(vector& nums, int start, int end) { 4 | int f0 = 0, f1 = 0; 5 | for(int i=start; i& nums) { 14 | int n = nums.size(); 15 | // 取第一个,后续从i=2开始到n-1 16 | // 不取第一个, 从i=1开始到n 17 | return max(nums[0] + help(nums, 2, n-1), help(nums, 1, n)); 18 | 19 | } 20 | }; -------------------------------------------------------------------------------- /programming/array/1047.删除字符串中的所有相邻重复项.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=1047 lang=cpp 3 | * 4 | * [1047] 删除字符串中的所有相邻重复项 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | string removeDuplicates(string S) { 11 | // 很明显的栈操作, 用字符串模拟栈 12 | string st; 13 | for(int i=0; i>& matrix, int target) { 4 | if(matrix.empty() || matrix[0].empty()) return false; 5 | int m = matrix.size(), n = matrix[0].size(); 6 | int i = 0, j = n-1; 7 | while(i < m && j >=0) { 8 | if(matrix[i][j] == target) { 9 | return true; 10 | } else if(matrix[i][j] > target) { 11 | j--; 12 | } else { 13 | i++; 14 | } 15 | } 16 | return false; 17 | } 18 | }; -------------------------------------------------------------------------------- /programming/bit-manipulation/判断字符是否唯一.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | class Solution { 5 | public: 6 | bool isUnique(string astr) { 7 | // 核心思路,每一个字母都可以固定到一个数字的二进制的位置上 8 | // 如果当前和新的字母& != 0, 则重复了,否则进行或操作 9 | int res = 0; 10 | for(auto c: astr) { 11 | int move_bit = c - 'a'; 12 | int tmp = 1 << move_bit; 13 | if((res & tmp) != 0) { 14 | return false; 15 | } else { 16 | res = res | tmp; 17 | } 18 | } 19 | return true; 20 | } 21 | }; -------------------------------------------------------------------------------- /programming/dynamic-programming/740.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | // 198. 打家劫舍 3 | int rob(vector& nums) { 4 | int f0 = 0, f1 = 0; 5 | for (int x : nums) { 6 | int new_f = max(f1, f0 + x); 7 | f0 = f1; 8 | f1 = new_f; 9 | } 10 | return f1; 11 | } 12 | 13 | public: 14 | int deleteAndEarn(vector& nums) { 15 | int mx = ranges::max(nums); 16 | vector a(mx + 1); 17 | for (int x : nums) { 18 | a[x] += x; // 统计等于 x 的元素之和 19 | } 20 | return rob(a); 21 | } 22 | }; -------------------------------------------------------------------------------- /programming/slide-window/2090.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector getAverages(vector& nums, int k) { 4 | int size = nums.size(); 5 | vector res(size, -1); 6 | if (size < 2*k + 1) return res; 7 | // 初始化窗口 8 | long long int sum = 0; 9 | for(int i=0; i < 2*k; i ++) { 10 | sum += nums[i]; 11 | } 12 | for(int i=k; i < size - k; i++) { 13 | sum += nums[i+k]; 14 | res[i] = sum / (2*k + 1); 15 | sum -= nums[i-k]; 16 | } 17 | return res; 18 | } 19 | }; -------------------------------------------------------------------------------- /programming/backtrack/3566.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | bool checkEqualPartitions(vector& nums, long long target) { 4 | auto dfs = [&](this auto&& dfs, int i, long long mul1, long long mul2) -> bool { 5 | if (mul1 > target || mul2 > target) { 6 | return false; 7 | } 8 | if (i == nums.size()) { 9 | return mul1 == target && mul2 == target; 10 | } 11 | return dfs(i + 1, mul1 * nums[i], mul2) || dfs(i + 1, mul1, mul2 * nums[i]); 12 | }; 13 | return dfs(0, 1, 1); 14 | } 15 | }; -------------------------------------------------------------------------------- /programming/sort/179.最大数.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=179 lang=cpp 3 | * 4 | * [179] 最大数 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | string largestNumber(vector& nums) { 11 | string res=""; 12 | if(nums.empty()) return res; 13 | // 定义排序方式 14 | sort(nums.begin(),nums.end(),[](const int& a,const int& b) 15 | {return to_string(a)+to_string(b)>to_string(b)+to_string(a);}); 16 | for (auto c:nums) res+=to_string(c); 17 | return (nums[0]==0) ? "0" : res; 18 | } 19 | }; 20 | // @lc code=end 21 | 22 | -------------------------------------------------------------------------------- /programming/dynamic-programming/1458.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int maxDotProduct(vector& nums1, vector& nums2) { 4 | int m = nums1.size(), n = nums2.size(); 5 | vector> dp(m + 1, vector(n + 1, INT_MIN/2)); 6 | for(int i = 1; i <= m; ++i) { 7 | for(int j = 1; j <= n; ++j) { 8 | int v = nums1[i - 1] * nums2[j - 1]; 9 | // 注意这里有四种情况 10 | dp[i][j] = max({dp[i - 1][j - 1] + v, v, dp[i - 1][j], dp[i][j - 1]}); 11 | } 12 | } 13 | return dp[m][n]; 14 | } 15 | }; -------------------------------------------------------------------------------- /programming/slide-window/slide-window.md: -------------------------------------------------------------------------------- 1 | # 滑动窗口相关算法练习题 2 | 3 | ``` 4 | // 滑动窗口的通用代码 5 | int left = 0, right = 0; 6 | 7 | while (right < s.size()) { 8 | window.add(s[right]); 9 | right++; 10 | 11 | while (valid) { 12 | window.remove(s[left]); 13 | left++; 14 | } 15 | } 16 | 17 | ``` 18 | | Title | Solution | Source| 19 | | ---- | -------|------| 20 | |无重复字符串最长子串|[3.无重复字符串最长子串](3.无重复字符的最长子串.cpp)|| 21 | |最小覆盖子串|[76.最小覆盖子串](76.最小覆盖子串.cpp)| 22 | |滑动窗口|[239.滑动窗口](../data-structure/239.滑动窗口最大值.cpp)| 23 | |438. 找到字符串中所有字母异位词|[438. 找到字符串中所有字母异位词](438.找到字符串中所有字母异位词.cpp)| 24 | 25 | -------------------------------------------------------------------------------- /programming/dynamic-programming/718.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int findLength(vector& nums1, vector& nums2) { 4 | int m = nums1.size(), n = nums2.size(); 5 | vector> dp(m + 1, vector(n + 1, 0)); 6 | int res = 0; 7 | for(int i = 1; i <= m; i++) { 8 | for(int j = 1; j <= n; j++) { 9 | if(nums1[i - 1] == nums2[j - 1]) { 10 | dp[i][j] = dp[i - 1][j - 1] + 1; 11 | } 12 | res = max(res, dp[i][j]); 13 | } 14 | } 15 | return res; 16 | } 17 | }; -------------------------------------------------------------------------------- /programming/binary-search/153.寻找旋转排序数组中的最小值.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=153 lang=cpp 3 | * 4 | * [153] 寻找旋转排序数组中的最小值 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | int findMin(vector& nums) { 11 | int left=0, right=nums.size()-1; 12 | while(left < right) { 13 | int mid = (left + right) >> 1; 14 | if(nums[mid] > nums[right]) { 15 | left = mid + 1; 16 | } else { 17 | right = mid; 18 | } 19 | } 20 | return nums[left]; 21 | } 22 | }; 23 | // @lc code=end 24 | 25 | -------------------------------------------------------------------------------- /programming/bit-manipulation/137.只出现一次的数字-ii.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=137 lang=cpp 3 | * 4 | * [137] 只出现一次的数字 II 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | // 通用的解法: 统计每一位出现的次数 11 | int singleNumber(vector& nums) { 12 | int ans = 0; 13 | for (int bit = 0; bit < 32; bit++) { 14 | int counter = 0; 15 | for (int i = 0; i < nums.size(); i++) 16 | counter += (nums[i] >> bit) & 1; 17 | ans += (counter % 3) << bit; 18 | } 19 | return ans; 20 | } 21 | }; 22 | // @lc code=end 23 | 24 | -------------------------------------------------------------------------------- /programming/array/118.杨辉三角.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=118 lang=cpp 3 | * 4 | * [118] 杨辉三角 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | vector> generate(int numRows) { 11 | vector > res; 12 | if(numRows <=0) return res; 13 | for(int i=0; i v(i+1, 1); 15 | for(int j=1; j& wordDict) { 4 | set dict(wordDict.begin(), wordDict.end()); 5 | int n = s.size(); 6 | vector dp(n+1, false); 7 | dp[0] = true; 8 | for(int i=1; i<=n; i++) { 9 | for(int j=i-1; j>=0; j--) { 10 | if(dp[j] && dict.find(s.substr(j, i-j)) != dict.end()) { 11 | dp[i] = true; 12 | break; 13 | } 14 | } 15 | } 16 | return dp[n]; 17 | 18 | } 19 | }; -------------------------------------------------------------------------------- /programming/dynamic-programming/2466.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int countGoodStrings(int low, int high, int zero, int one) { 4 | // 爬楼梯变种,主要取mode 5 | int mod = 1e9 + 7; 6 | vector dp(high + 1); 7 | dp[0] = 1; 8 | int ans = 0; 9 | for(int i = 1; i <= high; ++i) { 10 | if(i >= zero) dp[i] += dp[i - zero]; 11 | if(i >= one) dp[i] += dp[i - one]; 12 | dp[i] %= mod; 13 | if(i >= low) { 14 | ans += dp[i]; 15 | ans %= mod; 16 | } 17 | } 18 | return ans; 19 | } 20 | }; -------------------------------------------------------------------------------- /programming/dynamic-programming/123.买卖股票的最佳时机-iii.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=123 lang=cpp 3 | * 4 | * [123] 买卖股票的最佳时机 III 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | int maxProfit(vector& prices) { 11 | 12 | int dp_i10 = 0, dp_i11 = INT_MIN; 13 | int dp_i20 = 0, dp_i21 = INT_MIN; 14 | for (int price : prices) { 15 | dp_i20 = max(dp_i20, dp_i21 + price); 16 | dp_i21 = max(dp_i21, dp_i10 - price); 17 | dp_i10 = max(dp_i10, dp_i11 + price); 18 | dp_i11 = max(dp_i11, -price); 19 | } 20 | return dp_i20; 21 | } 22 | }; 23 | // @lc code=end 24 | 25 | -------------------------------------------------------------------------------- /programming/tree/530.二叉搜索树的最小绝对差.cpp: -------------------------------------------------------------------------------- 1 | // 中序遍历即可 2 | class Solution { 3 | public: 4 | int getMinimumDifference(TreeNode* root) { 5 | if(!root) return 0; 6 | int last = -1e5, res = INT_MAX; 7 | stack st; 8 | while(root || !st.empty()) { 9 | while(root) { 10 | st.push(root); 11 | root = root->left; 12 | } 13 | root = st.top(); 14 | st.pop(); 15 | res = min(res, root->val - last); 16 | last = root->val; 17 | root = root->right; 18 | } 19 | return res; 20 | } 21 | }; -------------------------------------------------------------------------------- /programming/slide-window/1493.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int longestSubarray(vector& nums) { 4 | // 问题等价于0最多出现1次的窗口最长 5 | int size = nums.size(), res = 0; 6 | int cnt0 = 0; 7 | for(int i=0, j=0; j < size; j++) { 8 | if (nums[j] == 0) { 9 | cnt0 += 1; 10 | } 11 | // 窗口不符合条件 12 | while(cnt0 > 1) { 13 | if(nums[i++] == 0) { 14 | cnt0--; 15 | } 16 | } 17 | res = max(res, j-i); // 这里有细微的变化 18 | } 19 | return res; 20 | 21 | } 22 | }; -------------------------------------------------------------------------------- /programming/dynamic-programming/2606.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int maximumCostSubstring(string s, string chars, vector& vals) { 4 | vector v(26, 0); 5 | for(int i=0; i < v.size(); i++) { 6 | v[i] = i + 1; 7 | } 8 | for(int i = 0; i < chars.size(); i++) { 9 | v[chars[i] - 'a'] = vals[i]; 10 | } 11 | // dp[i] = max(dp[i-1], 0) + nums[i] 12 | int res = 0, f = 0; 13 | for(int i = 0; i < s.size(); i++) { 14 | f = max(f, 0) + v[s[i] - 'a']; 15 | res = max(res, f); 16 | } 17 | return res; 18 | } 19 | }; -------------------------------------------------------------------------------- /programming/dynamic-programming/279.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | // 从1-sqrt(n)中选择x个数,可重复 4 | // 完全背包最值问题 5 | // dp[i][j] 表示前i个数中,和为j的最小值 6 | // dp[i][j] = min(dp[i-1][j], dp[i-1][j-x*x] + 1) 7 | // dp[j] = min(dp[j], dp[j-x*x] + 1) 8 | int numSquares(int n) { 9 | vector dp(n+1, INT_MAX); 10 | dp[0] = 0; 11 | for(int num = 1; num*num <= n; num++) { 12 | for(int i=0; i<=n; i++) { 13 | if(i-num*num >= 0) { 14 | dp[i] = min(dp[i], dp[i-num*num] + 1); 15 | } 16 | } 17 | } 18 | return dp[n]; 19 | } 20 | }; -------------------------------------------------------------------------------- /programming/slide-window/643.子数组最大平均数 I.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | double findMaxAverage(vector& nums, int k) { 4 | int size = nums.size(); 5 | if (size < k) return 0; 6 | double max_sum = INT_MIN, sum = 0; 7 | // 初始化窗口 8 | for(int i=0; i < k-1; i++) { 9 | sum += nums[i]; 10 | } 11 | for(int i=k-1; i < size; i++) { 12 | // insert 13 | sum += nums[i]; 14 | // update 15 | max_sum = max(max_sum, sum); 16 | // delete 17 | sum -= nums[i-k+1]; 18 | } 19 | return max_sum / k; 20 | } 21 | }; -------------------------------------------------------------------------------- /programming/linked_list/160.相交链表.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 | // 2 6 4 13 | // 1 5 14 | ListNode *a = headA, *b = headB; 15 | //while(a && b && a != b) { 这样ab都不会有空,进入死循环 16 | while(a != b) { 17 | a = a ? a->next : headB; // 要让a>next可能为空,才能跳出循环 18 | b = b ? b->next : headA; 19 | } 20 | return a; 21 | } 22 | }; -------------------------------------------------------------------------------- /programming/876.链表的中间结点.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=876 lang=cpp 3 | * 4 | * [876] 链表的中间结点 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for singly-linked list. 10 | * struct ListNode { 11 | * int val; 12 | * ListNode *next; 13 | * ListNode(int x) : val(x), next(NULL) {} 14 | * }; 15 | */ 16 | class Solution { 17 | public: 18 | ListNode* middleNode(ListNode* head) { 19 | ListNode *slow = head, *fast=head; 20 | while(fast && fast->next) { 21 | slow = slow->next; 22 | fast = fast->next->next; 23 | } 24 | return slow; 25 | } 26 | }; 27 | // @lc code=end 28 | 29 | -------------------------------------------------------------------------------- /programming/bit-manipulation/位运算题型总结.md: -------------------------------------------------------------------------------- 1 | # 位运算题型总结 2 | 3 | - 3370. 仅含置位位的最小整数 : 求二进制宽度 bit_widty 4 | - 3226. 使两个整数相等的位更改次数 : 集合的思想 n & k == k , k 属于n 5 | - 1356. 根据数字二进制下 1 的数目排序 : 二进制1的个数动态规划 bit[i] == bit[i>>1] + (i&1) 6 | - 461. 汉明距离 : 异或求二进制1的个数 ___builtin_popcount(a^b) 7 | - 476. 数字的补数: 8 | 9 | 10 | 与或运算 11 | - 2980. 检查按位或是否存在尾随零, 只需要判断奇偶即可,注意位运算优先级问题 12 | - 1318. 或运算的最小翻转次数 13 | - 2419. 按位与最大的最长子数组: 变相求最大值的最长子数组,一次遍历,需要会 14 | 15 | 16 | 17 | log trick 18 | - 3171. 找到按位或最接近 K 的子数组 : 子数组,逆序,提取停止 19 | - 1521. 找到最接近目标值的函数值 同 3171 题,OR 改成 AND 20 | - 3097. 或值至少为 K 的最短子数组 II 21 | 22 | 23 | 异或的性质 24 | a^a = 0, a^0 = a 25 | - 136. 只出现一次的数字, 将所有数异或,结果就是只出现一次的数字 -------------------------------------------------------------------------------- /programming/backtrack/77.组合.cpp: -------------------------------------------------------------------------------- 1 | // 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。 2 | 3 | class Solution { 4 | public: 5 | vector tmp; 6 | vector> res; 7 | void dfs(int n, int k, int beg) { 8 | if(tmp.size() == k) { 9 | res.push_back(tmp); 10 | return; 11 | } 12 | // 这里可以进行剪枝 13 | for(int i=beg; i <= n - (k - tmp.size()) + 1; i++) { 14 | tmp.push_back(i); 15 | dfs(n, k, i+1); 16 | tmp.pop_back(); 17 | } 18 | 19 | } 20 | vector> combine(int n, int k) { 21 | dfs(n, k, 1); 22 | return res; 23 | 24 | } 25 | }; -------------------------------------------------------------------------------- /programming/dynamic-programming/1035.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int maxUncrossedLines(vector& nums1, vector& nums2) { 4 | int m = nums1.size(), n = nums2.size(); 5 | vector> dp(m + 1, vector(n + 1, 0)); 6 | for (int i = 1; i <= m; ++i) { 7 | for (int j = 1; j <= n; ++j) { 8 | if (nums1[i - 1] == nums2[j - 1]) { 9 | dp[i][j] = dp[i - 1][j - 1] + 1; 10 | } else { 11 | dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); 12 | } 13 | } 14 | } 15 | return dp[m][n]; 16 | 17 | } 18 | }; -------------------------------------------------------------------------------- /programming/backtrack/0077.组合.cpp: -------------------------------------------------------------------------------- 1 | // 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。 2 | 3 | class Solution { 4 | public: 5 | vector tmp; 6 | vector> res; 7 | void dfs(int n, int k, int beg) { 8 | if(tmp.size() == k) { 9 | res.push_back(tmp); 10 | return; 11 | } 12 | // 这里可以进行剪枝 13 | for(int i=beg; i <= n - (k - tmp.size()) + 1; i++) { 14 | tmp.push_back(i); 15 | dfs(n, k, i+1); 16 | tmp.pop_back(); 17 | } 18 | 19 | } 20 | vector> combine(int n, int k) { 21 | dfs(n, k, 1); 22 | return res; 23 | 24 | } 25 | }; -------------------------------------------------------------------------------- /programming/dynamic-programming/1964.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | // dp[i] 以i结尾的最长递增子序列, 非严格递增 4 | vector longestObstacleCourseAtEachPosition(vector& obstacles) { 5 | int n = obstacles.size(); 6 | vector dp(n, 1), g; 7 | for(int i=0; i count; 13 | int ans = 0; 14 | for (char c : s) 15 | ++count[c]; 16 | // a = 5 17 | for (auto p : count) { 18 | int v = p.second; 19 | ans += v / 2 * 2; // ans + 4 20 | if (v % 2 == 1 and ans % 2 == 0) // 第一次遇到奇数 21 | ++ans; 22 | } 23 | return ans; 24 | } 25 | }; 26 | // @lc code=end 27 | 28 | -------------------------------------------------------------------------------- /programming/dynamic-programming/416.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | 4 | // f[i][j] = f[i-1][j] || f[i-1][j-nums[i]] 5 | // f[i+1][j] = f[i][j] || f[i][j-nums[i]] 6 | // f[j] = f[j] || f[j-nums[i]] 7 | bool canPartition(vector& nums) { 8 | int s = reduce(nums.begin(), nums.end(), 0); 9 | if(s%2) return false; 10 | s /= 2; 11 | vector f(s +1, 0); 12 | f[0] = true; 13 | // 遍历nums 14 | for(auto num : nums) { 15 | // 遍历target 16 | for(int j = s; j >= num; --j) { 17 | f[j] = f[j] || f[j-num]; 18 | } 19 | } 20 | return f[s]; 21 | } 22 | }; -------------------------------------------------------------------------------- /programming/slide-window/2379.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int minimumRecolors(string blocks, int k) { 4 | int size = blocks.size(); 5 | if(size < k) return 0; 6 | int cnt = 0, res = INT_MAX; 7 | for(int i=0; i < k-1; i++) { 8 | if(blocks[i] == 'W') { 9 | cnt += 1; 10 | } 11 | } 12 | for(int i=k-1; i < size; i++) { 13 | if(blocks[i] == 'W') { 14 | cnt += 1; 15 | } 16 | res = min(res, cnt); 17 | if(blocks[i-k+1] == 'W') { 18 | cnt -= 1; 19 | } 20 | } 21 | return res; 22 | } 23 | }; -------------------------------------------------------------------------------- /programming/array/75.颜色分类.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=75 lang=cpp 3 | * 4 | * [75] 颜色分类 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | void sortColors(vector& nums) { 11 | // p0:0 的右边界, p2:2的左边界 12 | int p0 = 0, p2 = nums.size()-1, cur=0; 13 | while(cur<=p2) { 14 | // 15 | if(nums[cur] == 0) { 16 | swap(nums[cur++], nums[p0++]); 17 | } else if(nums[cur] == 2) { 18 | swap(nums[cur], nums[p2--]); // 此时cur不加1,p2-- 19 | } else { 20 | cur++; // 当为1时,直接++ 21 | } 22 | } 23 | } 24 | }; 25 | // @lc code=end 26 | 27 | -------------------------------------------------------------------------------- /programming/backtrack/回溯题型总结.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | void backtracking(参数) { 4 | if (终止条件) { 5 | 存放结果; 6 | return; 7 | } 8 | 9 | for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) { 10 | 处理节点; 11 | backtracking(路径,选择列表); // 递归 12 | 回溯,撤销处理结果 13 | } 14 | } 15 | 16 | 17 | # 入门回溯 18 | - 17 19 | 20 | # 子集型回溯 21 | 两种方法: 选或不选 ; 从答案的角度 22 | - 78 23 | - 1836, 和子集是一样的,有其他数学做法 24 | - 784, 回溯,从答案的角度出发,记得回溯现场 25 | - 3566 26 | 27 | # 划分型回溯 28 | - 131 : 分割回文串 29 | - 2689: 求一个整数的惩罚数 30 | - 1593: 拆分字符串使唯一子字符串的数目最大 31 | - 306: 确定第一个和第二个数,然后递归 32 | 33 | # 组合型回溯 34 | - 39 : 组合综述 35 | - 77 组合 , 模版题,优化剪枝 36 | - 216 组合总和 III 找出所有相加之和为 n 的 k 个数的组合,且满足下列条件: 37 | - 22 括号生成, 2n个位置,选择问题 -------------------------------------------------------------------------------- /programming/dynamic-programming/120.三角形最小路径和.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=120 lang=cpp 3 | * 4 | * [120] 三角形最小路径和 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | int minimumTotal(vector>& triangle) { 11 | if(triangle.size() <=0 || triangle[0].size() <= 0 ) { 12 | return 0; 13 | } 14 | int m = triangle.size(); 15 | for(int i=m-2; i>=0; i--) { 16 | for(int j=0; j<=i; j++) { 17 | triangle[i][j] = min(triangle[i+1][j], triangle[i+1][j+1]) + triangle[i][j]; 18 | } 19 | } 20 | return triangle[0][0]; 21 | } 22 | }; 23 | // @lc code=end 24 | 25 | -------------------------------------------------------------------------------- /programming/greedy/455.分发饼干.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=455 lang=cpp 3 | * 4 | * [455] 分发饼干 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | int findContentChildren(vector& g, vector& s) { 11 | sort(g.begin(), g.end()); 12 | sort(s.begin(), s.end()); 13 | int g_size = g.size(), s_size = s.size(); 14 | int g_idx = 0, s_idx = 0; 15 | while(g_idx < g_size && s_idx < s_size) { 16 | // 满足需求 17 | if(g[g_idx] <= s[s_idx]) { 18 | g_idx += 1; 19 | } 20 | s_idx += 1; 21 | } 22 | return g_idx; 23 | } 24 | }; 25 | // @lc code=end 26 | 27 | -------------------------------------------------------------------------------- /programming/string/383.赎金信.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。 3 | 4 | 如果可以,返回 true ;否则返回 false 。 5 | 6 | magazine 中的每个字符只能在 ransomNote 中使用一次。 7 | */ 8 | bool canConstruct(string ransomNote, string magazine) { 9 | if (ransomNote.size() > magazine.size()) { 10 | return false; 11 | } 12 | vector res(26, 0); 13 | for(int i = 0; i < magazine.size(); i++) { 14 | res[magazine[i] - 'a']++; 15 | } 16 | for(int i = 0; i< ransomNote.size(); i++) { 17 | res[ransomNote[i] - 'a']--; 18 | if(res[ransomNote[i] - 'a'] < 0) { 19 | return false; 20 | } 21 | } 22 | return true; 23 | } -------------------------------------------------------------------------------- /programming/tree/508.出现次数最多的子树和.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | unordered_map cnt; 3 | int maxCnt = 0; 4 | 5 | int dfs(TreeNode *node) { 6 | if (node == nullptr) { 7 | return 0; 8 | } 9 | int sum = node->val + dfs(node->left) + dfs(node->right); 10 | maxCnt = max(maxCnt, ++cnt[sum]); 11 | return sum; 12 | } 13 | 14 | public: 15 | vector findFrequentTreeSum(TreeNode *root) { 16 | dfs(root); 17 | vector ans; 18 | for (auto &[s, c]: cnt) { 19 | if (c == maxCnt) { 20 | ans.emplace_back(s); 21 | } 22 | } 23 | return ans; 24 | } 25 | }; -------------------------------------------------------------------------------- /DataStructure/vectorAndMap/convert.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | int main() { 9 | map > name_score_map; 10 | name_score_map["LiMin"] = 90; 11 | name_score_map["ZiLinMi"] = 79; 12 | name_score_map["BoB"] = 92; 13 | //mapתvector 14 | vector>v(name_score_map.begin(), name_score_map.end()); 15 | sort(v.begin(), v.end(), [](paira, pairb) { 16 | return a.first.size() < b.first.size(); }); 17 | for (auto c : v) { 18 | cout << c.first << " " << c.second << endl; 19 | } 20 | return 0; 21 | } -------------------------------------------------------------------------------- /programming/string/38.报数.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=38 lang=cpp 3 | * 4 | * [38] 报数 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | string countAndSay(int n) { 11 | if (n == 0) return ""; 12 | string res = "1"; 13 | while (--n) { 14 | string cur = ""; 15 | for (int i = 0; i < res.size(); i++) { 16 | int count = 1; 17 | while ((i + 1 < res.size()) && (res[i] == res[i + 1])){ 18 | count++; 19 | i++; 20 | } 21 | cur += to_string(count) + res[i]; 22 | } 23 | res = cur; 24 | } 25 | return res; 26 | } 27 | }; 28 | // @lc code=end 29 | 30 | -------------------------------------------------------------------------------- /programming/binary-search/154.寻找旋转排序数组中的最小值-ii.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=154 lang=cpp 3 | * 4 | * [154] 寻找旋转排序数组中的最小值 II 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | int findMin(vector& nums) { 11 | int left =0, right = nums.size()-1; 12 | while(left < right) { 13 | int mid = (left + right) >> 1; 14 | if(nums[mid] > nums[right]) { 15 | left = mid+1; 16 | } else if(nums[mid] == nums[right]) { 17 | right--; 18 | } else { 19 | right = mid; 20 | } 21 | } 22 | return nums[left]; 23 | } 24 | }; 25 | // @lc code=end 26 | 27 | -------------------------------------------------------------------------------- /programming/dynamic-programming/583.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | // 思路转换,删除最少等价求最长公共子序列 4 | // m + n - 2 * cls 5 | int minDistance(string word1, string word2) { 6 | int m = word1.size(), n = word2.size(); 7 | vector> dp(m + 1, vector(n + 1, 0)); 8 | for(int i = 1; i <= m; ++i) { 9 | for(int j = 1; j <= n; ++j) { 10 | if(word1[i - 1] == word2[j - 1]) { 11 | dp[i][j] = dp[i - 1][j - 1] + 1; 12 | } else { 13 | dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); 14 | } 15 | } 16 | } 17 | return m + n - 2 * dp[m][n]; 18 | } 19 | }; -------------------------------------------------------------------------------- /programming/213.打家劫舍-ii.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=213 lang=cpp 3 | * 4 | * [213] 打家劫舍 II 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | int rob(vector& nums) { 11 | int n = nums.size(); 12 | if (n < 2) return n ? nums[0] : 0; 13 | return max(robber(nums, 0, n - 2), robber(nums, 1, n - 1)); 14 | } 15 | private: 16 | int robber(vector& nums, int l, int r) { 17 | int pre = 0, cur = 0; 18 | for (int i = l; i <= r; i++) { 19 | int temp = max(pre + nums[i], cur); 20 | pre = cur; 21 | cur = temp; 22 | } 23 | return cur; 24 | } 25 | }; 26 | // @lc code=end 27 | 28 | -------------------------------------------------------------------------------- /programming/slide-window/1343.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int numOfSubarrays(vector& arr, int k, int threshold) { 4 | int size = arr.size(); 5 | if (size < k) return 0; 6 | threshold = threshold * k; 7 | int res = 0, sum = 0; 8 | // 初始化窗口 9 | for(int i=0; i < k-1; i++) { 10 | sum += arr[i]; 11 | } 12 | for(int i=k-1; i < size; i++) { 13 | // insert 14 | sum += arr[i]; 15 | // update 16 | if(sum >= threshold) { 17 | res += 1; 18 | } 19 | // delete 20 | sum -= arr[i-k+1]; 21 | } 22 | return res; 23 | } 24 | }; -------------------------------------------------------------------------------- /programming/dynamic-programming/3290.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | // dp[i][j] = max(dp[i-1][j], dp[i-1][j-1] + a[j-1] * b[i-1]) 4 | // dp[j] = max(dp[j-1], dp[j-1] + a[j-1] * b[i]) 5 | long long maxScore(vector& a, vector& b) { 6 | vector dp(5, LLONG_MIN); 7 | dp[0] = 0; 8 | 9 | for(int i = 0; i < b.size(); ++i) { 10 | // 从后往前更新,避免重复使用本轮更新的值 11 | for(int j = min(4, i + 1); j >= 1; --j) { 12 | if(dp[j-1] != LLONG_MIN) { 13 | dp[j] = max(dp[j], dp[j-1] + (long long)a[j-1] * b[i]); 14 | } 15 | } 16 | } 17 | 18 | return dp[4]; 19 | } 20 | }; -------------------------------------------------------------------------------- /programming/tree/1110.删点成林cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | vector ans; 3 | unordered_set s; 4 | 5 | TreeNode* dfs(TreeNode *node) { 6 | if (node == nullptr) return nullptr; 7 | node->left = dfs(node->left); 8 | node->right = dfs(node->right); 9 | if (!s.count(node->val)) return node; 10 | if (node->left) ans.push_back(node->left); 11 | if (node->right) ans.push_back(node->right); 12 | return nullptr; 13 | } 14 | 15 | public: 16 | vector delNodes(TreeNode *root, vector &to_delete) { 17 | for (int x : to_delete) s.insert(x); 18 | if (dfs(root)) ans.push_back(root); 19 | return ans; 20 | } 21 | }; -------------------------------------------------------------------------------- /programming/two-pointers/21.奇数在偶数前.md: -------------------------------------------------------------------------------- 1 | [剑指 Offer 21. 调整数组顺序使奇数位于偶数前面](https://leetcode-cn.com/problems/diao-zheng-shu-zu-shun-xu-shi-qi-shu-wei-yu-ou-shu-qian-mian-lcof/) 2 | 3 | // 很简单的双指针算法 4 | 5 | class Solution { 6 | public: 7 | vector exchange(vector& nums) { 8 | int left = 0, right = nums.size() - 1; 9 | while (left < right) { 10 | if ((nums[left] & 1) != 0) { 11 | left ++; 12 | continue; 13 | } 14 | if ((nums[right] & 1) != 1) { 15 | right --; 16 | continue; 17 | } 18 | swap(nums[left++], nums[right--]); 19 | } 20 | return nums; 21 | } 22 | }; -------------------------------------------------------------------------------- /Algorithm/TicTacToe/TicTacToe.h: -------------------------------------------------------------------------------- 1 | #ifndef TICTACTOE_H 2 | #define TICTACTOE_H 3 | #include "ChessBoard.h" 4 | enum Role { Human, Comp }; 5 | static const int CompWin = 2; 6 | static const int Draw = 1; 7 | static const int HumanWin = 0; 8 | class TicTacToe { 9 | public: 10 | void start(); 11 | bool handleGameOver(); 12 | bool TicTacToe::gameIsOver(bool &draw, Role &win); 13 | Role chooseFirstPlace(); 14 | void compPlace(); 15 | int getBestMove(); 16 | void humanPlace(); 17 | int getPlacePosition(); 18 | void findCompMove(int& bestMove,int& value, int alpha, int beta); 19 | void findHumanMove(int& bestMove,int& value, int alpha, int beta); 20 | private: 21 | ChessBoard board; 22 | }; 23 | #endif // !TicTacToe 24 | 25 | -------------------------------------------------------------------------------- /programming/dynamic-programming/712.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | // dp[i][j] : s[:i] t[:j] 的最小值 4 | int minimumDeleteSum(string s1, string s2) { 5 | int m = s1.size(), n = s2.size(); 6 | vector> dp(m+1, vector(n+1, 0)); 7 | for(int i = 1; i <= m; i++) dp[i][0] = dp[i-1][0] + s1[i-1]; 8 | for(int j = 1; j <= n; j++) dp[0][j]= dp[0][j-1] + s2[j-1]; 9 | for(int i = 1; i <= m; i++) { 10 | for(int j = 1; j <= n; j++) { 11 | if(s1[i-1] == s2[j-1]) dp[i][j] = dp[i-1][j-1]; 12 | else dp[i][j] = min(dp[i-1][j] + s1[i-1], dp[i][j-1] + s2[j-1]); 13 | } 14 | } 15 | return dp[m][n]; 16 | } 17 | }; -------------------------------------------------------------------------------- /programming/linked_list/141.环形链表.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 | if(!head || !head->next) return false; 13 | ListNode *slow = head, *fast = head; 14 | while(fast && fast->next) { 15 | slow = slow->next; 16 | fast = fast->next->next; 17 | //cout << slow->val << " " << fast->val << endl; 18 | if(slow == fast) { 19 | return true; 20 | } 21 | } 22 | return false; 23 | } 24 | }; -------------------------------------------------------------------------------- /programming/array/4.二维数组中的查找.md: -------------------------------------------------------------------------------- 1 | 2 | ## [二维数组中的查找](https://leetcode-cn.com/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof/) 3 | 4 | 5 | ``` 6 | class Solution { 7 | public: 8 | // 此题需要注意的是,寻找合适的开始搜索的入口 9 | bool findNumberIn2DArray(vector>& matrix, int target) { 10 | if(matrix.empty() || matrix[0].empty()) return 0; 11 | int m = matrix.size(), n = matrix[0].size(); 12 | int i=0, j = n-1; 13 | while(i < m && j>=0) { 14 | if(matrix[i][j]==target) 15 | return true; 16 | else if(matrix[i][j]& nums1, int m, vector& nums2, int n) { 11 | int k = m + n -1; 12 | int i = m - 1, j = n - 1; 13 | while(i>=0 && j>=0) { 14 | if(nums2[j] > nums1[i]) { 15 | nums1[k--] = nums2[j--]; 16 | } else { 17 | nums1[k--] = nums1[i--]; 18 | } 19 | } 20 | // j >= 0 21 | while(j >= 0) { 22 | nums1[k--] = nums2[j--]; 23 | } 24 | // i >= 0 不用管 25 | } 26 | }; 27 | // @lc code=end 28 | 29 | -------------------------------------------------------------------------------- /programming/math/470.用-rand-7-实现-rand-10.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=470 lang=cpp 3 | * 4 | * [470] 用 Rand7() 实现 Rand10() 5 | */ 6 | 7 | // @lc code=start 8 | // The rand7() API is already defined for you. 9 | // int rand7(); 10 | // @return a random integer in the range 1 to 7 11 | 12 | class Solution { 13 | public: 14 | int rand10() { 15 | // 首先得到一个数, rand7() -> 0, 1, 2, .. 6 16 | // 0 ... 49 的均匀 17 | int num = (rand7() - 1) * 7 + rand7(); 18 | // 只要它还大于40,那你就给我不断生成吧 19 | while (num > 40) { 20 | num = (rand7() - 1) * 7 + rand7(); 21 | } 22 | // 返回结果,+1是为了解决 40%10为0的情况 23 | return 1 + num % 10; 24 | } 25 | }; 26 | // @lc code=end 27 | 28 | -------------------------------------------------------------------------------- /Algorithm/math/约瑟夫问题.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 题目: https://leetcode-cn.com/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof/ 4 | 5 | ``` 6 | class Solution { 7 | public: 8 | //令f[n]表示当有n个候选人时,最后当选者的编号。 9 | //f[1] = 0 10 | //f[n] = (f[n - 1] + K) mod n 11 | int lastRemaining(int n, int m) { 12 | if (n<=0||m<=0) return -1; 13 | //vectordp(n+1,0); 14 | int pre = 0, cur = 0; 15 | for (int i=2;i<=n;i++) { 16 | cur = (pre + m) % i; 17 | pre = cur; 18 | } 19 | //dp[i]=(dp[i-1]+m)%i; 20 | //return dp[n]; 21 | return cur; 22 | } 23 | } 24 | ``` 25 | 26 | ## 参考答案: 27 | [数论三·约瑟夫问题](http://hihocoder.com/problemset/problem/1296?sid=861197) 28 | -------------------------------------------------------------------------------- /programming/binary-search/88.合并两个有序数组.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=88 lang=cpp 3 | * 4 | * [88] 合并两个有序数组 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | void merge(vector& nums1, int m, vector& nums2, int n) { 11 | int i=m-1, j=n-1; 12 | while(i>=0 && j>=0) { 13 | if(nums1[i] < nums2[j]) { 14 | nums1[i+j+1] = nums2[j]; 15 | j--; 16 | } else{ 17 | nums1[i+j+1] = nums1[i]; 18 | i--; 19 | } 20 | } 21 | // 注意nums2有剩余元素 22 | while(j>=0) { 23 | nums1[j] = nums2[j]; 24 | j--; 25 | } 26 | } 27 | }; 28 | // @lc code=end 29 | 30 | -------------------------------------------------------------------------------- /programming/dynamic-programming/2707.字符串中的额外字符.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | // dp[i] 当前字符串的最少删除次数 4 | int minExtraChar(string s, vector& dictionary) { 5 | int n = s.size(); 6 | set st(dictionary.begin(), dictionary.end()); 7 | vector dp(n + 1, INT_MAX); 8 | dp[0] = 0; 9 | for(int i=1; i<=n; i++) { 10 | dp[i] = dp[i - 1] + 1; // 不选 11 | // 枚举选哪个 12 | for(int j=i-1; j>=0; j--) { 13 | string cur = s.substr(j, i - j); 14 | if(st.find(cur) != st.end()) { 15 | dp[i] = min(dp[i], dp[j]); 16 | } 17 | } 18 | } 19 | return dp[n]; 20 | } 21 | }; -------------------------------------------------------------------------------- /programming/dynamic-programming/918.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | // 1.最大子数组在中间 最大子数组和 max_s 4 | // 2.最大子数组跨两边 sum - min_s 5 | // 3. min_s == sum, 返回max_s 6 | int maxSubarraySumCircular(vector& nums) { 7 | int max_s = INT_MIN; 8 | int min_s = 0; 9 | int max_f = 0, min_f = 0, sum = 0; 10 | for(auto x : nums) { 11 | // 以x结尾的最大子数组和 12 | max_f = max(x, max_f + x); 13 | // 以x结尾的最小子数组和 14 | min_f = min(x, min_f + x); 15 | max_s = max(max_s, max_f); 16 | min_s = min(min_s, min_f); 17 | sum += x; 18 | } 19 | return sum == min_s ? max_s : max(max_s, sum - min_s); 20 | 21 | } 22 | }; -------------------------------------------------------------------------------- /programming/two-pointers/125.验证回文串.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=125 lang=cpp 3 | * 4 | * [125] 验证回文串 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | bool isPalindrome(string s) { 11 | if(s.empty()) return true; 12 | 13 | int i=0, j = s.size()-1; 14 | while(i 0) { 13 | int bit = n % 10; 14 | sum += bit * bit; 15 | n = n / 10; 16 | } 17 | return sum; 18 | } 19 | 20 | bool isHappy(int n) { 21 | int slow = n, fast = n; 22 | do { 23 | slow = bitSquareSum(slow); 24 | fast = bitSquareSum(fast); 25 | fast = bitSquareSum(fast); 26 | } while(slow != fast); 27 | 28 | return slow == 1; 29 | } 30 | }; 31 | // @lc code=end 32 | 33 | -------------------------------------------------------------------------------- /programming/dynamic-programming/322.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | // 完全背包最值问题 4 | // dp[i][j] 表示使用前i种硬币,凑成j的最少硬币数 5 | // dp[i][j] = min(dp[i-1][j], dp[i][j-coins[i]]+1]) // 不选或选 6 | // dp[j] = min(dp[j], dp[j-coins[i]]+1]) 7 | int coinChange(vector& coins, int amount) { 8 | vector dp(amount+1, INT_MAX/2); 9 | dp[0] = 0; // 初始化 10 | // 遍历nums 11 | for(auto coin : coins) { 12 | // 正序遍历amount 13 | for(int j=0; j<=amount; j++) { 14 | if(j >= coin) { 15 | dp[j] = min(dp[j], dp[j-coin]+1); 16 | } 17 | } 18 | } 19 | return dp[amount] == INT_MAX/2 ? -1 : dp[amount]; 20 | 21 | } 22 | }; -------------------------------------------------------------------------------- /programming/dynamic-programming/174.地下城游戏.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=174 lang=cpp 3 | * 4 | * [174] 地下城游戏 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | int calculateMinimumHP(vector>& dungeon) { 11 | if (dungeon.empty() || dungeon[0].empty()) return -1; 12 | int m = dungeon.size(), n = dungeon[0].size(); 13 | vector> dp(m + 1, vector(n + 1, 1e9)); 14 | dp[m][n-1] = 1; 15 | for (int i = m - 1; i >= 0; --i) { 16 | for (int j = n - 1; j >= 0; --j) { 17 | dp[i][j] = max(1, min(dp[i][j + 1], dp[i + 1][j]) - dungeon[i][j]); 18 | } 19 | } 20 | return dp[0][0]; 21 | } 22 | }; 23 | // @lc code=end 24 | 25 | -------------------------------------------------------------------------------- /programming/array/119.杨辉三角-ii.py: -------------------------------------------------------------------------------- 1 | # 2 | # @lc app=leetcode.cn id=119 lang=python 3 | # 4 | # [119] 杨辉三角 II 5 | # 6 | 7 | # @lc code=start 8 | class Solution(object): 9 | def getRow(self, rowIndex): 10 | """ 11 | :type rowIndex: int 12 | :rtype: List[int] 13 | """ 14 | # j行的数据, 应该由j - 1行的数据计算出来. 15 | # 假设j - 1行为[1,3,3,1], 那么我们前面插入一个0(j行的数据会比j-1行多一个), 16 | # 然后执行相加[0+1,1+3,3+3,3+1,1] = [1,4,6,4,1], 最后一个1保留即可. 17 | r = [1] 18 | for i in range(1, rowIndex + 1): 19 | r.insert(0, 0) 20 | # 因为i行的数据长度为i+1, 所以j+1不会越界, 并且最后一个1不会被修改. 21 | for j in range(i): 22 | r[j] = r[j] + r[j + 1] 23 | return r 24 | 25 | 26 | # @lc code=end 27 | 28 | -------------------------------------------------------------------------------- /programming/array/31.下一个排列.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=31 lang=cpp 3 | * 4 | * [31] 下一个排列 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | // 1 5 8 4 7 6 5 3 1 11 | // a[i+1] > a[i]的位置, 4 12 | // 交换4,5 ,然后逆序 13 | void nextPermutation(vector& nums) { 14 | int len = nums.size(); 15 | if(len <= 1) return; 16 | int i = len -2; 17 | while(i>=0 && nums[i+1] <= nums[i]) i--; 18 | if(i>=0) { 19 | // 从后往前找到第一个比4大的数,进行交换 20 | int j = len-1; 21 | while(j>i && nums[j] <= nums[i]) j--; 22 | swap(nums[i], nums[j]); 23 | } 24 | reverse(nums.begin()+i+1,nums.end()); 25 | 26 | } 27 | }; 28 | // @lc code=end 29 | 30 | -------------------------------------------------------------------------------- /programming/dynamic-programming/2111.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int kIncreasing(vector& arr, int k) { 4 | int n = arr.size(); 5 | if(k > n) return 0; 6 | int ans = 0; 7 | vector g; 8 | for(int i=0; i < k; i++) { 9 | g.clear(); 10 | int length = 0; 11 | for(int j=i; j < n; j+=k) { 12 | length++; 13 | auto it = upper_bound(g.begin(), g.end(), arr[j]); 14 | if(it == g.end()) { 15 | g.push_back(arr[j]); 16 | } else { 17 | *it = arr[j]; 18 | } 19 | } 20 | ans += length - g.size(); 21 | } 22 | return ans; 23 | } 24 | }; -------------------------------------------------------------------------------- /programming/backtrack/1836.找出所有子集的异或总和再求和.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | // 最基础的做法 4 | class Solution { 5 | public: 6 | int res = 0; 7 | 8 | int help(vector& nums) { 9 | int ans = 0; 10 | for(auto x: nums) { 11 | ans = ans ^ x; 12 | } 13 | return ans; 14 | } 15 | 16 | void backtrace(vector& nums, vector& tmp, int beg) { 17 | res += help(tmp); 18 | for(int i=beg; i < nums.size(); i++) { 19 | tmp.push_back(nums[i]); 20 | backtrace(nums, tmp, i+1); 21 | tmp.pop_back(); 22 | } 23 | } 24 | 25 | int subsetXORSum(vector& nums) { 26 | vector tmp; 27 | backtrace(nums, tmp, 0); 28 | return res; 29 | 30 | } 31 | }; -------------------------------------------------------------------------------- /programming/backtrack/216.组合总数3.cpp: -------------------------------------------------------------------------------- 1 | // 经典回溯模版题,记得剪枝操作 2 | 3 | 4 | class Solution { 5 | public: 6 | vector> res; 7 | vector path; 8 | int tmp = 0; 9 | 10 | void dfs(int k, int n, int beg) { 11 | if(tmp == n && path.size() == k) { 12 | res.push_back(path); 13 | return; 14 | } 15 | // 剪枝 16 | for(int i=beg; i <= 9 && tmp <= n-i && path.size() < k; i++) { 17 | tmp += i; 18 | path.push_back(i); 19 | dfs(k, n, i+1); 20 | tmp -= i; 21 | path.pop_back(); 22 | } 23 | 24 | 25 | } 26 | vector> combinationSum3(int k, int n) { 27 | dfs(k, n, 1); 28 | return res; 29 | 30 | } 31 | }; -------------------------------------------------------------------------------- /programming/greedy/605.种花问题.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=605 lang=cpp 3 | * 4 | * [605] 种花问题 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | bool canPlaceFlowers(vector& flowerbed, int n) { 11 | int size = flowerbed.size(); 12 | for(int i=0; i < size && n > 0; i++) { 13 | // 连续三个为0,考虑首位特殊情况 14 | //不考虑首位 i-1, i , i+1都为0 15 | //考虑首位 i==0, i, i+1为0, i==m-1,ii-1 为0 16 | if((i == 0 || flowerbed[i-1] == 0) && 17 | (flowerbed[i] == 0) && 18 | (i==size-1 || flowerbed[i+1] == 0)) { 19 | n--; 20 | i++; // 下一个位置肯定不能 21 | } 22 | } 23 | return n == 0; 24 | } 25 | }; 26 | // @lc code=end 27 | 28 | -------------------------------------------------------------------------------- /programming/hash-table/187.重复的dna序列.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=187 lang=cpp 3 | * 4 | * [187] 重复的DNA序列 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | vector findRepeatedDnaSequences(string s) { 11 | int m = s.size(); 12 | vector res; 13 | if(m<=10) { 14 | return res; 15 | } 16 | unordered_map hash; 17 | for(int i=0; i<=m-10; i++) { 18 | string sub = s.substr(i, 10); 19 | 20 | //cout< &gas, vector &cost) { 11 | 12 | int start = gas.size()-1; 13 | int end = 0; 14 | int sum = gas[start] - cost[start]; 15 | while (start > end) { 16 | if (sum >= 0) { 17 | sum += gas[end] - cost[end]; 18 | ++end; 19 | } 20 | else { 21 | --start; 22 | sum += gas[start] - cost[start]; //while sum<0,just start--,and find this can make sum>=0.complement the end . 23 | } 24 | } 25 | return sum >= 0 ? start : -1; 26 | } 27 | }; 28 | // @lc code=end 29 | 30 | -------------------------------------------------------------------------------- /programming/sort/56.合并区间.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector> merge(vector>& intervals) { 4 | vector> res; 5 | if(intervals.empty()) return res; 6 | int m = intervals.size(); 7 | sort(intervals.begin(), intervals.end(), [](vector &a, vector &b) { 8 | return a[0] < b[0]; 9 | }); 10 | res.push_back(intervals[0]); 11 | for(int i=1; i < m; i++) { 12 | // 头大于尾 13 | if(intervals[i][0] > res.back()[1]) { 14 | res.push_back(intervals[i]); 15 | } else { 16 | // 可以合并,更新尾巴 17 | res.back()[1] = max(res.back()[1], intervals[i][1]); 18 | } 19 | } 20 | return res; 21 | } 22 | }; -------------------------------------------------------------------------------- /programming/array/167.两数之和-ii-输入有序数组.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=167 lang=cpp 3 | * 4 | * [167] 两数之和 II - 输入有序数组 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | vector twoSum(vector& numbers, int target) { 11 | vector res(2,0); 12 | int left = 0, right = numbers.size()-1; 13 | while(left < right) { 14 | if(numbers[left] + numbers[right] == target) { 15 | res[0] = left+1; 16 | res[1] = right+1; 17 | return res; 18 | } else if(numbers[left] + numbers[right] < target) { 19 | left++; 20 | } else { 21 | right--; 22 | } 23 | } 24 | return res; 25 | } 26 | }; 27 | // @lc code=end 28 | 29 | -------------------------------------------------------------------------------- /programming/backtrack/1593.拆分字符串使唯一子字符串的数目最大.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int maxUniqueSplit(string s) { 4 | dfs(s, 0); 5 | return ans; 6 | } 7 | 8 | void dfs(string& s, int pos) { 9 | // 剪枝 10 | if (s.size() - pos + us.size() <= ans) return; 11 | if (pos == s.size()) { 12 | ans = max(ans, (int)us.size()); 13 | return; 14 | } 15 | 16 | string temp; 17 | for (int i = pos; i < s.size(); i++) { 18 | temp += s[i]; 19 | if (us.find(temp) == us.end()) { 20 | us.insert(temp); 21 | dfs(s, i + 1); 22 | us.erase(temp); 23 | } 24 | } 25 | } 26 | private: 27 | int ans = 0; 28 | unordered_set us; 29 | }; -------------------------------------------------------------------------------- /programming/dynamic-programming/1191.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | // 53. 最大子数组和(repeat 表示重复次数) 3 | int maxSubArray(vector& nums, int repeat) { 4 | int n = nums.size(); 5 | int ans = 0, f = 0; // 本题允许子数组为空,ans 可以初始化成 0 6 | for (int i = 0; i < n * repeat; i++) { 7 | f = max(f, 0) + nums[i % n]; 8 | ans = max(ans, f); 9 | } 10 | return ans; 11 | } 12 | 13 | public: 14 | int kConcatenationMaxSum(vector& arr, int k) { 15 | if (k == 1) { 16 | return maxSubArray(arr, 1); 17 | } 18 | long long ans = maxSubArray(arr, 2); // arr+arr 的最大子数组和 19 | int s = reduce(arr.begin(), arr.end()); 20 | ans += 1LL * max(s, 0) * (k - 2); 21 | return ans % 1'000'000'007; 22 | } 23 | }; -------------------------------------------------------------------------------- /programming/array/3164.优质对数对.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | long long numberOfPairs(vector& nums1, vector& nums2, int k) { 4 | unordered_map count, count2; 5 | int max1 = 0; 6 | for (int num : nums1) { 7 | count[num]++; 8 | max1 = max(max1, num); 9 | } 10 | for (int num : nums2) { 11 | count2[num]++; 12 | } 13 | long long res = 0; 14 | for (const auto& pair : count2) { 15 | int a = pair.first, cnt = pair.second; 16 | for (int b = a * k; b <= max1; b += a * k) { 17 | if (count.count(b) > 0) { 18 | res += 1L * count[b] * cnt; 19 | } 20 | } 21 | } 22 | return res; 23 | 24 | } 25 | }; -------------------------------------------------------------------------------- /programming/dynamic-programming/1143.最长公共子序列.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=1143 lang=cpp 3 | * 4 | * [1143] 最长公共子序列 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | int longestCommonSubsequence(string text1, string text2) { 11 | int m = text1.size(), n = text2.size(); 12 | vector> dp(m+1, vector(n+1, 0)); 13 | // 初始化 14 | for(int i=1; i <= m; i++) { 15 | for(int j=1; j <= n; j++) { 16 | if(text1[i-1] == text2[j-1]) { 17 | dp[i][j] = dp[i-1][j-1] + 1; 18 | } else { 19 | dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); 20 | } 21 | } 22 | } 23 | return dp[m][n]; 24 | } 25 | }; 26 | // @lc code=end 27 | 28 | -------------------------------------------------------------------------------- /programming/array/1209.删除字符串中的所有相邻重复项-ii.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=1209 lang=cpp 3 | * 4 | * [1209] 删除字符串中的所有相邻重复项 II 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | string removeDuplicates(string s, int k) { 11 | // 很巧妙的使用栈,栈中存储的是个数,而不是字符 12 | stack st; 13 | for(int i=0; i stk; 13 | stringstream ss(path); 14 | while (getline(ss, tmp, '/')) { 15 | // 首先空和.不进行操作 16 | if (tmp == "" || tmp == ".") continue; 17 | // 弹出栈的条件 18 | if (tmp == ".." && !stk.empty()) 19 | stk.pop_back(); 20 | // 进栈 21 | else if (tmp != "..") 22 | stk.push_back(tmp); 23 | } 24 | for (auto str : stk) res += "/" + str; 25 | return res.empty() ? "/" : res; 26 | } 27 | }; 28 | // @lc code=end 29 | 30 | -------------------------------------------------------------------------------- /programming/two-pointers/209.长度最小的子数组.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=209 lang=cpp 3 | * 4 | * [209] 长度最小的子数组 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | int minSubArrayLen(int s, vector& nums) { 11 | if(nums.empty()) return 0; 12 | int res = INT_MAX, sum = 0; 13 | for(int i=0, j=0; i st; 14 | st.push(-1); 15 | int res = 0; 16 | for(int i=0; i < n; i++) { 17 | if(s[i] == '(') { 18 | st.push(i); 19 | } else { 20 | st.pop(); 21 | if(st.empty()) { 22 | st.push(i); 23 | } else { 24 | res = max(res, i - st.top()); 25 | } 26 | } 27 | } 28 | return res; 29 | 30 | } 31 | }; 32 | // @lc code=end 33 | 34 | -------------------------------------------------------------------------------- /programming/slide-window/2904.cpp: -------------------------------------------------------------------------------- 1 | // 注意字典序比较,条件满足多少 2 | class Solution { 3 | public: 4 | string shortestBeautifulSubstring(string s, int k) { 5 | if (ranges::count(s, '1') < k) { 6 | return ""; 7 | } 8 | string ans = s; 9 | int cnt1 = 0, left = 0; 10 | for (int right = 0; right < s.length(); right++) { 11 | cnt1 += s[right] - '0'; 12 | while (cnt1 > k || s[left] == '0') { 13 | cnt1 -= s[left++] - '0'; 14 | } 15 | if (cnt1 == k) { 16 | string t = s.substr(left, right - left + 1); 17 | if (t.length() < ans.length() || t.length() == ans.length() && t < ans) { 18 | ans = move(t); 19 | } 20 | } 21 | } 22 | return ans; 23 | } 24 | }; -------------------------------------------------------------------------------- /programming/tree/110.平衡二叉树.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=110 lang=cpp 3 | * 4 | * [110] 平衡二叉树 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for a binary tree node. 10 | * struct TreeNode { 11 | * int val; 12 | * TreeNode *left; 13 | * TreeNode *right; 14 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 15 | * }; 16 | */ 17 | class Solution { 18 | public: 19 | int depth(TreeNode* root) { 20 | return root ? max(depth(root->left), depth(root->right)) + 1 : 0; 21 | } 22 | bool isBalanced(TreeNode* root) { 23 | if(!root) return true; 24 | int left = depth(root->left); 25 | int right = depth(root->right); 26 | return abs(left-right) <= 1 && isBalanced(root->left) && isBalanced(root->right); 27 | } 28 | }; 29 | // @lc code=end 30 | 31 | -------------------------------------------------------------------------------- /programming/tree/637.二叉树的平均值.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector averageOfLevels(TreeNode* root) { 4 | vector res; 5 | if(!root) return res; 6 | queue que; 7 | que.push(root); 8 | while(!que.empty()) { 9 | int size = que.size(); 10 | double cnt = 0; 11 | for(int i=0; i < size; i++) { 12 | TreeNode* cur = que.front(); 13 | que.pop(); 14 | cnt += cur->val; 15 | if(cur->left) { 16 | que.push(cur->left); 17 | } 18 | if(cur->right) { 19 | que.push(cur->right); 20 | } 21 | } 22 | res.push_back(cnt / size); 23 | } 24 | return res; 25 | } 26 | }; -------------------------------------------------------------------------------- /programming/836.矩形重叠.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=836 lang=cpp 3 | * 4 | * [836] 矩形重叠 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | // 方法1: 逆向思维,不重叠地方情况 11 | bool isRectangleOverlap(vector& rec1, vector& rec2) { 12 | return !(rec1[2] <= rec2[0] || // left 13 | rec1[3] <= rec2[1] || // bottom 14 | rec1[0] >= rec2[2] || // right 15 | rec1[1] >= rec2[3]); // top 16 | } 17 | // 方法2: 矩形有重叠,则其投影一定有重叠 18 | /* 19 | x1, y1, x2, y2 x3,y3, x4, y4, 在x轴和y轴有重叠 20 | bool isRectangleOverlap(vector& rec1, vector& rec2) { 21 | return (min(rec1[2], rec2[2]) > max(rec1[0], rec2[0]) && 22 | min(rec1[3], rec2[3]) > max(rec1[1], rec2[1])); 23 | } 24 | */ 25 | }; 26 | // @lc code=end 27 | 28 | -------------------------------------------------------------------------------- /programming/linked_list/83.删除排序链表中的重复元素.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=83 lang=cpp 3 | * 4 | * [83] 删除排序链表中的重复元素 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for singly-linked list. 10 | * struct ListNode { 11 | * int val; 12 | * ListNode *next; 13 | * ListNode(int x) : val(x), next(NULL) {} 14 | * }; 15 | */ 16 | class Solution { 17 | public: 18 | ListNode* deleteDuplicates(ListNode* head) { 19 | if(!head || !head->next) { 20 | return head; 21 | } 22 | ListNode *cur = head;; 23 | while(cur->next) { 24 | if(cur->next->val == cur->val) { 25 | cur->next = cur->next->next; 26 | } else { 27 | cur = cur->next; 28 | } 29 | } 30 | return head; 31 | } 32 | }; 33 | // @lc code=end 34 | 35 | -------------------------------------------------------------------------------- /programming/array/3162.优质对数对.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int numberOfPairs(vector& nums1, vector& nums2, int k) { 4 | // 要求: a[i] = c * k * b[j], c = 1,2,3... 5 | // 统计k*b[j]的倍数 6 | unordered_map hash1, hash2; 7 | int res = 0, max_res = 0; 8 | for(auto n:nums1) { 9 | hash1[n]++; 10 | max_res = max(max_res, n); 11 | } 12 | for(auto n:nums2) { 13 | hash2[n]++; 14 | } 15 | for(auto num : hash2) { 16 | int n = num.first, cnt = num.second; 17 | // 倍数的写法要注意 18 | for(int b=k*n; b <= max_res ; b+=n*k) { 19 | if (hash1.count(b) > 0) { 20 | res += hash1[b] * cnt; 21 | } 22 | } 23 | } 24 | return res; 25 | } 26 | }; -------------------------------------------------------------------------------- /programming/string/URL化.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | URL化。编写一种方法,将字符串中的空格全部替换为%20。 3 | 假定该字符串尾部有足够的空间存放新增字符,并且知道字符串的“真实”长度。 4 | */ 5 | class Solution { 6 | public: 7 | string replaceSpaces(string S, int length) { 8 | int blank = 0; 9 | for(int i = 0; i < length; i++) { 10 | if(S[i] == ' ') { 11 | blank++; 12 | } 13 | } 14 | int end = length + blank * 2; 15 | int j = 0; 16 | // a b %20b 17 | for(int i = end-1; i >=0; i--) { 18 | if(S[length-1-j] == ' ') { 19 | S[i] = '0'; 20 | S[i-1] = '2'; 21 | S[i-2] = '%'; 22 | i= i - 2; 23 | } else { 24 | S[i] = S[length-1-j]; 25 | } 26 | j++; 27 | } 28 | return S.substr(0, end); 29 | } 30 | }; -------------------------------------------------------------------------------- /programming/dynamic-programming/115.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | // dp[i][j] 表示s[0...i-1] 中有多少个子串等于 t[0...j-1] 4 | int numDistinct(string s, string t) { 5 | int m = s.size(), n = t.size(); 6 | vector> dp(m+1, vector(n+1, 0)); 7 | 8 | // 空字符串是任何字符串的一个子序列 9 | for(int i = 0; i <= m; ++i) dp[i][0] = 1; 10 | 11 | for(int i = 1; i <= m; ++i) { 12 | for(int j = 1; j <= n; ++j) { 13 | if(s[i-1] == t[j-1]) { 14 | // 如果字符相等,可以选择匹配或不匹配 15 | dp[i][j] = dp[i-1][j-1] + dp[i-1][j]; 16 | } else { 17 | // 如果字符不等,只能选择不匹配 18 | dp[i][j] = dp[i-1][j]; 19 | } 20 | } 21 | } 22 | return dp[m][n]; 23 | } 24 | }; -------------------------------------------------------------------------------- /programming/math/89.格雷编码.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=89 lang=cpp 3 | * 4 | * [89] 格雷编码 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | // n = 1 res = [0, 1] 11 | // n = 2时 12 | // a. res的每一位二进制前加0, 十进制表示不变 13 | // b. res集合中逆序二进制放1 即 [1,0] -> [11, 10], 加上十进制的t*2 14 | vector grayCode(int n) { 15 | vector res; 16 | res.push_back(0); 17 | int t = 1; 18 | while (n -- ) { 19 | vector newRes = res; 20 | // for (int i = 0; i < res.size(); i ++ ) 21 | // newRes.push_back(res[i]); 22 | for (int i = res.size() - 1; i >= 0; i -- ) 23 | newRes.push_back(t + res[i]); 24 | res = newRes; 25 | t *= 2; 26 | } 27 | return res; 28 | } 29 | }; 30 | // @lc code=end 31 | 32 | -------------------------------------------------------------------------------- /programming/data-structure/3066.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int minOperations(vector& nums, int k) { 4 | int res = 0; 5 | if(nums.size() < 2) { 6 | return res; 7 | } 8 | priority_queue, greater> pq; 9 | for(auto &num : nums) { 10 | pq.push(num); 11 | } 12 | while(pq.size() >= 2) { 13 | int x = pq.top(); 14 | pq.pop(); 15 | int y = pq.top(); 16 | pq.pop(); 17 | if (x >= k) { 18 | break; 19 | } 20 | res++; 21 | // 2x + y >= k 22 | if ((k - y) / 2 <= x) { 23 | pq.push(k+1); 24 | } 25 | pq.push(x * 2LL + y); 26 | } 27 | return res; 28 | } 29 | }; -------------------------------------------------------------------------------- /programming/dynamic-programming/0064.最小路径和.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=64 lang=cpp 3 | * 4 | * [64] 最小路径和 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | int minPathSum(vector>& grid) { 11 | // dp方法,直接在原始的矩阵中进行 12 | if(grid.empty()) 13 | return 0; 14 | int m=grid.size(), n=grid[0].size(); 15 | // 初始化 16 | for(int i=1; i map(n+1, 0); // 所有的数都是质数 21 | for(int i=2; i 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | const int ChessBoard_Row = 13; 11 | const int ChessBoard_Col = 26; 12 | const int GridNuber = 9; 13 | const char Comp_Char = 'X'; 14 | const char Human_Char = 'O'; 15 | const char Blank_Char = ' '; 16 | 17 | class ChessBoard { 18 | public: 19 | ChessBoard(); 20 | 21 | bool isEmpty(int pos); 22 | bool isFull(); 23 | bool canWin(char c); 24 | bool immediateComWin(int& bestMove); 25 | bool immediateHumanWin(int& bestMove); 26 | void placeComp(int pos); 27 | void placeHuman(int pos); 28 | void unPlace(int pos); 29 | void print(); 30 | private: 31 | vector boardInOneDimens; 32 | vector board; 33 | 34 | }; 35 | #endif // !CHESS_BOARD_H 36 | 37 | -------------------------------------------------------------------------------- /programming/greedy/763.划分字母区间.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=763 lang=cpp 3 | * 4 | * [763] 划分字母区间 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | vector partitionLabels(string S) { 11 | //用end 和 start来划分现在的一个区间 12 | int map[26], length = S.size(), end = 0, start = 0; 13 | vector ans; 14 | 15 | //记录字符串中每个字母最后出现的位置 16 | for(int i = 0;i < length;i++){ 17 | map[S[i]-'a'] = i; 18 | } 19 | 20 | //遍历字符串 21 | for(int i = 0;i < length;i++) { 22 | end = max(end, map[S[i]-'a']); //贪心策略:每次刷新到最小的但是要全部包含字母的位置 23 | if(i == end) { //如果指针i找到了end的话,就代表这个区间已经搜索完毕 24 | ans.push_back(end-start+1); 25 | start = end + 1; 26 | } 27 | } 28 | return ans; 29 | } 30 | }; 31 | // @lc code=end 32 | 33 | -------------------------------------------------------------------------------- /programming/hash-table/205.同构字符串.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=205 lang=cpp 3 | * 4 | * [205] 同构字符串 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | bool isIsomorphic(string s, string t) { 11 | unordered_map map; 12 | for (int i=0;i 9 | class Stack 10 | { 11 | public: 12 | Stack() { top = -1; } 13 | bool Empty() { return top == -1; } 14 | void Push(T x); 15 | void Pop(); 16 | T GetTop(); 17 | int Size(); 18 | private: 19 | T data[stackSize]; 20 | int top; 21 | }; 22 | template 23 | void Stack::Push(T x) 24 | { 25 | if (top >= stackSize - 1) 26 | throw "out of range"; 27 | top++; 28 | data[top] = x; 29 | } 30 | template 31 | void Stack::Pop() { 32 | T temp = data[top]; 33 | top--; 34 | } 35 | template 36 | T Stack::GetTop() { 37 | if (top <= -1) 38 | throw "the stack is empty"; 39 | return data[top]; 40 | } 41 | template 42 | int Stack::Size() { 43 | return top+1; 44 | } -------------------------------------------------------------------------------- /programming/1160.拼写单词.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=1160 lang=cpp 3 | * 4 | * [1160] 拼写单词 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | int countCharacters(vector& words, string chars) { 11 | unordered_map chars_cnt; 12 | for (char c : chars) 13 | ++chars_cnt[c]; 14 | int ans = 0; 15 | for (string word : words) { 16 | unordered_map word_cnt; 17 | for (char c : word) 18 | ++word_cnt[c]; 19 | bool is_ans = true; 20 | for (char c : word) 21 | if (chars_cnt[c] < word_cnt[c]) { 22 | is_ans = false; 23 | break; 24 | } 25 | if (is_ans) 26 | ans += word.size(); 27 | } 28 | return ans; 29 | } 30 | }; 31 | // @lc code=end 32 | 33 | -------------------------------------------------------------------------------- /programming/greedy/435.无重叠区间.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=435 lang=cpp 3 | * 4 | * [435] 无重叠区间 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | int eraseOverlapIntervals(vector>& intervals) { 11 | // 贪心算法,对尾结点进行排序,尽量选择尾结点小的,给后面流出空间 12 | int size = intervals.size(); 13 | if(size <= 1) return 0; 14 | sort(intervals.begin(), intervals.end(), [](const vector& a, const vector& b) { 15 | return a[1] < b[1]; 16 | }); 17 | int res = 0, tail = intervals[0][1]; 18 | for(int i=1; i < size; i++) { 19 | // 当前起点小于上一个尾点,则删除这个区间 20 | if(intervals[i][0] < tail) { 21 | res++; 22 | } else { // 起点大于前一个尾点,更新尾点 23 | tail = intervals[i][1]; 24 | } 25 | } 26 | return res; 27 | } 28 | }; 29 | // @lc code=end 30 | 31 | -------------------------------------------------------------------------------- /programming/greedy/452.用最少数量的箭引爆气球.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=452 lang=cpp 3 | * 4 | * [452] 用最少数量的箭引爆气球 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | int findMinArrowShots(vector>& points) { 11 | if(points.empty() || points[0].empty()) { 12 | return 0; 13 | } 14 | // 贪心算法,按区间末尾进行升序排列 15 | sort(points.begin(), points.end(), [](const vector& a, const vector& b) { 16 | return a[1] < b[1]; 17 | }); 18 | int size = points.size(); 19 | int res = 1, tail = points[0][1]; 20 | for(int i=1; i tail) { 23 | res++; 24 | tail = points[i][1]; 25 | } 26 | } 27 | return res; 28 | } 29 | }; 30 | // @lc code=end 31 | 32 | -------------------------------------------------------------------------------- /programming/tree/binary_tree_deep.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | struct TreeNode { 8 | int val; 9 | TreeNode *left; 10 | TreeNode *right; 11 | TreeNode(int x) : val(x), left(NULL), right(NULL) {} 12 | }; 13 | 14 | int depth(TreeNode* root) { 15 | return root ? max(depth(root->left), depth(root->right)) + 1 : 0; 16 | } 17 | 18 | int main() { 19 | /* 20 | * 1 21 | * / \ 22 | * 2 3 23 | * / 24 | * 4 25 | */ 26 | TreeNode* p1 = new TreeNode(1); 27 | TreeNode* p2 = new TreeNode(2); 28 | TreeNode* p3 = new TreeNode(3); 29 | TreeNode* p4 = new TreeNode(4); 30 | p1->left = p2;p1->right=p3;p3->left=p4; 31 | 32 | int res = depth(p1); 33 | cout << res << endl; 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /programming/328.奇偶链表.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=328 lang=cpp 3 | * 4 | * [328] 奇偶链表 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for singly-linked list. 10 | * struct ListNode { 11 | * int val; 12 | * ListNode *next; 13 | * ListNode(int x) : val(x), next(NULL) {} 14 | * }; 15 | */ 16 | class Solution { 17 | public: 18 | ListNode* oddEvenList(ListNode* head) { 19 | if(!head || !head->next) return head; 20 | ListNode* slow = head, *fast = head->next; 21 | ListNode* l1 = slow, *l2 = fast; 22 | while(fast && fast->next) { 23 | slow->next = fast->next; 24 | slow = slow->next; 25 | if(slow) { 26 | fast->next = slow->next; 27 | fast = fast->next; 28 | } 29 | } 30 | slow->next = l2; 31 | return l1; 32 | } 33 | }; 34 | // @lc code=end 35 | 36 | -------------------------------------------------------------------------------- /programming/binary-search/162.寻找峰值.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=162 lang=cpp 3 | * 4 | * [162] 寻找峰值 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | int findPeakElement(vector& nums) { 11 | // 二分搜索,只需要比较mid和mid+1即可 12 | int l = 0, r = nums.size() - 1; 13 | while (l < r) { 14 | int mid = (l + r) / 2; 15 | if (nums[mid] > nums[mid + 1]) 16 | r = mid; 17 | else 18 | l = mid + 1; 19 | } 20 | return l; 21 | } 22 | }; 23 | /* 24 | public class Solution { 25 | public int findPeakElement(int[] nums) { 26 | for (int i = 0; i < nums.length - 1; i++) { 27 | // 只需要比较当前和后一个元素即可 28 | if (nums[i] > nums[i + 1]) 29 | return i; 30 | } 31 | return nums.length - 1; 32 | } 33 | } 34 | */ 35 | // @lc code=end 36 | 37 | -------------------------------------------------------------------------------- /programming/linked_list/24.两两交换链表中的节点.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=24 lang=cpp 3 | * 4 | * [24] 两两交换链表中的节点 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for singly-linked list. 10 | * struct ListNode { 11 | * int val; 12 | * ListNode *next; 13 | * ListNode(int x) : val(x), next(NULL) {} 14 | * }; 15 | */ 16 | class Solution { 17 | public: 18 | ListNode* swapPairs(ListNode* head) { 19 | if(!head) return nullptr; 20 | ListNode preHead(0), *pre = &preHead, *cur = head; 21 | pre->next = head; 22 | while(cur && cur->next) { 23 | ListNode* nxt = cur->next; 24 | cur->next = nxt->next; 25 | nxt->next = cur; 26 | pre->next = nxt; 27 | //更新pre和cur的位置 28 | pre = cur; 29 | cur = cur->next; 30 | } 31 | return preHead.next; 32 | } 33 | }; 34 | // @lc code=end 35 | 36 | -------------------------------------------------------------------------------- /programming/tree/1457.二叉树中的伪回文路径.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | // 判断是不是回文,奇数的个数即可 4 | int res = 0; 5 | unordered_map map; 6 | void dfs(TreeNode* root, int odd_num) { 7 | if(!root) return; 8 | 9 | // 修改状态 10 | map[root->val]++; 11 | if(map[root->val] % 2 == 1) odd_num++; 12 | else odd_num--; 13 | 14 | // 叶子节点判断 15 | if(!root->left && !root->right && odd_num <= 1) { 16 | res++; 17 | } 18 | 19 | // 递归子节点 20 | dfs(root->left, odd_num); 21 | dfs(root->right, odd_num); 22 | 23 | // 回溯状态 24 | if(map[root->val] % 2 == 1) odd_num--; // 先调整odd_num 25 | else odd_num++; 26 | map[root->val]--; // 再恢复map 27 | } 28 | int pseudoPalindromicPaths (TreeNode* root) { 29 | dfs(root, 0); 30 | return res; 31 | } 32 | }; -------------------------------------------------------------------------------- /programming/backtrack/87.扰乱字符串.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=87 lang=cpp 3 | * 4 | * [87] 扰乱字符串 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | bool isScramble(string s1, string s2) { 11 | if (s1 == s2) return true; 12 | string ss1 = s1, ss2 = s2; 13 | sort(ss1.begin(), ss1.end()), sort(ss2.begin(), ss2.end()); 14 | if (ss1 != ss2) return false; 15 | for (int i = 1; i < s1.size(); i ++ ) 16 | { 17 | if (isScramble(s1.substr(0, i), s2.substr(0, i)) 18 | && isScramble(s1.substr(i), s2.substr(i))) 19 | return true; 20 | if (isScramble(s1.substr(0, i), s2.substr(s2.size() - i)) 21 | && isScramble(s1.substr(i), s2.substr(0, s2.size() - i))) 22 | return true; 23 | } 24 | return false; 25 | } 26 | }; 27 | 28 | // @lc code=end 29 | 30 | -------------------------------------------------------------------------------- /programming/array/3.数组中重复的数字.md: -------------------------------------------------------------------------------- 1 | 2 | ## [数组中重复的数字](https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof/) 3 | 4 | 在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。 5 | 6 | 7 | 方法1:hash表: 8 | 9 | ``` 10 | int findRepeatNumber(vector& nums) { 11 | unordered_map hash; 12 | for(auto &n:nums) { 13 | hash[n]++; 14 | if(hash[n] > 1) { 15 | return n; 16 | } 17 | } 18 | return -1; 19 | } 20 | ``` 21 | 22 | 方法2:桶排序 23 | 因为数字都在0-n-1之间,很容易进行桶排序。 24 | 25 | ``` 26 | int findRepeatNumber(vector& nums) { 27 | for(int i=0; inext = head; 21 | for(int i=0; inext; 23 | } 24 | ListNode* cur = pre->next; 25 | for(int i=0; inext; 27 | cur->next = nxt->next; 28 | nxt->next = pre->next; 29 | pre->next = nxt; 30 | } 31 | return preHead.next; 32 | } 33 | }; 34 | // @lc code=end 35 | 36 | -------------------------------------------------------------------------------- /programming/dynamic-programming/2266.cpp: -------------------------------------------------------------------------------- 1 | const int MOD = 1'000'000'007; 2 | const int MX = 100'001; 3 | 4 | long long f[MX], g[MX]; 5 | 6 | int init = []() { 7 | f[0] = g[0] = 1; 8 | f[1] = g[1] = 1; 9 | f[2] = g[2] = 2; 10 | f[3] = g[3] = 4; 11 | for (int i = 4; i < MX; ++i) { 12 | f[i] = (f[i - 1] + f[i - 2] + f[i - 3]) % MOD; 13 | g[i] = (g[i - 1] + g[i - 2] + g[i - 3] + g[i - 4]) % MOD; 14 | } 15 | return 0; 16 | }(); 17 | 18 | class Solution { 19 | public: 20 | int countTexts(string s) { 21 | long long ans = 1; 22 | int cnt = 0; 23 | for (int i = 0; i < s.length(); i++) { 24 | char c = s[i]; 25 | cnt++; 26 | if (i == s.length() - 1 || c != s[i + 1]) { 27 | ans = ans * (c != '7' && c != '9' ? f[cnt] : g[cnt]) % MOD; 28 | cnt = 0; 29 | } 30 | } 31 | return ans; 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /programming/dynamic-programming/2369.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | // dp[i] 0-i是不是有效的划分 4 | // nums[i] == nums[i-1] && dp[i-2] 5 | // nums[i] == nums[i-1] + 1 && nums[i] == nums[i-2] + 2 && dp[i-3] 6 | // nums[i] == nums[i-1] == nums[i-2] + 1 && dp[i-3] 7 | 8 | bool valid(int num1, int num2, int num3) { 9 | return (num1 == num2 && num2 == num3) || 10 | (num1 + 1== num2 && num2 +1 == num3); 11 | } 12 | bool validPartition(vector& nums) { 13 | int n = nums.size(); 14 | vector dp(n+1, 0); 15 | dp[0] = true; 16 | for(int i=1; i <=n ; i++) { 17 | if(i >= 2) { 18 | dp[i] = dp[i-2] && nums[i-2] == nums[i-1]; 19 | } 20 | if(i >= 3) { 21 | dp[i] = dp[i] || (dp[i-3] && valid(nums[i-3], nums[i-2], nums[i-1])); 22 | } 23 | } 24 | return dp[n]; 25 | 26 | } 27 | }; -------------------------------------------------------------------------------- /programming/dynamic-programming/494.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | // 设正数和p , 负数和q 4 | // p + q = s 5 | // p - q = target 6 | // p = (s + target) / 2 7 | // q = (s - target) / 2 8 | // target > 0 q小, target < 0 p小 9 | // m = (s-abs(target)) / 2 10 | // dp[i][j] : 表示前i个数字中, 和为j的方案数 11 | // dp[i][j] = dp[i-1][j] + dp[i-1][j-nums[i]] 12 | // dp[j] = dp[j] + dp[j-nums[i]] 13 | // 01背包组合问题 14 | int findTargetSumWays(vector& nums, int target) { 15 | int s = reduce(nums.begin(), nums.end(), 0) - abs(target); 16 | if(s < 0 || s % 2 == 1) return 0; 17 | int m = s / 2; 18 | vector dp(m+1, 0); 19 | dp[0] = 1; // 前0的数字, 合为0的方案数是1 20 | // 遍历nums 21 | for(auto num : nums) { 22 | for(int i = m; i >= num; i--) { 23 | dp[i] = dp[i] + dp[i-num]; 24 | } 25 | } 26 | return dp[m]; 27 | } 28 | }; -------------------------------------------------------------------------------- /programming/tree/572.另一个树的子树.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=572 lang=cpp 3 | * 4 | * [572] 另一个树的子树 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for a binary tree node. 10 | * struct TreeNode { 11 | * int val; 12 | * TreeNode *left; 13 | * TreeNode *right; 14 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 15 | * }; 16 | */ 17 | class Solution { 18 | public: 19 | bool isSameTree(TreeNode* s, TreeNode* t) { 20 | if(!s || !t) return s == t; 21 | return s->val == t->val && isSameTree(s->left, t->left) && 22 | isSameTree(s->right, t->right); 23 | } 24 | 25 | bool dfs(TreeNode* s, TreeNode* t) { 26 | if (!s) 27 | return false; 28 | return isSameTree(s, t) || dfs(s->left, t) || dfs(s->right, t); 29 | } 30 | 31 | bool isSubtree(TreeNode* s, TreeNode* t) { 32 | return dfs(s, t); 33 | } 34 | }; 35 | // @lc code=end 36 | 37 | -------------------------------------------------------------------------------- /programming/bit-manipulation/位运算总结.md: -------------------------------------------------------------------------------- 1 | # 位运算总结 2 | 3 | 1. n & (n-1) : 可以直接去除n的最后一个1 4 | 示例题目: 191 计算位1的个数 5 | 2. n & ~(1 << k): 置第i位为0 6 | 7 | 3. 提取奇数和偶数位 8 | 奇数位全1 -> 0101.... 表示为 0x55555555 9 | 偶数位全1 -> 1010.... 表示为 0xaaaaaaaa 10 | 11 | 12 | 4. 判断奇偶: 13 | 奇:(x & 1) == 1  14 | 偶:(x & 1) == 0  15 | https://leetcode.cn/problems/exchange-lcci/description/?envType=study-plan-v2&envId=cracking-the-coding-interview 16 | 17 | 1. 去除最后一位 1:x & (x - 1) 18 | 19 | 2. 得到最后一位 1:x & -x 20 | 21 | 3. 判断 2 的幂次:x & (x - 1) == 0 22 | 23 | 4. 交换两个数:a ^= b; b ^= a; a ^= b; 24 | 25 | 5. 将最左边的 n 位清零:x & (~0 << n) 26 | 27 | 6. 获取 x 的第 n 位值(0 或 1):(x >> n) & 1 28 | 29 | 7. 获取 x 的第 n 位的幂值:x & (1 << n) 30 | 31 | 仅将第 n 位置为 1:x | (1 << n) 32 | 33 | 仅将第 n 位置为 0:x & (~(1 << n)) 34 | 35 | 将 x 最高位至第 n 位(含)清零:x & ((1 << n) - 1) 36 | 37 | 将第 n 位至第 0 位(含)清零:x & (~((1 << (n + 1)) - 1)) 38 | 39 | 取反第 n 位:x ^ (1 << n) 40 | 41 | 异或满足交换律、结合律:a ^ b ^ a = b ^ (a ^ a) = b ^ 0 = b 42 | 43 | -------------------------------------------------------------------------------- /programming/linked_list/61.旋转链表.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=61 lang=cpp 3 | * 4 | * [61] 旋转链表 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for singly-linked list. 10 | * struct ListNode { 11 | * int val; 12 | * ListNode *next; 13 | * ListNode(int x) : val(x), next(NULL) {} 14 | * }; 15 | */ 16 | class Solution { 17 | public: 18 | ListNode* rotateRight(ListNode* head, int k) { 19 | if(!head || k<=0) { 20 | return head; 21 | } 22 | ListNode *p = head; 23 | int len=1; 24 | //求链表长度,同时可以拿到最后一个节点 25 | while(p->next) { 26 | p = p->next; 27 | len++; 28 | } 29 | p->next = head; //链接收尾 30 | k = len - k%len; 31 | for(int i=0; inext; 33 | } 34 | head = p->next; 35 | p->next = nullptr; 36 | return head; 37 | } 38 | }; 39 | // @lc code=end 40 | 41 | -------------------------------------------------------------------------------- /programming/linked_list/0061.旋转链表.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=61 lang=cpp 3 | * 4 | * [61] 旋转链表 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for singly-linked list. 10 | * struct ListNode { 11 | * int val; 12 | * ListNode *next; 13 | * ListNode(int x) : val(x), next(NULL) {} 14 | * }; 15 | */ 16 | class Solution { 17 | public: 18 | ListNode* rotateRight(ListNode* head, int k) { 19 | if(!head || k<=0) { 20 | return head; 21 | } 22 | ListNode *p = head; 23 | int len=1; 24 | //求链表长度,同时可以拿到最后一个节点 25 | while(p->next) { 26 | p = p->next; 27 | len++; 28 | } 29 | p->next = head; //链接收尾 30 | k = len - k%len; 31 | for(int i=0; inext; 33 | } 34 | head = p->next; 35 | p->next = nullptr; 36 | return head; 37 | } 38 | }; 39 | // @lc code=end 40 | 41 | -------------------------------------------------------------------------------- /programming/tree/balance_tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | struct TreeNode { 8 | int val; 9 | TreeNode *left; 10 | TreeNode *right; 11 | TreeNode(int x) : val(x), left(NULL), right(NULL) {} 12 | }; 13 | 14 | int depth(TreeNode* root) { 15 | return root ? max(depth(root->left), depth(root->right)) + 1 : 0; 16 | } 17 | 18 | bool balance(TreeNode* root) { 19 | } 20 | 21 | int main() { 22 | /* 23 | * 1 24 | * / \ 25 | * 2 3 26 | * / 27 | * 4 28 | */ 29 | TreeNode* p1 = new TreeNode(1); 30 | TreeNode* p2 = new TreeNode(2); 31 | TreeNode* p3 = new TreeNode(3); 32 | TreeNode* p4 = new TreeNode(4); 33 | p1->left = p2;p1->right=p3;p3->left=p4; 34 | 35 | cout << "is balance tree " << balance(p1) << endl; 36 | 37 | 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /programming/string/68.文本左右对齐.py: -------------------------------------------------------------------------------- 1 | # 2 | # @lc app=leetcode.cn id=68 lang=python 3 | # 4 | # [68] 文本左右对齐 5 | # 6 | 7 | # @lc code=start 8 | class Solution(object): 9 | # https://leetcode.com/problems/text-justification/discuss/24891/Concise-python-solution-10-lines. 10 | def fullJustify(self, words, maxWidth): 11 | """ 12 | :type words: List[str] 13 | :type maxWidth: int 14 | :rtype: List[str] 15 | """ 16 | res, cur, num_of_letters = [], [], 0 17 | for w in words: 18 | if num_of_letters + len(w) + len(cur) > maxWidth: 19 | for i in range(maxWidth - num_of_letters): 20 | cur[i%(len(cur)-1 or 1)] += ' ' 21 | res.append(''.join(cur)) 22 | cur, num_of_letters = [], 0 23 | cur += [w] 24 | num_of_letters += len(w) 25 | return res + [' '.join(cur).ljust(maxWidth)] 26 | 27 | # @lc code=end 28 | 29 | -------------------------------------------------------------------------------- /programming/backtrack/2689.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | // dfs(81, 0, 0, 9) 4 | bool dfs(string &s, int pos, int tot, int target) { 5 | // 终止条件,判断 6 | if (pos == s.size()) { 7 | return tot == target; 8 | } 9 | 10 | // 分割子串并计算sum, 和累计前面的和 11 | int sum = 0; 12 | for (int i = pos; i < s.size(); i++) { 13 | sum = sum * 10 + s[i] - '0'; 14 | if (sum + tot > target) { 15 | break; 16 | } 17 | if (dfs(s, i + 1, sum + tot, target)) { 18 | return true; 19 | } 20 | } 21 | return false; 22 | } 23 | 24 | int punishmentNumber(int n) { 25 | int res = 0; 26 | for (int i = 1; i <= n; i++) { 27 | string s = to_string(i * i); 28 | if (dfs(s, 0, 0, i)) { 29 | res += i * i; 30 | } 31 | } 32 | return res; 33 | } 34 | }; -------------------------------------------------------------------------------- /DataStructure/Queue/Queue.h: -------------------------------------------------------------------------------- 1 | //Author : yqtao 2 | //date : 2016.09.09 3 | //Email : yqtao@whu.edu.cn 4 | /* 5 | Implement my own queue,it is a sequence queue 6 | */ 7 | const int maxSize = 100; 8 | template class Queue 9 | { 10 | private: 11 | T data[maxSize]; 12 | int front, rear; //the queue point of head ,end 13 | public: 14 | Queue() { front = rear = -1; } 15 | bool empty() { return front == rear; } 16 | void enQueue(T x); 17 | void deQueue(); 18 | T getFront(); //get the front of queue 19 | }; 20 | template 21 | void Queue::enQueue(T x) { 22 | if (rear == maxSize - 1) 23 | throw "out of range"; 24 | rear++; 25 | data[rear] = x; 26 | } 27 | // 28 | template 29 | void Queue::deQueue() { 30 | if (front == rear) 31 | throw "the queue is empty"; 32 | front++; 33 | } 34 | // 35 | template 36 | T Queue::getFront() { 37 | if (rear == front) throw "the queue is empty"; 38 | return data[front+1]; 39 | } 40 | -------------------------------------------------------------------------------- /programming/math/0009.回文数.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=9 lang=cpp 3 | * 4 | * [9] 回文数 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | bool isPalindrome(int x) { 11 | if (x < 0 || x && x % 10 == 0) return false; 12 | int s = 0; 13 | while (s <= x) { 14 | s = s * 10 + x % 10; 15 | if (s == x || s == x / 10) return true; // 分别处理整数长度是奇数或者偶数的情况 16 | x /= 10; 17 | } 18 | return false; 19 | } 20 | }; 21 | 22 | /* 23 | bool isPalindrome(int x) { 24 | // 解法1: long long int 25 | if (x < 0 || (x != 0 && x % 10 == 0)) { 26 | return false; 27 | } 28 | long long result = 0; //using long long it can not be overflow 29 | int temp = x; 30 | while (temp) //revere the num; 31 | { 32 | result = result * 10 + temp % 10; 33 | temp /= 10; 34 | if (result>INT_MAX) //if overflow ,it must be return false 35 | return false; 36 | } 37 | return x ==result; 38 | } 39 | */ 40 | // @lc code=end -------------------------------------------------------------------------------- /programming/math/大数运算.md: -------------------------------------------------------------------------------- 1 | - [大数运算](#大数运算) 2 | - [1.字符串相加](#1字符串相加) 3 | # 大数运算 4 | 5 | 大数运算包含了字符串、链表模拟加减乘除的运算过程 6 | 7 | ## [1.字符串相加](https://leetcode-cn.com/problems/add-strings/) 8 | 9 | 模拟字符串的加法,此题虽然简单,但是bugfree有难度,一定要熟练掌握。 10 | 11 | ``` 12 | class Solution { 13 | public: 14 | string addStrings(string num1, string num2) { 15 | string res = ""; 16 | int m = num1.size(), n = num2.size(); 17 | int i = m -1, j = n - 1, carry = 0, sum = 0; 18 | while(i >= 0 || j >= 0 || carry) { 19 | int a = i >= 0 ? num1[i] - '0' : 0; 20 | int b = j >= 0 ? num2[j] - '0' : 0; 21 | sum = a + b + carry; 22 | res += (sum % 10) + '0'; 23 | //cout << i << " " << j << endl; 24 | //cout << a << " " << b << " " << sum << endl; 25 | carry = sum / 10; 26 | i = i - 1; 27 | j = j - 1; 28 | } 29 | reverse(res.begin(), res.end()); 30 | return res; 31 | } 32 | }; 33 | ``` -------------------------------------------------------------------------------- /programming/slide-window/1456. 定长子串中元音的最大数目.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int maxVowels(string s, int k) { 4 | int size = s.size(); 5 | if (size < k) return 0; 6 | int res = 0, window_res = 0; 7 | // 初始化满足条件的窗口 8 | for(int i=0; i < k - 1; i++) { 9 | char c = s[i]; 10 | if(c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') { 11 | window_res += 1; 12 | } 13 | } 14 | for(int i=k-1; i < size; i++) { 15 | // 插入 16 | char c = s[i]; 17 | if(c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') { 18 | window_res += 1; 19 | } 20 | // 更新 21 | res = max(res ,window_res); 22 | // 删除 23 | c = s[i-k+1]; 24 | if(c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') { 25 | window_res -= 1; 26 | } 27 | } 28 | return res; 29 | } 30 | }; -------------------------------------------------------------------------------- /programming/string/165.比较版本号.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=165 lang=cpp 3 | * 4 | * [165] 比较版本号 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | int compareVersion(string version1, string version2) { 11 | int i = 0; 12 | int j = 0; 13 | int n1 = version1.size(); 14 | int n2 = version2.size(); 15 | int num1 = 0; 16 | int num2 = 0; 17 | while(inum2) return 1; 27 | else if(num1 < num2) return -1; 28 | num1 = 0; 29 | num2 = 0; 30 | i++; 31 | j++; 32 | } 33 | return 0; 34 | } 35 | }; 36 | // @lc code=end 37 | 38 | -------------------------------------------------------------------------------- /programming/data-structure/238-除自身以外其他元素乘积.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | // 前缀积和后缀积 4 | vector productExceptSelf(vector& nums) { 5 | int length = nums.size(); 6 | 7 | // L 和 R 分别表示左右两侧的乘积列表 8 | vector L(length, 0), R(length, 0); 9 | 10 | vector answer(length); 11 | 12 | // L[i] 为索引 i 左侧所有元素的乘积 13 | // 对于索引为 '0' 的元素,因为左侧没有元素,所以 L[0] = 1 14 | L[0] = 1; 15 | for (int i = 1; i < length; i++) { 16 | L[i] = nums[i - 1] * L[i - 1]; 17 | } 18 | 19 | // R[i] 为索引 i 右侧所有元素的乘积 20 | // 对于索引为 'length-1' 的元素,因为右侧没有元素,所以 R[length-1] = 1 21 | R[length - 1] = 1; 22 | for (int i = length - 2; i >= 0; i--) { 23 | R[i] = nums[i + 1] * R[i + 1]; 24 | } 25 | 26 | // 对于索引 i,除 nums[i] 之外其余各元素的乘积就是左侧所有元素的乘积乘以右侧所有元素的乘积 27 | for (int i = 0; i < length; i++) { 28 | answer[i] = L[i] * R[i]; 29 | } 30 | 31 | return answer; 32 | } 33 | }; -------------------------------------------------------------------------------- /programming/dynamic-programming/115.不同的子序列.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=115 lang=cpp 3 | * 4 | * [115] 不同的子序列 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | int numDistinct(string s, string t) { 11 | int n = s.size(), m = t.size(); 12 | if (m == 0) return 1; 13 | if (n == 0) return 0; 14 | vector> dp(n + 1, vector(m + 1, 0)); 15 | // dp[i][0] = 1, dp[0][j] = 0; 16 | for (int i = 0; i <= n; i++) dp[i][0] = 1; 17 | // 状态转移 18 | // s[i-1] == t[j-1]时,dp[i][j] = dp[i-1][j-1] + dp[i-1][j] dp[i-1][j-1]表示保留s[i-1]的情况,dp[i-1][j]表示移除s[i-1]的情况 19 | // s[i-1] != t[j-1]时,dp[i][j] = dp[i-1][j] 20 | for (int i = 1; i <= n; i++) { 21 | for (int j = 1; j <= m; j++) { 22 | dp[i][j] = dp[i - 1][j]; 23 | if (s[i - 1] == t[j - 1]) dp[i][j] += dp[i - 1][j - 1]; 24 | } 25 | } 26 | 27 | return dp[n][m]; 28 | } 29 | }; 30 | // @lc code=end 31 | 32 | -------------------------------------------------------------------------------- /programming/tree/230.二叉搜索树第k小的数.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 | 13 | // 同98题,验证是不是二叉搜索树 14 | class Solution { 15 | public: 16 | int kthSmallest(TreeNode* root, int k) { 17 | // 中序遍历有序 18 | stack st; 19 | // 注意了,必须是LLONG_MIN 20 | int index = 0; 21 | while(!st.empty() || root) { 22 | while(root) { 23 | st.push(root); 24 | root = root->left; 25 | } 26 | root = st.top(); 27 | st.pop(); 28 | index++; 29 | if(index == k) return root->val; 30 | root = root->right; 31 | } 32 | return -1; 33 | } 34 | }; -------------------------------------------------------------------------------- /programming/dynamic-programming/132.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | // 统计状态0-i是不是回文 4 | // 如果dp[i]是回文直接返回0 5 | // 如果dp[i]不是回文,从j=1开始遍历,如果[j,i]是回文,可以进行切割,同时记录最小值 6 | int minCut(string s) { 7 | int n = s.size(); 8 | vector> st(n, vector(n, false)); 9 | 10 | for (int i = 0; i < n; i ++ ) 11 | for (int j = i; j >= 0; j -- ) 12 | if (i - j <= 1) { 13 | st[j][i] = s[j] == s[i]; 14 | } else { 15 | st[j][i] = s[j] == s[i] && st[j + 1][i - 1]; 16 | } 17 | 18 | vector f(n); 19 | for(int r=0;r postorderTraversal(TreeNode* root) { 20 | vector res; 21 | if(!root) return res; 22 | stack st; 23 | st.push(root); 24 | while(!st.empty()) { 25 | root = st.top(); 26 | st.pop(); 27 | res.push_back(root->val); 28 | 29 | if(root->left) { 30 | st.push(root->left); 31 | } 32 | if(root->right) { 33 | st.push(root->right); 34 | } 35 | } 36 | reverse(res.begin(), res.end()); 37 | return res; 38 | } 39 | }; 40 | // @lc code=end 41 | 42 | -------------------------------------------------------------------------------- /programming/dynamic-programming/198.打家劫舍.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | // int rob(vector& nums) { 4 | // // dp[i] = max(dp[i-1], dp[i-2] + nums[i]) dp[i]: i时最大的收获 5 | // if(nums.empty()) return 0; 6 | // int n = nums.size(); 7 | // vector dp(n+1, 0); 8 | // dp[1] = nums[0]; 9 | // for(int i=2; i <=n; i++) { 10 | // dp[i] = max(dp[i-1], dp[i-2] + nums[i-1]); 11 | // } 12 | // return dp[n]; 13 | // } 14 | 15 | // 空间优化 16 | int rob(vector& nums) { 17 | // dp[i] = max(dp[i-1], dp[i-2] + nums[i]) dp[i]: i时最大的收获 18 | if(nums.empty()) return 0; 19 | int n = nums.size(); 20 | //vector dp(n+1, 0); 21 | //dp[1] = nums[0]; 22 | int f1 = nums[0], f0 = 0; 23 | for(int i=2; i <=n; i++) { 24 | //dp[i] = max(dp[i-1], dp[i-2] + nums[i-1]); 25 | int x = max(f1, f0 + nums[i-1]); 26 | f0 = f1; 27 | f1 = x; 28 | } 29 | return f1; 30 | } 31 | }; -------------------------------------------------------------------------------- /programming/data-structure/239.滑动窗口最大值.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector maxSlidingWindow(vector& nums, int k) { 4 | // 不是优先队列,优先队列会改变顺序,单调递减的队列,则头就是最大的值 5 | // 使用deque双端队列,而不是queue 6 | vector res; 7 | int len = nums.size(); 8 | if(len < k) return res; 9 | deque deq; 10 | for(int i=0; i< len; i++) { 11 | // 队尾,队头的索引差值大于K了 12 | if(!deq.empty() && i-k+1 > deq.front()) { 13 | deq.pop_front(); 14 | } 15 | // 维护单调队列 16 | while(deq.size()>0 && nums[deq.back()] <= nums[i]) { 17 | deq.pop_back(); 18 | } 19 | // 加入,保持单调队列 20 | deq.push_back(i); 21 | 22 | // 队头元素为需要元素 23 | if(!deq.empty() && i-k+1 >= 0) { 24 | res.push_back(nums[deq.front()]); 25 | } 26 | } 27 | return res; 28 | 29 | 30 | 31 | } 32 | }; -------------------------------------------------------------------------------- /programming/dynamic-programming/97.交错字符串.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=97 lang=cpp 3 | * 4 | * [97] 交错字符串 5 | */ 6 | 7 | // @lc code=start 8 | // 尝试用回溯法去解决 9 | class Solution { 10 | public: 11 | bool isInterleave(string s1, string s2, string s3) { 12 | int n = s1.size(), m = s2.size(), k = s3.size(); 13 | if (k != n + m) return false; 14 | vector> f = 15 | vector>(n + 1, vector(m + 1)); 16 | f[0][0] = 1; 17 | for (int i = 1; i <= n; i ++ ) 18 | f[i][0] = f[i - 1][0] && s1[i - 1] == s3[i - 1]; 19 | for (int i = 1; i <= m; i ++ ) 20 | f[0][i] = f[0][i - 1] && s2[i - 1] == s3[i - 1]; 21 | for (int i = 1; i <= n; i ++ ) 22 | for (int j = 1; j <= m; j ++ ) { 23 | if (s1[i - 1] == s3[i + j - 1]) 24 | f[i][j] |= f[i - 1][j]; 25 | if (s2[j - 1] == s3[i + j - 1]) 26 | f[i][j] |= f[i][j - 1]; 27 | } 28 | return f[n][m]; 29 | } 30 | }; 31 | // @lc code=end 32 | 33 | -------------------------------------------------------------------------------- /programming/hash-table/219.存在重复元素.cpp: -------------------------------------------------------------------------------- 1 | // 滑动窗口 2 | 3 | class Solution { 4 | public: 5 | bool containsNearbyDuplicate(vector& nums, int k) { 6 | if(nums.size() <= 1) return false; 7 | unordered_set hash; 8 | for(int i=0; i k) { 10 | hash.erase(nums[i-k-1]); 11 | } 12 | if(hash.count(nums[i])) { 13 | return true; 14 | } 15 | hash.emplace(nums[i]); 16 | } 17 | return false; 18 | } 19 | }; 20 | 21 | // 哈希表 22 | class Solution { 23 | public: 24 | bool containsNearbyDuplicate(vector& nums, int k) { 25 | if(nums.size() <= 1) return false; 26 | unordered_map hash; 27 | for(int i=0; i < nums.size(); i++) { 28 | if(hash.find(nums[i]) != hash.end()) { 29 | if(i - hash[nums[i]] <= k) { 30 | return true; 31 | } 32 | } 33 | hash[nums[i]] = i; 34 | } 35 | return false; 36 | } 37 | }; -------------------------------------------------------------------------------- /programming/linked_list/82.删除排序链表中的重复元素-ii.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=82 lang=cpp 3 | * 4 | * [82] 删除排序链表中的重复元素 II 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for singly-linked list. 10 | * struct ListNode { 11 | * int val; 12 | * ListNode *next; 13 | * ListNode(int x) : val(x), next(NULL) {} 14 | * }; 15 | */ 16 | class Solution { 17 | public: 18 | ListNode* deleteDuplicates(ListNode* head) { 19 | ListNode preHead(0), *pre=&preHead, *cur=head; 20 | pre->next = cur; 21 | while(cur && cur->next) { 22 | ListNode* nxt=cur->next; 23 | // 不相等,直接操作 24 | if(cur->val != nxt->val) { 25 | pre = cur; 26 | cur = nxt; 27 | } else { 28 | // cur == nxt, 一直移动nxt, 直到不相等 29 | while(nxt && cur->val == nxt->val) 30 | nxt = nxt->next; 31 | cur = nxt; 32 | pre->next = cur; 33 | } 34 | } 35 | return preHead.next; 36 | } 37 | }; 38 | // @lc code=end 39 | 40 | -------------------------------------------------------------------------------- /programming/bit-manipulation/169.多数元素.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=169 lang=cpp 3 | * 4 | * [169] 多数元素 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | // 位运算的方法,同137题 11 | int majorityElement(vector& nums) { 12 | int m = nums.size(), res = 0; 13 | for(int bit=0; bit<32; bit++) { 14 | int count = 0; 15 | for(auto &n:nums) { 16 | // 统计1的个数 17 | count += (n >> bit) & 1; 18 | } 19 | // 如果当前1的个数超过了一半 20 | if(count > m/2) { 21 | res += 1<& nums) { 28 | int major, counts = 0, n = nums.size(); 29 | for (int i = 0; i < n; i++) { 30 | if (!counts) { 31 | major = nums[i]; 32 | counts = 1; 33 | } 34 | else counts += (nums[i] == major) ? 1 : -1; 35 | } 36 | return major; 37 | } 38 | }; 39 | // @lc code=end 40 | 41 | -------------------------------------------------------------------------------- /programming/tree/700.二叉搜索树中的搜索.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=700 lang=cpp 3 | * 4 | * [700] 二叉搜索树中的搜索 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for a binary tree node. 10 | * struct TreeNode { 11 | * int val; 12 | * TreeNode *left; 13 | * TreeNode *right; 14 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 15 | * }; 16 | */ 17 | class Solution { 18 | public: 19 | // 迭代,非常简单,找到值,相等的返回即可 20 | TreeNode* searchBST(TreeNode* root, int val) { 21 | while(root && root->val != val) { 22 | root = (root->val < val) ? root->right: root->left; 23 | } 24 | return root; 25 | } 26 | // 迭代 27 | // TreeNode* searchBST(TreeNode* root, int val) { 28 | // if(root == NULL) return NULL; 29 | // if(root->val == val) { 30 | // return root; 31 | // } else if(root->val > val) { 32 | // return searchBST(root->left, val); 33 | // } else { 34 | // return searchBST(root->right, val); 35 | // } 36 | // } 37 | }; 38 | // @lc code=end 39 | 40 | -------------------------------------------------------------------------------- /programming/dynamic-programming/91.解码方法.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=91 lang=cpp 3 | * 4 | * [91] 解码方法 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | // 1. s[i] = 0 , 如果s[i-1] = 1,2 dp[i]=dp[i-2], 否则为0 11 | // 2. s[i-1]=1|| s[i-1]=2 && 1<=s[i]<=6 dp[i] = dp[i-1] + dp[i-2] 12 | // 参考资料:https://leetcode-cn.com/problems/decode-ways/solution/c-wo-ren-wei-hen-jian-dan-zhi-guan-de-jie-fa-by-pr/ 13 | int numDecodings(string s) { 14 | if (s[0] == '0') return 0; 15 | int pre = 1, curr = 1;//dp[-1] = dp[0] = 1 16 | for (int i = 1; i < s.size(); i++) { 17 | int tmp = curr; 18 | if (s[i] == '0') { 19 | if (s[i - 1] == '1' || s[i - 1] == '2') { 20 | curr = pre; 21 | } 22 | else return 0; 23 | } 24 | else if (s[i - 1] == '1' || (s[i - 1] == '2' && s[i] >= '1' && s[i] <= '6')) 25 | curr = curr + pre; 26 | pre = tmp; 27 | } 28 | return curr; 29 | } 30 | }; 31 | // @lc code=end 32 | 33 | -------------------------------------------------------------------------------- /programming/linked_list/203.移除链表元素.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=203 lang=cpp 3 | * 4 | * [203] 移除链表元素 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for singly-linked list. 10 | * struct ListNode { 11 | * int val; 12 | * ListNode *next; 13 | * ListNode(int x) : val(x), next(NULL) {} 14 | * }; 15 | */ 16 | /** 17 | * Definition for singly-linked list. 18 | * struct ListNode { 19 | * int val; 20 | * ListNode *next; 21 | * ListNode(int x) : val(x), next(NULL) {} 22 | * }; 23 | */ 24 | class Solution { 25 | public: 26 | ListNode* removeElements(ListNode* head, int val) { 27 | if(!head) return head; 28 | ListNode preHead(0), *pre = &preHead; 29 | pre->next = head; 30 | while(head) { 31 | if(head->val == val) { 32 | pre->next = head->next; 33 | head = head->next; 34 | } else { 35 | head = head->next; 36 | pre = pre->next; 37 | } 38 | } 39 | return preHead.next; 40 | } 41 | }; 42 | // @lc code=end 43 | 44 | -------------------------------------------------------------------------------- /programming/tree/99.恢复二叉搜索树.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=99 lang=cpp 3 | * 4 | * [99] 恢复二叉搜索树 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for a binary tree node. 10 | * struct TreeNode { 11 | * int val; 12 | * TreeNode *left; 13 | * TreeNode *right; 14 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 15 | * }; 16 | */ 17 | class Solution { 18 | public: 19 | TreeNode *pre = new TreeNode(INT_MIN); 20 | TreeNode *first = nullptr, *second = nullptr; 21 | 22 | void dfs(TreeNode* root) { 23 | // 中序遍历 24 | if(!root) { 25 | return; 26 | } 27 | dfs(root->left); 28 | 29 | if(first == nullptr && pre->val > root->val) { 30 | first = pre; 31 | } 32 | if(first && pre->val > root->val) { 33 | second = root; 34 | } 35 | 36 | pre = root; 37 | 38 | dfs(root->right); 39 | } 40 | 41 | void recoverTree(TreeNode* root) { 42 | dfs(root); 43 | swap(first->val, second->val); 44 | } 45 | }; 46 | // @lc code=end 47 | 48 | -------------------------------------------------------------------------------- /programming/bit-manipulation/0461.汉明距离.cpp: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* 0461.汉明距离.cpp :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: taoyanqi +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2025/09/24 11:13:53 by taoyanqi #+# #+# */ 9 | /* Updated: 2025/09/24 11:13:54 by taoyanqi ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | class Solution { 14 | public: 15 | int hammingDistance(int x, int y) { 16 | return __builtin_popcount(x ^ y); 17 | 18 | } 19 | }; -------------------------------------------------------------------------------- /programming/greedy/135.分发糖果.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=135 lang=cpp 3 | * 4 | * [135] 分发糖果 5 | */ 6 | 7 | // @lc code=start 8 | /* 9 | * @lc app=leetcode.cn id=135 lang=cpp 10 | * 11 | * [135] 分发糖果 12 | */ 13 | 14 | // @lc code=start 15 | class Solution { 16 | public: 17 | // 1 0 2 18 | // 1. 初始化 1 1 1 19 | // 2. 从左到右遍历 1 1 2 20 | // 3. 从右到左遍历 2 1 2 21 | int candy(vector& ratings) { 22 | int size = ratings.size(); 23 | if(size < 2) { 24 | return size; 25 | } 26 | vector v(size, 1); 27 | // 从左到右遍历,比前一个大值,值加1 28 | for(int i=1; i < size; i++) { 29 | if(ratings[i] > ratings[i-1]) { 30 | v[i] = v[i-1] + 1; 31 | } 32 | } 33 | // 从右到左, 比后一个大是,如果本身值小则加1 34 | for(int i=size-2; i>=0; i--) { 35 | if(ratings[i] > ratings[i+1] && v[i] <= v[i+1]) { 36 | v[i] = v[i+1] + 1; 37 | } 38 | } 39 | return accumulate(v.begin(), v.end(), 0); 40 | } 41 | }; 42 | // @lc code=end 43 | 44 | 45 | // @lc code=end 46 | 47 | -------------------------------------------------------------------------------- /programming/data-structure/滑动窗口.cpp: -------------------------------------------------------------------------------- 1 | 2 | // 题目链接: https://www.acwing.com/problem/content/156/ 3 | #include 4 | 5 | using namespace std; 6 | 7 | const int N=1e6+10; 8 | int a[N], q[N]; 9 | int n,k; 10 | 11 | int main() { 12 | cin >> n >> k; 13 | for(int i =0; i q[hh]) { 20 | hh++; //删除队头 21 | } 22 | // 将比当前元素大的数出队,保持将其插入后是单调递增的队列 23 | while(hh <= tt && a[q[tt]] >= a[i]) { 24 | tt--; 25 | } 26 | q[++tt] = i; // 加入队尾 27 | if (i >= k - 1) printf("%d ", a[q[hh]]); 28 | } 29 | 30 | puts(""); 31 | 32 | hh = 0, tt = -1; 33 | for (int i = 0; i < n; i ++ ) { 34 | if (hh <= tt && i - k + 1 > q[hh]) hh ++ ; 35 | 36 | while (hh <= tt && a[q[tt]] <= a[i]) tt -- ; 37 | q[ ++ tt] = i; 38 | 39 | if (i >= k - 1) printf("%d ", a[q[hh]]); 40 | } 41 | 42 | puts(""); 43 | 44 | return 0; 45 | } -------------------------------------------------------------------------------- /programming/binary-search/300.最长上升子序列.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=300 lang=cpp 3 | * 4 | * [300] 最长上升子序列 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | // 贪心 + 二分查找, 特别注意这个二分查找的写法啊,即找到其插入的位置 11 | int lengthOfLIS(vector& nums) { 12 | int size = nums.size(); 13 | if(size <= 0) { 14 | return 0; 15 | } 16 | int res = 0; 17 | vector v; 18 | v.push_back(nums[0]); 19 | for(int i=1; i < size; i++) { 20 | if(nums[i] > v.back()) { 21 | v.push_back(nums[i]); 22 | } else { 23 | int left = 0, right = v.size()-1; 24 | while(left <= right) { 25 | int mid = (left + right) / 2; 26 | if(v[mid] >= nums[i]) { 27 | right = mid - 1; 28 | } else { 29 | left = mid + 1; 30 | } 31 | } 32 | v[left] = nums[i]; 33 | } 34 | } 35 | return v.size(); 36 | } 37 | }; 38 | // @lc code=end 39 | 40 | -------------------------------------------------------------------------------- /programming/tree/113.路径总和-ii.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=113 lang=cpp 3 | * 4 | * [113] 路径总和 II 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for a binary tree node. 10 | * struct TreeNode { 11 | * int val; 12 | * TreeNode *left; 13 | * TreeNode *right; 14 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 15 | * }; 16 | */ 17 | class Solution { 18 | public: 19 | void dfs(vector > &res, vector& path, int exp, TreeNode* root) { 20 | if(!root) { 21 | return; 22 | } 23 | path.push_back(root->val); 24 | 25 | if(root->left == nullptr && root->right == nullptr && root->val == exp) { 26 | res.push_back(path); 27 | } 28 | 29 | dfs(res, path, exp-root->val, root->left); 30 | dfs(res, path, exp-root->val, root->right); 31 | 32 | path.pop_back(); 33 | } 34 | vector> pathSum(TreeNode* root, int sum) { 35 | vector > res; 36 | vector path; 37 | dfs(res, path, sum, root); 38 | return res; 39 | } 40 | }; 41 | // @lc code=end 42 | 43 | -------------------------------------------------------------------------------- /programming/backtrack/131.分割回文串.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | bool isPalindrome(const string& s, int left, int right) { 3 | while (left < right) { 4 | if (s[left++] != s[right--]) { 5 | return false; 6 | } 7 | } 8 | return true; 9 | } 10 | 11 | public: 12 | // 从答案的角度思考 13 | vector> partition(string s) { 14 | int n = s.size(); 15 | vector> ans; 16 | vector path; 17 | 18 | // 考虑 s[i] ~ s[n-1] 怎么分割 19 | auto dfs = [&](this auto&& dfs, int i) { 20 | if (i == n) { // s 分割完毕 21 | ans.emplace_back(path); 22 | return; 23 | } 24 | for (int j = i; j < n; j++) { // 枚举子串的结束位置 25 | if (isPalindrome(s, i, j)) { 26 | path.push_back(s.substr(i, j - i + 1)); // 分割! 27 | // 考虑剩余的 s[j+1] ~ s[n-1] 怎么分割 28 | dfs(j + 1); 29 | path.pop_back(); // 恢复现场 30 | } 31 | } 32 | }; 33 | 34 | dfs(0); 35 | return ans; 36 | } 37 | }; -------------------------------------------------------------------------------- /programming/linked_list/86.分隔链表.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=86 lang=cpp 3 | * 4 | * [86] 分隔链表 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for singly-linked list. 10 | * struct ListNode { 11 | * int val; 12 | * ListNode *next; 13 | * ListNode(int x) : val(x), next(NULL) {} 14 | * }; 15 | */ 16 | /** 17 | * Definition for singly-linked list. 18 | * struct ListNode { 19 | * int val; 20 | * ListNode *next; 21 | * ListNode(int x) : val(x), next(NULL) {} 22 | * }; 23 | */ 24 | class Solution { 25 | public: 26 | ListNode* partition(ListNode* head, int x) { 27 | ListNode lowHead(0), highHead(0), *low = &lowHead, *high=&highHead, *cur = head; 28 | while(cur) { 29 | if(cur->val < x) { 30 | low->next= cur; 31 | low = low->next; 32 | } else { 33 | high->next = cur; 34 | high = high->next; 35 | } 36 | cur = cur->next; 37 | } 38 | low->next = highHead.next; 39 | high->next = nullptr; 40 | return lowHead.next; 41 | } 42 | }; 43 | // @lc code=end 44 | 45 | -------------------------------------------------------------------------------- /programming/backtrack/842.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector ans; 4 | bool check(){ 5 | if(ans.size() < 3) return true; 6 | return (long long)ans.back() == (long long)ans[ans.size() - 2] + (long long)ans[ans.size() - 3]; 7 | } 8 | bool dfs(string& s, int ind){ 9 | if(ind >= s.size()) return ans.size() > 2; // 出口,ans.size()大于2表示找到一个合法的答案了 10 | if(s[ind] == '0'){ 11 | ans.push_back(0); 12 | if(check() && dfs(s, ind + 1)) return true; // 本次选择合法并且后续搜索也找到答案 13 | ans.pop_back(); 14 | return false; // 回溯 15 | } 16 | long long cur = 0; // 枚举所有不超过INT_MAX的数作为本层选择 17 | while(ind < s.size()){ 18 | cur = cur * 10 + s[ind++] - '0'; 19 | if(cur > INT_MAX) return false; // 枚举已经超过INT_MAX却还没找打答案,搜索失败 20 | ans.push_back(cur); 21 | if(check() && dfs(s, ind)) return true; // 本次选择合法并且后续搜索也找到答案 22 | ans.pop_back(); 23 | } 24 | return false; // 回溯 25 | } 26 | vector splitIntoFibonacci(string s) { 27 | if(dfs(s, 0)) return ans; 28 | return {}; 29 | } 30 | }; -------------------------------------------------------------------------------- /programming/binary-search/81.搜索旋转排序数组-ii.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=81 lang=cpp 3 | * 4 | * [81] 搜索旋转排序数组 II 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | bool search(vector& nums, int target) { 11 | int left = 0, right = nums.size()-1, mid; 12 | while(left<=right) { 13 | mid = (left + right) >> 1; 14 | if(nums[mid] == target) return true; 15 | // the only difference from the first one, trickly case, just updat left and right 16 | if( (nums[left] == nums[mid]) && (nums[right] == nums[mid]) ) { 17 | ++left; --right; 18 | } 19 | else if(nums[left] <= nums[mid]) { 20 | if( (nums[left]<=target) && (nums[mid] > target) ) 21 | right = mid-1; 22 | else left = mid + 1; 23 | } 24 | else { 25 | if((nums[mid] < target) && (nums[right] >= target) ) 26 | left = mid+1; 27 | else right = mid-1; 28 | } 29 | } 30 | return false; 31 | } 32 | }; 33 | // @lc code=end 34 | 35 | -------------------------------------------------------------------------------- /programming/hash-table/128.最长连续序列.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=128 lang=cpp 3 | * 4 | * [128] 最长连续序列 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | int longestConsecutive(vector& nums) { 11 | // 100,4,200,1,3,2 12 | // 不断的更新边界值, 13 | // 100 l=0,r=0 -> len=1 14 | // 4 l=0,r=0,len=1 15 | // 200 l=0,r=0,len=1 16 | // 1 l=0,r=0,len=1 17 | // 3 l=0,r=1,len=2 3,4 18 | // 2 l=1,r=2, len=4 19 | int res = 0; 20 | unordered_map map; 21 | for(auto n : nums) { 22 | if(map.find(n) == map.end()) { 23 | int l = map.count(n-1) == 1 ? map[n-1] : 0; 24 | int r = map.count(n+1) == 1 ? map[n+1] : 0; 25 | int len = r + l + 1; 26 | map[n] = len; 27 | map[n-l] = len; // 特别注意 28 | map[n+r] = len; 29 | res = max(len, res); 30 | 31 | } else { 32 | // 出现过的元素,不会重新更新左右边界 33 | continue; 34 | } 35 | } 36 | return res; 37 | } 38 | }; 39 | // @lc code=end 40 | 41 | -------------------------------------------------------------------------------- /programming/search/129.求根到叶子节点数字之和.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=129 lang=cpp 3 | * 4 | * [129] 求根到叶子节点数字之和 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for a binary tree node. 10 | * struct TreeNode { 11 | * int val; 12 | * TreeNode *left; 13 | * TreeNode *right; 14 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 15 | * }; 16 | */ 17 | /** 18 | * Definition for a binary tree node. 19 | * struct TreeNode { 20 | * int val; 21 | * TreeNode *left; 22 | * TreeNode *right; 23 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 24 | * }; 25 | */ 26 | // 注意了,此题不能广搜,会很复杂 27 | class Solution { 28 | public: 29 | int res = 0; 30 | void dfs(TreeNode* root, int sum) { 31 | if(!root) { 32 | return; 33 | } 34 | sum = 10*sum + root->val; 35 | if(!root->left && !root->right) { 36 | res += sum; 37 | } 38 | 39 | dfs(root->left, sum); 40 | dfs(root->right, sum); 41 | } 42 | 43 | int sumNumbers(TreeNode* root) { 44 | dfs(root, 0); 45 | return res; 46 | } 47 | }; 48 | // @lc code=end 49 | 50 | -------------------------------------------------------------------------------- /programming/1248.统计「优美子数组」.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=1248 lang=cpp 3 | * 4 | * [1248] 统计「优美子数组」 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | // [2,2,2,1,2,2,1,2,2,2] 11 | // 将奇数存储起来 3 6 12 | // 分别统计其左边和右边的奇数m,n -> (m+1)*(n+1) 13 | int numberOfSubarrays(vector& nums, int k) { 14 | int n = nums.size(); 15 | vectorindex; 16 | for(int i = 0; i < n; i ++){ 17 | //存奇数数字的下标 18 | if(nums[i] % 2) 19 | index.push_back(i); 20 | 21 | } 22 | if(index.size() < k) return 0; 23 | if(index.size() == k) return (index[0] + 1)*(n - index[k - 1]); 24 | int number = 0; 25 | for(int i = 0; i <= index.size() - k; i ++){ 26 | if(i == 0) number += (index[0] + 1)*(index[k] - index[k - 1]); 27 | else if(i == index.size() - k) { 28 | number += (index[i] - index[i - 1])*(n - index[i + k - 1]); 29 | } else 30 | number += (index[i] - index[i - 1])*(index[i + k] - index[i + k - 1]); 31 | } 32 | return number; 33 | } 34 | }; 35 | // @lc code=end 36 | 37 | -------------------------------------------------------------------------------- /programming/dynamic-programming/1671.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | // dp[i] : 以i结尾的最长子序列长度 4 | vector get_lis_array(vector& nums) { 5 | int n = nums.size(); 6 | vector dp(n, 1), g; 7 | for (int i = 0; i < n; ++i) { 8 | auto it = lower_bound(g.begin(), g.end(), nums[i]); 9 | if(it == g.end()) { 10 | g.push_back(nums[i]); 11 | dp[i] = g.size(); 12 | } else { 13 | *it = nums[i]; 14 | dp[i] = it - g.begin() + 1; 15 | } 16 | } 17 | return dp; 18 | } 19 | 20 | int minimumMountainRemovals(vector& nums) { 21 | vector pre = get_lis_array(nums); 22 | vector reversed_nums(nums.rbegin(), nums.rend()); 23 | vector suf = get_lis_array(reversed_nums); 24 | reverse(suf.begin(), suf.end()); 25 | int ans = 0; 26 | for(int i=0; i 1 && suf[i] > 1) { 28 | ans = max(pre[i] + suf[i] - 1, ans); 29 | } 30 | } 31 | return nums.size() - ans; 32 | } 33 | }; -------------------------------------------------------------------------------- /programming/string/93.复原ip地址.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=93 lang=cpp 3 | * 4 | * [93] 复原IP地址 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | vector restoreIpAddresses(string s) { 11 | vector res; 12 | int len = s.size(); 13 | for(int i=1; i<4 && i3) 17 | continue; 18 | string a = s.substr(0, i); 19 | string b = s.substr(i, j-i); 20 | string c = s.substr(j, k-j); 21 | string d = s.substr(k, len-k); 22 | if(isValid(a) && isValid(b) && isValid(c) && isValid(d)) 23 | res.push_back(a+'.'+b+'.'+c+'.'+d); 24 | } 25 | } 26 | } 27 | return res; 28 | } 29 | bool isValid(string s){ 30 | if(atoi(s.c_str()) > 255 || (s[0] == '0' && s.size() > 1)) 31 | return false; 32 | return true; 33 | } 34 | }; 35 | // @lc code=end 36 | 37 | -------------------------------------------------------------------------------- /programming/dynamic-programming/0044.通配符匹配.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=44 lang=cpp 3 | * 4 | * [44] 通配符匹配 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | // 动态规划dp[i][j]表示s的前i个字符是否匹配p的前j个字符 11 | bool isMatch(string s, string p) { 12 | int m=s.size(), n=p.size(); 13 | vector > dp(m+1, vector(n+1,false)); 14 | //初始化 15 | dp[0][0] = true; 16 | for(int i=1; i<=n; i++) { 17 | dp[0][i] = (dp[0][i-1] && p[i-1] == '*'); 18 | } 19 | for(int i=1; i<=m; i++) { 20 | for(int j=1; j<=n; j++) { 21 | // dp[i][j]可能为true的情况 22 | // 1. 匹配上 23 | if(s[i-1] == p[j-1] || p[j-1] == '?') { 24 | dp[i][j] = dp[i-1][j-1]; 25 | } 26 | // 2.出现* 27 | if(p[j-1] == '*') { 28 | // a. *匹配空 dp[i][j-1] 29 | // b. *匹配 dp[i-1][j]---- 例如: abc 和a*的匹配方式 30 | dp[i][j] = dp[i][j-1] || dp[i-1][j]; 31 | } 32 | } 33 | } 34 | return dp[m][n]; 35 | } 36 | }; 37 | // @lc code=end 38 | 39 | -------------------------------------------------------------------------------- /programming/dynamic-programming/300.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | // 更简洁的写法 4 | int lengthOfLIS(vector& nums) { 5 | int n = nums.size(); 6 | vector g; 7 | for(int i=0; i=nums[i]的元素,则插入到末尾 10 | g.push_back(nums[i]); 11 | } else { 12 | *it = nums[i]; 13 | } 14 | } 15 | return g.size(); 16 | } 17 | // int lengthOfLIS(vector& nums) { 18 | // if(nums.empty()) return 0; 19 | // int n = nums.size(); 20 | // vector v; 21 | // v.push_back(nums[0]); 22 | // for(int i=1; i v.back()) { 24 | // v.push_back(nums[i]); 25 | // } else { 26 | // auto it = lower_bound(v.begin(), v.end(), nums[i]); 27 | // //int pos = lower_bound(v.begin(), v.end(), nums[i]) - v.begin(); 28 | // *it = nums[i]; 29 | // } 30 | 31 | // } 32 | // return v.size(); 33 | // } 34 | }; -------------------------------------------------------------------------------- /programming/linked_list/25.k-个一组翻转链表.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=25 lang=cpp 3 | * 4 | * [25] K 个一组翻转链表 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for singly-linked list. 10 | * struct ListNode { 11 | * int val; 12 | * ListNode *next; 13 | * ListNode(int x) : val(x), next(NULL) {} 14 | * }; 15 | */ 16 | class Solution { 17 | public: 18 | ListNode *reverseKGroup(ListNode *head, int k) { 19 | if (!head || k == 1) return head; 20 | int listLen = 0; 21 | ListNode preHead(0); 22 | preHead.next = head; 23 | ListNode* cur = &preHead, *pre = &preHead, *next = NULL; 24 | while (cur = cur->next) listLen++; 25 | while (listLen >= k) { 26 | cur = pre->next; 27 | next = cur->next; 28 | for (int i = 0; i < k - 1; i++) { 29 | cur->next = next->next; 30 | next->next = pre->next; 31 | pre->next = next; 32 | next = cur->next; 33 | } 34 | pre = cur; 35 | listLen -= k; 36 | } 37 | return preHead.next; 38 | } 39 | }; 40 | // @lc code=end 41 | 42 | -------------------------------------------------------------------------------- /Algorithm/knapsack_problem/0_1.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | https://www.acwing.com/problem/content/2/ 3 | 动态规划: f[i][j] : 第i个物品,重量j时最大的价值 4 | 1)当前背包容量不够,为前i-1个物品最优解: f[i][j] = f[i-1][j] 5 | 2)当前背包容量够,判断选与不选第i个物品 6 | 选:f[i][j] = f[i-1][j-w[i]] + v[i] 7 | 不选:f[i][j] = f[i-1][j] 8 | 9 | 优化方式:因为i只与i-1状态有关 10 | 状态转移方程为:f[j]=max(f[j],f[j-w[i]]+v[i] 11 | for(int i = 1; i <= n; ++i) 12 | { 13 | for(int j = m; j>=0; --j) 14 | if(j>=w[i]) 15 | f[j] = max(f[j], f[j-w[i]]+v[i]); 16 | } 17 | 18 | */ 19 | 20 | # include 21 | using namespace std; 22 | 23 | const int MAXN=1010; 24 | int w[MAXN], v[MAXN]; //重量和价值 25 | int f[MAXN][MAXN]; // f[i][j], j重量下前i个物品的最大价值 26 | 27 | int main() { 28 | int n, m; 29 | cin >> n >> m; 30 | for (int i=1; i<=n; i++) { 31 | cin >> w[i] >> v[i]; 32 | } 33 | for (int i=1; i<=n; i++) { 34 | for (int j=1; j<=m; j++) { 35 | f[i][j] = f[i-1][j]; //不选 36 | if (j >= w[i]) //当前容量能否装下 37 | f[i][j] = max(f[i][j], f[i-1][j-w[i]] + v[i]); 38 | //cout << f[i][j] << " "; 39 | } 40 | //cout << endl; 41 | } 42 | cout << f[n][m] <& A) { 12 | int count = 0; 13 | sort(A.begin(), A.end()); 14 | for (int i = 1; i < A.size(); ++i) { 15 | int diff = A[i - 1] - A[i] + 1 ; //diff表示后者需要比前者大1,所要进行的操作次数 16 | count += max(0, diff ); 17 | A[i] += max(0, diff ); 18 | } 19 | return count; 20 | } 21 | //计数 22 | /* 23 | int minIncrementForUnique(vector& A) { 24 | int cnt[80000] = { 0 }; 25 | for (int x: A) cnt[x]++; 26 | 27 | int ans = 0, taken = 0; 28 | 29 | for (int x = 0; x < 80000; ++x) { 30 | if (cnt[x] >= 2) { 31 | taken += cnt[x] - 1; 32 | ans -= x * (cnt[x] - 1); 33 | } 34 | else if (taken > 0 && cnt[x] == 0) { 35 | taken--; 36 | ans += x; 37 | } 38 | } 39 | 40 | return ans; 41 | } 42 | */ 43 | }; 44 | // @lc code=end 45 | 46 | -------------------------------------------------------------------------------- /programming/dynamic-programming/63.不同路径-ii.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=63 lang=cpp 3 | * 4 | * [63] 不同路径 II 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | // 方法1:使用矩阵保存数组结果 11 | int uniquePathsWithObstacles(vector > &obstacleGrid) { 12 | int m = obstacleGrid.size() , n = obstacleGrid[0].size(); 13 | vector> dp(m+1,vector(n+1,0)); 14 | // 巧妙的初始化方式 15 | dp[0][1] = 1; 16 | for(int i = 1 ; i <= m ; ++i) 17 | for(int j = 1 ; j <= n ; ++j) 18 | if(!obstacleGrid[i-1][j-1]) 19 | dp[i][j] = dp[i-1][j]+dp[i][j-1]; 20 | return dp[m][n]; 21 | } 22 | // 方法2: 因为此题的特殊性,可以直接在矩阵中进行操作,伪代码如下: 23 | // 链接:https://leetcode-cn.com/problems/unique-paths-ii/solution/bu-tong-lu-jing-ii-by-leetcode/ 24 | /* 25 | for i in range(1,m): 26 | for j in range(1,n): 27 | if obstacleGrid[i][j] == 0: 28 | obstacleGrid[i][j] = obstacleGrid[i-1][j] + obstacleGrid[i][j-1] 29 | else: 30 | obstacleGrid[i][j] = 0 31 | */ 32 | }; 33 | // @lc code=end 34 | 35 | -------------------------------------------------------------------------------- /programming/tree/199.二叉树的右视图.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=199 lang=cpp 3 | * 4 | * [199] 二叉树的右视图 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for a binary tree node. 10 | * struct TreeNode { 11 | * int val; 12 | * TreeNode *left; 13 | * TreeNode *right; 14 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 15 | * }; 16 | */ 17 | class Solution { 18 | public: 19 | vector rightSideView(TreeNode* root) { 20 | vector res; 21 | if(!root) return res; 22 | queue que; 23 | que.push(root); 24 | while(!que.empty()) { 25 | int size = que.size(); 26 | for(int i=0; ival); 31 | } 32 | if(root->left) { 33 | que.push(root->left); 34 | } 35 | if(root->right) { 36 | que.push(root->right); 37 | } 38 | } 39 | } 40 | return res; 41 | } 42 | }; 43 | // @lc code=end 44 | 45 | -------------------------------------------------------------------------------- /programming/search/785.判断二分图.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=785 lang=cpp 3 | * 4 | * [785] 判断二分图 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | bool isBipartite(vector>& graph) { 11 | if(graph.empty()) { 12 | return true; 13 | } 14 | int n = graph.size(); 15 | vector color(n, 0); // 初始化不染色 16 | queue que; 17 | for(int i=0; i& inorder,int i,int j, vector& postorder,int ii,int jj) { 20 | if (i>j||ii>jj) return NULL; 21 | int mid=postorder[jj]; 22 | TreeNode* root=new TreeNode(mid); 23 | int index=0; 24 | for ( index=i;index<=j;index++) { 25 | if (inorder[index]==mid) 26 | break; 27 | } 28 | int dis=index-i; //步数 29 | root->left=helper(inorder,i,i+dis-1,postorder,ii,ii+dis-1); 30 | root->right=helper(inorder,i+dis+1,j,postorder,ii+dis,jj-1); 31 | return root; 32 | } 33 | TreeNode* buildTree(vector& inorder, vector& postorder) { 34 | return helper(inorder,0,inorder.size()-1,postorder,0,postorder.size()-1); 35 | } 36 | }; 37 | // @lc code=end 38 | 39 | -------------------------------------------------------------------------------- /programming/slide-window/567.字符串的排列cpp: -------------------------------------------------------------------------------- 1 | // 统一的模板 2 | // 3 & 76 & 438 & 567 3 | 4 | class Solution { 5 | public: 6 | bool checkInclusion(string s1, string s2) { 7 | unordered_map need, window; 8 | for (char c : s1) need[c]++; 9 | 10 | int left = 0, right = 0; 11 | int valid = 0; 12 | while (right < s2.size()) { 13 | char c = s2[right]; 14 | right++; 15 | // 进行窗口内数据的一系列更新 16 | if (need.count(c)) { 17 | window[c]++; 18 | if (window[c] == need[c]) 19 | valid++; 20 | } 21 | // 判断左侧窗口是否要收缩 22 | while (right - left >= s1.size()) { 23 | // 当窗口符合条件时,把起始索引加入 res 24 | if (valid == need.size()) 25 | return true; 26 | char d = s2[left]; 27 | left++; 28 | // 进行窗口内数据的一系列更新 29 | if (need.count(d)) { 30 | if (window[d] == need[d]) 31 | valid--; 32 | window[d]--; 33 | } 34 | } 35 | 36 | } 37 | return false; 38 | } 39 | 40 | }; -------------------------------------------------------------------------------- /programming/1071.字符串的最大公因子.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=1071 lang=cpp 3 | * 4 | * [1071] 字符串的最大公因子 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | /* 11 | bool valid(string str, string s) { 12 | int m = str.size(), n = s.size(); 13 | if(m % n != 0) return false; 14 | string tmp=""; 15 | for(int i=1; i<= m/n; i++) { 16 | tmp += s; 17 | if(tmp != str.substr(0, i*n)) { 18 | return false; 19 | } 20 | } 21 | return true; 22 | } 23 | 24 | string gcdOfStrings(string str1, string str2) { 25 | if(str1.size() > str2.size()) { 26 | return gcdOfStrings(str2, str1); 27 | } 28 | string res = ""; 29 | for(int i=str1.size(); i>=1; i--) { 30 | string s = str1.substr(0, i); // 前缀 31 | if(valid(str1,s) && valid(str2, s)) { 32 | return s; 33 | } 34 | } 35 | return res; 36 | } 37 | */ 38 | string gcdOfStrings(string str1, string str2) { 39 | return (str1 + str2 == str2 + str1) ? str1.substr(0, gcd(size(str1), size(str2))) : ""; 40 | } 41 | }; 42 | // @lc code=end 43 | 44 | -------------------------------------------------------------------------------- /programming/slide-window/438.找到字符串中所有字母异位词.cpp: -------------------------------------------------------------------------------- 1 | 2 | // 模板题, 滑动窗口,定长和不定长都可以 3 | class Solution { 4 | public: 5 | vector findAnagrams(string s, string t) { 6 | unordered_map need, window; 7 | for (char c : t) need[c]++; 8 | 9 | int left = 0, right = 0; 10 | int valid = 0; 11 | vector res; // 记录结果 12 | while (right < s.size()) { 13 | // insert 14 | char c = s[right]; 15 | right++; 16 | // 进行窗口内数据的一系列更新 17 | if (need.count(c)) { 18 | window[c]++; 19 | if (window[c] == need[c]) 20 | valid++; 21 | } 22 | // 判断左侧窗口是否要收缩 23 | while (right - left >= t.size()) { // 本题可以换成if 24 | // 当窗口符合条件时,把起始索引加入 res 25 | // update 26 | if (valid == need.size()) 27 | res.push_back(left); 28 | char d = s[left]; 29 | // remove 30 | left++; 31 | // 进行窗口内数据的一系列更新 32 | if (need.count(d)) { 33 | if (window[d] == need[d]) 34 | valid--; 35 | window[d]--; 36 | } 37 | } 38 | } 39 | return res; 40 | } 41 | }; 42 | // @lc code=end 43 | 44 | -------------------------------------------------------------------------------- /programming/tree/958.二叉树的完全性检验.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=958 lang=cpp 3 | * 4 | * [958] 二叉树的完全性检验 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for a binary tree node. 10 | * struct TreeNode { 11 | * int val; 12 | * TreeNode *left; 13 | * TreeNode *right; 14 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 15 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 16 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 17 | * }; 18 | */ 19 | class Solution { 20 | public: 21 | bool isCompleteTree(TreeNode* root) { 22 | // 层序遍历,空节点之后不能再出现空节点, [1,2,3,4,5,null,7]不是完全二叉树 23 | queue que; 24 | que.push(root); 25 | bool end = false; 26 | while(!que.empty()) { 27 | root = que.front(); 28 | que.pop(); 29 | if(end && root) { 30 | return false; 31 | } 32 | if(!root) { 33 | end = true; 34 | continue; 35 | } 36 | que.push(root->left); 37 | que.push(root->right); 38 | } 39 | return true; 40 | 41 | } 42 | }; 43 | // @lc code=end 44 | 45 | -------------------------------------------------------------------------------- /programming/dynamic-programming/0070.爬楼梯.cpp: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* 0070.爬楼梯.cpp :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: taoyanqi +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2025/11/14 09:32:41 by taoyanqi #+# #+# */ 9 | /* Updated: 2025/11/14 09:32:43 by taoyanqi ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | class Solution { 14 | public: 15 | int climbStairs(int n) { 16 | int f0 = 1, f1 = 1; 17 | for (int i = 2; i <= n; i++) { 18 | int new_f = f1 + f0; 19 | f0 = f1; 20 | f1 = new_f; 21 | } 22 | return f1; 23 | } 24 | }; -------------------------------------------------------------------------------- /programming/slide-window/3697_3698.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | 给你两个字符串 word1 和 word2 。 4 | 5 | 如果一个字符串 x 重新排列后,word2 是重排字符串的 6 | 前缀 7 | ,那么我们称字符串 x 是 合法的 。 8 | 9 | 请你返回 word1 中 合法 10 | 子字符串 11 | 的数目。 12 | */ 13 | 14 | class Solution { 15 | public: 16 | long long validSubstringCount(string word1, string word2) { 17 | int m = word1.size(), n = word2.size(); 18 | if (m < n) return 0; 19 | unordered_map count, need; 20 | for(auto &c : word2) { 21 | need[c]++; 22 | } 23 | int cnt = need.size(); 24 | int i = 0, j = 0; 25 | long long res = 0; 26 | while(j < m) { 27 | char s = word1[j]; 28 | count[s]++; 29 | if(need.count(s)) { 30 | if(count[s] == need[s]) { 31 | cnt--; 32 | } 33 | } 34 | while(i <= j && cnt == 0) { 35 | res += m - j; 36 | char t = word1[i]; 37 | i++; 38 | if(need.count(t) && --count[t] < need[t]) { 39 | cnt++; 40 | break; 41 | } 42 | } 43 | j++; 44 | } 45 | return res; 46 | } 47 | }; -------------------------------------------------------------------------------- /programming/slide-window/76.最小覆盖子串.cpp: -------------------------------------------------------------------------------- 1 | // 滑动窗口,收缩的条件要明确 2 | 3 | class Solution { 4 | public: 5 | string minWindow(string s, string t) { 6 | unordered_map need, hash; 7 | int s_size = s.size(), t_size = t.size(); 8 | int need_cnt = 0, match = 0; 9 | for(int i=0; i < t_size; i++) { 10 | need[t[i]]++; 11 | } 12 | int beg = 0, end = 0, min_len=INT_MAX; 13 | int start = 0; 14 | while(end < s_size) { 15 | char c = s[end]; 16 | if(need.count(c)) { 17 | hash[c]++; 18 | if (need[c] == hash[c]) { 19 | match++; 20 | } 21 | } 22 | end++; 23 | // 满足条件后,才进行窗口的减少 24 | while (match == need.size()) { 25 | if(end-beg < min_len) { 26 | start = beg; 27 | min_len = end-beg; 28 | } 29 | char c2 = s[beg]; 30 | if(need.count(c2)) { 31 | // 这里注意条件, 都统一写成== 32 | if(hash[c2] == need[c2]) { 33 | match--; 34 | } 35 | hash[c2]--; 36 | } 37 | beg++; 38 | } 39 | } 40 | return min_len == INT_MAX ? "" : s.substr(start, min_len); 41 | } 42 | }; -------------------------------------------------------------------------------- /programming/slide-window/0076.最小覆盖子串.cpp: -------------------------------------------------------------------------------- 1 | // 滑动窗口,收缩的条件要明确 2 | 3 | class Solution { 4 | public: 5 | string minWindow(string s, string t) { 6 | unordered_map need, hash; 7 | int s_size = s.size(), t_size = t.size(); 8 | int need_cnt = 0, match = 0; 9 | for(int i=0; i < t_size; i++) { 10 | need[t[i]]++; 11 | } 12 | int beg = 0, end = 0, min_len=INT_MAX; 13 | int start = 0; 14 | while(end < s_size) { 15 | char c = s[end]; 16 | if(need.count(c)) { 17 | hash[c]++; 18 | if (need[c] == hash[c]) { 19 | match++; 20 | } 21 | } 22 | end++; 23 | // 满足条件后,才进行窗口的减少 24 | while (match == need.size()) { 25 | if(end-beg < min_len) { 26 | start = beg; 27 | min_len = end-beg; 28 | } 29 | char c2 = s[beg]; 30 | if(need.count(c2)) { 31 | // 这里注意条件, 都统一写成== 32 | if(hash[c2] == need[c2]) { 33 | match--; 34 | } 35 | hash[c2]--; 36 | } 37 | beg++; 38 | } 39 | } 40 | return min_len == INT_MAX ? "" : s.substr(start, min_len); 41 | } 42 | }; -------------------------------------------------------------------------------- /programming/tree/102.二叉树的层次遍历.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=102 lang=cpp 3 | * 4 | * [102] 二叉树的层次遍历 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for a binary tree node. 10 | * struct TreeNode { 11 | * int val; 12 | * TreeNode *left; 13 | * TreeNode *right; 14 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 15 | * }; 16 | */ 17 | class Solution { 18 | public: 19 | vector> levelOrder(TreeNode* root) { 20 | vector > res; 21 | if(!root) { 22 | return res; 23 | } 24 | queue que; 25 | que.push(root); 26 | while(!que.empty()) { 27 | int size = que.size(); 28 | vector v(size,0); 29 | for(int i=0; ival; 33 | if(root->left) { 34 | que.push(root->left); 35 | } 36 | if(root->right) { 37 | que.push(root->right); 38 | } 39 | } 40 | res.push_back(v); 41 | } 42 | return res; 43 | } 44 | }; 45 | // @lc code=end 46 | 47 | -------------------------------------------------------------------------------- /programming/695.岛屿的最大面积.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=695 lang=cpp 3 | * 4 | * [695] 岛屿的最大面积 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; 11 | 12 | void dfs(vector>& grid, int m, int n, int i, int j, int &count) { 13 | if(i >=m || i < 0 || j>=n || j<0 || grid[i][j] == 0) { 14 | return; 15 | } 16 | count++; 17 | grid[i][j] = 0; 18 | for(int k=0; k<4; k++) { 19 | int tx = i + dx[k]; 20 | int ty = j + dy[k]; 21 | dfs(grid, m, n, tx, ty, count); 22 | } 23 | return; 24 | } 25 | 26 | int maxAreaOfIsland(vector>& grid) { 27 | if(grid.empty() || grid[0].empty()) return 0; 28 | int row = grid.size(), col = grid[0].size(), res = 0; 29 | for(int i=0; i< row; i++) { 30 | for(int j=0; j< col; j++) { 31 | if(grid[i][j] == 1) { 32 | int count = 0; 33 | dfs(grid, row, col, i, j, count); 34 | res = max(res, count); 35 | } 36 | } 37 | } 38 | return res; 39 | } 40 | }; 41 | // @lc code=end 42 | 43 | -------------------------------------------------------------------------------- /programming/string/0058.最后一个单词的长度.cpp: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* 0058.最后一个单词的长度.cpp :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: taoyanqi +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2025/11/06 12:47:57 by taoyanqi #+# #+# */ 9 | /* Updated: 2025/11/06 12:48:11 by taoyanqi ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | class Solution { 14 | public: 15 | int lengthOfLastWord(string s) { 16 | // 实现很精妙,从后往前会更简单 17 | int i=s.size()-1,len=0; 18 | while (i >= 0 && s[i]==' ') i--; 19 | while (i >= 0 && s[i]!=' ') { 20 | i--;len++; 21 | } 22 | return len; 23 | } 24 | }; -------------------------------------------------------------------------------- /programming/bit-manipulation/3226.使两个整数相等的位更改次数.cpp: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* 3226.使两个整数相等的位更改次数.cpp :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: taoyanqi +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2025/09/24 11:07:31 by taoyanqi #+# #+# */ 9 | /* Updated: 2025/09/24 11:07:31 by taoyanqi ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | class Solution { 14 | public: 15 | int minChanges(int n, int k) { 16 | // 修改n的bit位,从集合的角度上删除一些数,剩余的集合和k集合是一致的 17 | // 也就是说 k 属于 n n & k == k 18 | // 如果是子集的关系,也就是要求差集 19 | return (n & k) != k ? -1 : __builtin_popcount(n ^ k); 20 | 21 | } 22 | }; -------------------------------------------------------------------------------- /Algorithm/sort/mySort_Demo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "mySort.h" 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | //insert sort test. 8 | vector arr = { 9,4,6,10,12,15,3,7,4 }; 9 | mySort::insert_sort(arr); 10 | mySort::print(arr); 11 | //merge sort test 12 | vector arr1 = { 9,4,6,10,12,15,3,7,4 }; 13 | mySort::merge_sort(arr, 0, arr1.size() - 1); 14 | mySort::print(arr); 15 | //shell srot test 16 | vector arr2 = { 9,4,6,10,12,15,3,7,4,13,456,35}; 17 | mySort::shell_sort(arr2); 18 | mySort::print(arr2); 19 | //quick sort test 20 | vector arr3 = { 9,4,6,10,12,15,3,7,4,13,456,35,2,3,4,1,5,7,8,4 }; 21 | mySort::quick_sort(arr3,0,arr3.size()-1); 22 | mySort::print(arr3); 23 | //bubble sort test 24 | vector arr4 = { 35,2,3,4,1,5,7,8,4,4,5,6,2,1}; 25 | mySort::bubble_sort(arr4); 26 | mySort::print(arr4); 27 | //select sort test 28 | vector arr5 = { 35,2,3,4,1,5,7,8,4,4,5,6,2,1,234,56,134 }; 29 | mySort::select_sort(arr5); 30 | mySort::print(arr5); 31 | //heap sort test 32 | vector arr6 = { 0,2,3,4,1,5,7,8,4,4,5,6,2,1,234,56,134 }; 33 | mySort::heap_sort(arr6); 34 | mySort::print(arr6); 35 | 36 | 37 | return 0; 38 | } 39 | 40 | -------------------------------------------------------------------------------- /programming/data-structure/295.数据流的中位数.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=295 lang=cpp 3 | * 4 | * [295] 数据流的中位数 5 | */ 6 | 7 | // @lc code=start 8 | class MedianFinder { 9 | public: 10 | /** initialize your data structure here. */ 11 | 12 | //存放较小的一半元素,堆顶元素为该堆的最大值 13 | priority_queue small; 14 | 15 | //存放较大的一半元素,堆顶元素为该堆的最小值 16 | priority_queue, greater> large; 17 | 18 | void addNum(int num) { 19 | 20 | //元素一开始全都入堆small,然后将堆small的最大元素加入到堆large 21 | //这样可以保证堆small存放的是较小的一半元素,堆large存放的是较大的一半元素 22 | small.push(num); 23 | large.push(small.top()); 24 | small.pop(); 25 | 26 | //平衡两个堆的个数,使这两个堆具有特性a)或b),即使得small的元素个数大于或等于large的元素个数 27 | if(large.size() > small.size()){ 28 | small.push(large.top()); 29 | large.pop(); 30 | } 31 | } 32 | 33 | double findMedian() { 34 | return small.size() > large.size() ? double(small.top()) : (small.top()+large.top())*0.5; 35 | } 36 | }; 37 | 38 | /** 39 | * Your MedianFinder object will be instantiated and called as such: 40 | * MedianFinder* obj = new MedianFinder(); 41 | * obj->addNum(num); 42 | * double param_2 = obj->findMedian(); 43 | */ 44 | // @lc code=end 45 | 46 | -------------------------------------------------------------------------------- /programming/tree/114.二叉树展开为链表.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=114 lang=cpp 3 | * 4 | * [114] 二叉树展开为链表 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for a binary tree node. 10 | * struct TreeNode { 11 | * int val; 12 | * TreeNode *left; 13 | * TreeNode *right; 14 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 15 | * }; 16 | */ 17 | class Solution { 18 | public: 19 | /* 20 | 1.将左子树插入到右子树的地方 21 | 2.将原来的右子树接到左子树的最右边节点 22 | 3.考虑新的右子树的根节点,一直重复上边的过程,直到新的右子树为 null 23 | */ 24 | void flatten(TreeNode* root) { 25 | while(root) { 26 | // 找到左子树的最右节点 27 | if(root->left == nullptr) { 28 | root = root->right; 29 | } else { 30 | // 找到左子树的最右节点 31 | TreeNode* pre = root->left; 32 | while(pre->right) { 33 | pre = pre->right; 34 | } 35 | // 原先的右子树加到左子树的最右节点 36 | pre->right = root->right; 37 | // 左子树变成当前节点的右子树 38 | root->right = root->left; 39 | root->left = nullptr; 40 | root = root->right; 41 | } 42 | } 43 | } 44 | }; 45 | // @lc code=end 46 | 47 | -------------------------------------------------------------------------------- /programming/favorite/readme.md: -------------------------------------------------------------------------------- 1 | 2 | - [重点、难点相关算法](#%e9%87%8d%e7%82%b9%e9%9a%be%e7%82%b9%e7%9b%b8%e5%85%b3%e7%ae%97%e6%b3%95) 3 | - [数组](#%e6%95%b0%e7%bb%84) 4 | - [字符串](#%e5%ad%97%e7%ac%a6%e4%b8%b2) 5 | - [回溯](#%e5%9b%9e%e6%ba%af) 6 | - [难点或暂时未搞懂的题目](#%e9%9a%be%e7%82%b9%e6%88%96%e6%9a%82%e6%97%b6%e6%9c%aa%e6%90%9e%e6%87%82%e7%9a%84%e9%a2%98%e7%9b%ae) 7 | - [总结](#%e6%80%bb%e7%bb%93) 8 | 9 | # 重点、难点相关算法 10 | 11 | 12 | ## 数组 13 | 14 | | Title | Comment| 15 | | ---- | -------|------| 16 | |[top-k问题总结](../array/top-k问题总结.md)|top k问题,两个有序数组的中位数问题| 17 | 18 | 19 | 20 | ## 字符串 21 | | Title | Solution | Source| 22 | | ---- | -------|------| 23 | 24 | 25 | ## 回溯 26 | | Title | Solution | Source| 27 | | ---- | -------|------| 28 | 29 | 30 | ## 难点或暂时未搞懂的题目 31 | 32 | | Title | Solution | Source| 33 | | ---- | -------|------| 34 | |文本左右对齐|[68.文本左右对齐.cpp](../string/68.文本左右对齐.py)|[文本左右对齐](https://leetcode-cn.com/problems/text-justification/)| 35 | |扰乱字符串|[87]|| 36 | |单词分割|[140.单词分割](../dynamit-programming/140.单词拆分-ii.cpp)|动态规划题目,bfs同样可解,但不知为何超时| 37 | 38 | 39 | ## 总结 40 | 41 | | Title | Comment| 42 | | ---- | -------| 43 | |[二分问题](二分问题.md)| 二分模板总结| 44 | |[链表问题](链表问题.md) | 链表必会题| 45 | |[排序问题](排序问题.md)|排序问题总结| 46 | |[全排列问题.md](全排列问题.md)| 关于全排列问题的总结| 47 | |[数据结构](数据结构.md)|数据结构相关问题总结| -------------------------------------------------------------------------------- /programming/linked_list/链表相交.cpp: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* 链表相交.cpp :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: taoyanqi +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/05/07 21:04:20 by taoyanqi #+# #+# */ 9 | /* Updated: 2024/05/07 21:04:23 by taoyanqi ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | class Solution { 14 | public: 15 | ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { 16 | ListNode *l1 = headA, *l2 = headB; 17 | while(l1 != l2) { 18 | l1 = l1 ? l1->next : headB; 19 | l2 = l2 ? l2->next : headA; 20 | } 21 | return l1; 22 | } 23 | }; -------------------------------------------------------------------------------- /programming/tree/107.二叉树的层次遍历-ii.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=107 lang=cpp 3 | * 4 | * [107] 二叉树的层次遍历 II 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for a binary tree node. 10 | * struct TreeNode { 11 | * int val; 12 | * TreeNode *left; 13 | * TreeNode *right; 14 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 15 | * }; 16 | */ 17 | class Solution { 18 | public: 19 | vector> levelOrderBottom(TreeNode* root) { 20 | vector > res; 21 | if(!root) { 22 | return res; 23 | } 24 | queue que; 25 | que.push(root); 26 | while(!que.empty()) { 27 | int size = que.size(); 28 | vector v(size,0); 29 | for(int i=0; ival; 33 | if(root->left) { 34 | que.push(root->left); 35 | } 36 | if(root->right) { 37 | que.push(root->right); 38 | } 39 | } 40 | res.insert(res.begin(), v); 41 | } 42 | return res; 43 | } 44 | }; 45 | // @lc code=end 46 | 47 | -------------------------------------------------------------------------------- /programming/tree/109.有序链表转换二叉搜索树.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=109 lang=cpp 3 | * 4 | * [109] 有序链表转换二叉搜索树 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for singly-linked list. 10 | * struct ListNode { 11 | * int val; 12 | * ListNode *next; 13 | * ListNode(int x) : val(x), next(NULL) {} 14 | * }; 15 | */ 16 | /** 17 | * Definition for a binary tree node. 18 | * struct TreeNode { 19 | * int val; 20 | * TreeNode *left; 21 | * TreeNode *right; 22 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 23 | * }; 24 | */ 25 | class Solution { 26 | public: 27 | TreeNode* sortedListToBST(ListNode* head) { 28 | return buildTree(head, nullptr); 29 | } 30 | TreeNode * buildTree(ListNode* head, ListNode * tail){ 31 | if(head == tail) return nullptr; 32 | ListNode* slow = head, *fast = head; 33 | // 快慢指针找中间节点 34 | while(fast != tail && fast->next != tail){ 35 | slow = slow->next; 36 | fast = fast->next->next; 37 | } 38 | TreeNode * root = new TreeNode(slow->val); 39 | root->left = buildTree(head, slow); 40 | root->right = buildTree(slow->next, tail); 41 | return root; 42 | } 43 | }; 44 | // @lc code=end 45 | 46 | -------------------------------------------------------------------------------- /programming/linked_list/234.回文链表.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * struct ListNode { 4 | * int val; 5 | * ListNode *next; 6 | * ListNode() : val(0), next(nullptr) {} 7 | * ListNode(int x) : val(x), next(nullptr) {} 8 | * ListNode(int x, ListNode *next) : val(x), next(next) {} 9 | * }; 10 | */ 11 | class Solution { 12 | public: 13 | bool isPalindrome(ListNode* head) { 14 | // 1 2 2 1 -> 1->2-2 1 -> 2 -> nullptr 15 | // 1 2 2 2 1 -> 1 -> 2->2 1-> 2->2 1->2->2 16 | if(!head || !head->next) return true; 17 | ListNode *slow = head, *fast = head; 18 | while(fast && fast->next) { 19 | slow = slow->next; 20 | fast = fast->next->next; 21 | } 22 | // 反转链表 23 | ListNode *pre = nullptr, *cur = slow; 24 | while(cur) { 25 | ListNode *nxt = cur->next; 26 | cur->next = pre; 27 | pre = cur; 28 | cur = nxt; 29 | } 30 | // pre 31 | while(head && pre) { 32 | if(head->val != pre->val) { 33 | return false; 34 | } 35 | head = head->next; 36 | pre = pre->next; 37 | } 38 | return true; 39 | } 40 | }; -------------------------------------------------------------------------------- /programming/array/189.旋转数组.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=189 lang=cpp 3 | * 4 | * [189] 旋转数组 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | void rotate(vector& nums, int k) { 11 | int len=nums.size(); 12 | if (len==0||k<=0) return; 13 | k=k%len; 14 | reverse(nums.begin(),nums.begin()+len-k); 15 | reverse(nums.begin()+len-k,nums.end()); 16 | reverse(nums.begin(),nums.end()); 17 | } 18 | /* 19 | void rotate(vector& nums, int k) { 20 | int len=nums.size(); 21 | if (len==0||k<=0) return; 22 | k=k%len; 23 | vector v(nums.begin()+len-k,nums.end()); 24 | for (int i=len-1;i>=k;i--) { 25 | nums[i]=nums[i-k]; 26 | } 27 | for (int i=0;i& nums, int k) { 35 | int n = nums.size(); 36 | vector newArr(n); 37 | for (int i = 0; i < n; ++i) { 38 | newArr[(i + k) % n] = nums[i]; 39 | } 40 | nums.assign(newArr.begin(), newArr.end()); 41 | } 42 | }; 43 | */ 44 | 45 | 46 | }; 47 | // @lc code=end 48 | 49 | -------------------------------------------------------------------------------- /programming/sort/51. 数组中的逆序对.md: -------------------------------------------------------------------------------- 1 | [数组中的逆序对](https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/) 2 | 3 | 归并排序中,可以顺便计算逆序对的个数,一定要会归并排序。 4 | 5 | ``` 6 | class Solution { 7 | public: 8 | int res = 0; 9 | void merge(vector &nums, int left, int mid, int right) { 10 | vector v(right-left+1, 0); 11 | int i=left, j = mid+1, k=0; 12 | while(i <= mid && j <= right) { 13 | if(nums[i] <= nums[j]) { 14 | v[k++] = nums[i++]; 15 | } else { 16 | v[k++] = nums[j++]; 17 | res += mid-i+1; 18 | } 19 | } 20 | while(i<=mid) v[k++] = nums[i++]; 21 | while(j<=right) v[k++] = nums[j++]; 22 | for(int i=0;i &nums, int left, int right) { 28 | if(left < right) { 29 | int mid = (left+right) >> 1; 30 | merge_sort(nums, left, mid); 31 | merge_sort(nums, mid+1, right); 32 | merge(nums, left, mid , right); 33 | } 34 | } 35 | int reversePairs(vector& nums) { 36 | if(nums.empty()) return 0; 37 | merge_sort(nums, 0, nums.size()-1); 38 | return res; 39 | } 40 | }; 41 | ``` 42 | -------------------------------------------------------------------------------- /programming/tree/173.二叉搜索树迭代器.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=173 lang=cpp 3 | * 4 | * [173] 二叉搜索树迭代器 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for a binary tree node. 10 | * struct TreeNode { 11 | * int val; 12 | * TreeNode *left; 13 | * TreeNode *right; 14 | * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 15 | * }; 16 | */ 17 | class BSTIterator { 18 | public: 19 | // 记得使用栈模拟 20 | stack st; 21 | BSTIterator(TreeNode *root) { 22 | pushAllLeft(root); 23 | } 24 | 25 | /** @return whether we have a next smallest number */ 26 | bool hasNext() { 27 | return !st.empty(); 28 | } 29 | 30 | /** @return the next smallest number */ 31 | int next() { 32 | TreeNode* node=st.top(); 33 | st.pop(); 34 | pushAllLeft(node->right); 35 | return node->val; 36 | } 37 | private: 38 | void pushAllLeft(TreeNode* root) { 39 | while(root) { 40 | st.push(root); 41 | root=root->left; 42 | } 43 | } 44 | }; 45 | 46 | /** 47 | * Your BSTIterator object will be instantiated and called as such: 48 | * BSTIterator* obj = new BSTIterator(root); 49 | * int param_1 = obj->next(); 50 | * bool param_2 = obj->hasNext(); 51 | */ 52 | // @lc code=end 53 | 54 | -------------------------------------------------------------------------------- /programming/bit-manipulation/位插入.cpp: -------------------------------------------------------------------------------- 1 | /* ************************************************************************** */ 2 | /* */ 3 | /* ::: :::::::: */ 4 | /* 位插入.cpp :+: :+: :+: */ 5 | /* +:+ +:+ +:+ */ 6 | /* By: taoyanqi +#+ +:+ +#+ */ 7 | /* +#+#+#+#+#+ +#+ */ 8 | /* Created: 2024/05/23 20:30:58 by taoyanqi #+# #+# */ 9 | /* Updated: 2024/05/23 20:31:26 by taoyanqi ### ########.fr */ 10 | /* */ 11 | /* ************************************************************************** */ 12 | 13 | // https://leetcode.cn/problems/insert-into-bits-lcci/description/?envType=study-plan-v2&envId=cracking-the-coding-interview 14 | class Solution { 15 | public: 16 | int insertBits(int N, int M, int i, int j) { 17 | // i-j 置0 18 | for(int k=i; k <=j; k++) { 19 | N &= ~(1 << k); 20 | } 21 | return N + (M << i); 22 | } 23 | }; -------------------------------------------------------------------------------- /programming/math/65.有效数字.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode.cn id=65 lang=cpp 3 | * 4 | * [65] 有效数字 5 | */ 6 | 7 | // @lc code=start 8 | class Solution { 9 | public: 10 | bool isNumber(string s) { 11 | int n = s.size(), i = 0, digits = 0, dots = 0; 12 | // 1. 去掉前导空格 13 | for (; i < n && isspace(s[i]); i++); 14 | // 2. 如果有符号,去掉 15 | if (s[i] == '+' || s[i] == '-') { 16 | i++; 17 | } 18 | // 3. 接下来是.和数字都可以,统计点和数字的个数 19 | for (; i < n && (isdigit(s[i]) || s[i] == '.'); i++) { 20 | isdigit(s[i]) ? digits++ : dots++; 21 | } 22 | // 没有数字或者.大于1个,则是错误的 23 | if (!digits || dots > 1) { 24 | return false; 25 | } 26 | // 4. 对e进行特殊处理 27 | if (s[i] == 'e') { 28 | i++; 29 | // 去掉符号 30 | if (s[i] == '+' || s[i] == '-') { 31 | i++; 32 | } 33 | digits = 0; 34 | for (; i < n && isdigit(s[i]); i++) { 35 | digits++; 36 | } 37 | // e后面必须加数字 38 | if (!digits) { 39 | return false; 40 | } 41 | } 42 | // 5. 去掉末尾空格 43 | for (; i < n && isspace(s[i]); i++); 44 | return i == n; 45 | } 46 | }; 47 | // @lc code=end 48 | 49 | --------------------------------------------------------------------------------