
数据结构与算法
文章平均质量分 60
记录数据结构与算法
我只是一只自动小青蛙
这个作者很懒,什么都没留下…
展开
-
在线编程常见输入输出
一、多组等长数据输入题目:输入包括两个正整数a,b(1 <= a, b <= 10^9),输入数据包括多组。输出a+b的结果。解决方案:使用iostream头文件和std命名空间使用while(cin >> a >> b)来依次读取多组输入,这里注意a和b需要提前定义输入输出例子//输入1 510 20//输出630解题代码#include <iostream>using namespace std;int main(){原创 2021-07-17 23:49:12 · 1267 阅读 · 1 评论 -
算法范本:链表
一、链表基础链表的基础操作包括链表的创建和增删查改。其中链表的索引index一般从0开始。这里有以下几点需要注意:链表是一个类,节点结构体是类中的一个私有结构体对于一个链表,其私有数据需要包括节点结构体,虚拟头结点,节点数量对于节点结构体,需要在定义结构体的时候需要定义构造函数,且不要忘记结构体定义最后的;号对于链表,需要在public中定义链表的初始化构造函数class MyLinkedList {private: /---链表依赖的基础结构:节点,节点数量,虚拟头结点---/原创 2021-07-09 16:00:24 · 672 阅读 · 0 评论 -
那些见过才会的题目
11. 盛最多水的容器给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。这道题应该使用双指针方法来做,初始化左右指针分别指向数组的左右两端,指针移动规则为:如果左指针元素小于右指针元素,则左指针向右移动如果右指针元素小于左指针元素,则右指针向左移动记录指针遍历过程中全部容量,选择其中最大的最最原创 2021-07-09 13:03:20 · 163 阅读 · 2 评论 -
算法范本:旋转矩阵
给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。其核心问题在于:遍历多少圈:(min(m, n) + 1) / 2最后一个数如何处理:特殊处理什么时候遍历完成:必须实时判定,以防最后一圈遍历两次class Solution {public: vector<int> spiralOrder(vector<vector<int>>& matrix) { //空矩阵处理,一定先判定m原创 2021-07-08 17:26:36 · 282 阅读 · 0 评论 -
算法范本:滑动窗口
滑动窗口算法可以用于位于一个符合题意的子序列,在O(n)时间复杂下完成序列的子序列查找。一、滑动窗口滑动窗口的思想核心是先移动窗口终止位置扩张窗口;当扩张后的窗口不符合要求时,移动窗口其实位置缩小窗口,从而找到符合条件的窗口。其中要求:当窗口为空时,必须能够满足要求,否则窗口的起始位置就会超越终止位置int start = 0, end = 0, len = 0, res = INT32_MAX, sum = 0;/---窗口终止位置移动---/for(end; end < nums.原创 2021-07-08 17:03:14 · 237 阅读 · 0 评论 -
链表习题汇总
2. 两数相加给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。请你将两个数相加,并以相同形式返回一个表示和的链表。你可以假设除了数字 0 之外,这两个数都不会以 0 开头。联系链表操作,关键是别忘了进位class Solution {public: ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { ListNode* cur1 = l1;原创 2021-07-07 18:07:36 · 149 阅读 · 0 评论 -
动态规划(十):其他题目
647. 回文子串给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。注意:回文子串是要求连续的1、dp数组布尔类型的dp[i][j]:表示区间范围[i,j] (注意是左闭右闭)的子串是否是回文子串,如果是dp[i][j]为true,否则为false。2、递推公式想要等到dp[i][j],整体上是两种,就是s[i]与s[j]相等,s[i]与s[j]不相等这两种。当s[i]与s[j]不相等,那没啥好说的原创 2021-07-06 19:18:26 · 208 阅读 · 2 评论 -
动态规划(九):编辑距离
//d[i][j]为s[0,i - 1]和t[0,j - 1]中含有s[i-1]元素的最长子序列原创 2021-07-06 16:28:21 · 231 阅读 · 0 评论 -
C++基础知识
要求答案在32 位带符号整数范围那么题目中的int要换成uint64_t原创 2021-07-06 14:47:48 · 80 阅读 · 0 评论 -
动态规划(八):子序列系列
一、最长递增子序列(非连续)300. 最长递增子序列给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。1、dp数组dp[i]为以元素nums[i]结尾的最长递增子序列。2、递推公式位置i的最长升序子序列等于j从0到i-1各个位置的最长升序子序列 + 1 的最大值。 for(int j = i -原创 2021-07-06 11:02:53 · 1179 阅读 · 1 评论 -
动态规划(七):买卖股票发大财
一、买卖股票(单次买卖,持有一支)121. 买卖股票的最佳时机给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。1、dp数组含义我们使用二维数组记录第i天的两种状态dp[i][0]:第i天不持有股票手中的现金dp[i][1]:第i天持有股票手原创 2021-07-05 16:57:35 · 343 阅读 · 0 评论 -
动态规划(六):打家劫舍
一、打家劫舍基础题198. 打家劫舍你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。给定一个代表每个房屋存放金额的非负整数数组nums,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。1、dp数组含义dp[i]:考虑下标i(包括i)以内的房屋,最多可以偷窃的金额为dp[i]2、递推公式对于第i间房屋,可以分为两种情况:不偷第i间房屋:d原创 2021-07-05 10:10:42 · 451 阅读 · 0 评论 -
动态规划(五):多重背包问题
一、多重背包问题背包问题为有N种物品和一个最多能被重量为W 的背包。第i件物品的重量是weight[i],数量为Mi,得到的价值是value[i] ,没件物品只能使用一次,将这些物品装进背包,怎么装价值最高。二、多重背包问题的解法我们注意到01背包并没有要求物品不一样,因此我么可以把多重背包摊开,把Mi件第i中物品视作Mi种物品,没种只有一个,这就转换成一个01背包问题,具体的转化方式有两种1、显示摊开void test_multi_pack() { vector<int> w原创 2021-07-03 08:20:43 · 1475 阅读 · 0 评论 -
动态规划(三):01背包问题
一、背包问题概述背包问题为有N件物品和一个最多能被重量为W 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。将这些物品装进背包,怎么装价值最高。 根据条件不同,可以分为以下几类:01背包:每件物品只有一个,要不拿一个,要不不拿完全背包:每件物品有无数个,可以拿0-任意个多重背包:不同物品数量不同分组背包:多种物品组成一个小组,每组只能拿一种组合背包:01背包,完全背包与多重背包的组合体leetcode上学会01背包,完全背包和多种背包足够了,因此这里只讲这三种原创 2021-06-30 15:56:21 · 1051 阅读 · 1 评论 -
贪心算法(二):复杂例题
135. 分发糖果老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。你需要按照以下要求,帮助老师给这些孩子分发糖果:每个孩子至少分配到 1 个糖果。评分更高的孩子必须比他两侧的邻位孩子获得更多的糖果。那么这样下来,老师至少需要准备多少颗糖果呢?1、贪心策略本题目需要使用两次贪心策略,首先给每个孩子发一个糖果,然后:第一次是从左边往右边贪心:只要右边评分比左边大,右边的孩子就多一个糖果第二次是右边往左边贪心:只要左边比右边大,左边的孩子得原创 2021-06-28 15:32:54 · 601 阅读 · 0 评论 -
容器相关内容
一、相关函数1、sort函数sort函数的默认排序按照容器内元素的<符号排序,小的元素排在前面vector<int> Vec;sort(Vec.begin(), Vec.end());sort函数的自定义排序自定义针对X类型元素的排序函数cmp,然后使用cmp对包含X元素的容器排序,排序结果使得cmp(前面的元素, 后面的元素)返回truestatic bool cmp(X a, Xb){ ...}vector<X> Vec;sort(Vec.begi原创 2021-06-28 10:48:24 · 124 阅读 · 0 评论 -
回溯算法(六):N皇后问题
51. N 皇后n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。一、解题思路首先我们写一个函数,来判定在某个格子上放置皇后是否合法对于棋盘,按层向下每层放置一个皇后如果能够放到最后,就可以得到一个可行解其实这就是一个回溯问题,只不过路径选择的合法性更复杂一些二、代原创 2021-06-26 13:36:37 · 1119 阅读 · 0 评论 -
回溯问题(四):子集问题
78. 子集给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。子集问题的特点组合问题与分割问题是将递归到最底层的路径作为结果子集问题的特点是需要将递归路上的全部路径作为结果因此,对于子集问题,我们对结果的记录发生在每次递归的最开始,而不是终止条件内2、代码实现class Solution {private: vector<vector<int>> res原创 2021-06-25 22:41:01 · 142 阅读 · 1 评论 -
回溯问题(三):切割问题
131. 分割回文串 给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。回文串 是正着读和反着读都一样的字符串。1、切割问题抽象化因此,切割问题中需要递归传递的也只有一个参数:当前应该从哪里继续切割2、代码实现class Solution { vector<vector<string>> res; vector<string> path; /-----递归函数-----/ v原创 2021-06-25 21:36:10 · 657 阅读 · 0 评论 -
C++基础:字符串
string类型的成员函数对于string s,其具有如下成员函数1、s.substr()成员函数格式:s.substr(int begIndex, int length)成员函数作用:返回一个从字符串s的begIndex下标开始(包括该下标对应的元素),长度为length的字符串注意事项length参数可以省略,当该参数省略或者给定的length超过字符串s的范围时候,函数返回从startIndex到s串尾的拷贝begIndex可以和length参数被一起省略,但不能被单独省略;当一起原创 2021-06-25 20:22:53 · 129 阅读 · 0 评论 -
回溯问题(二):组合和问题及回溯问题的横向去重和纵向去重
组合总和给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。candidates 中的数字可以无限制重复被选取。1、问题抽象与代码实现1)问题抽象2)代码实现class Solution {private: vector<vector<int>> result; vector<int> path; void backtracki..原创 2021-06-25 15:48:03 · 392 阅读 · 1 评论 -
回溯算法(一):组合问题
77.组合给定两个整数 n 和 k,返回 1 … n 中所有可能的 k 个数的组合。这就是个暴力搜索的问题,但是如果k=50,我们就要写50层循环,这是不现实的。回溯算法就是将k层for循环转换成k层递归深度,从而让我们可以把代码写出来。1、问题抽象与代码实现1)将该问题抽象为树形结构:2)代码实现class Solution {private:/-----回溯算法-----/ vector<vector<int>> res; //用于存放总结果 .原创 2021-06-25 13:12:41 · 1288 阅读 · 1 评论 -
回溯算法理论
一、回溯算法理论原创 2021-06-25 10:49:33 · 278 阅读 · 0 评论 -
排序算法:习题篇
剑指 Offer 45. 把数组排成最小的数输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。1、思路此题求拼接起来的最小数字,本质上是一个排序问题。设数组 numsnums 中任意两数字的字符串为 x 和 y ,则规定排序判断规则为:若拼接字符串 x + y > y + x ,则 x “大于” y ;反之,若 x + y < y + x ,则 x “小于” y ;x “小于” y 代表:排序完成后,数组中 x 应在 y 左边;“大于.原创 2021-06-24 23:53:05 · 546 阅读 · 0 评论 -
排序算法(三):时间复杂度O(n)的排序算法
O(n) 级的排序算法存在已久,但他们只能用于特定的场景一、计数排序计数排序限制:举个例子,我们需要对一列数组排序,这个数组中每个元素都是 [1, 9]区间内的整数。那么我们可以构建一个长度为 9 的数组用于计数,计数数组的下标分别对应区间内的 9 个整数。然后遍历待排序的数组,将区间内每个整数出现的次数统计到计数数组中对应下标的位置。最后遍历计数数组,将每个元素输出,输出的次数就是对应位置记录的次数。计数排序限制:数据需要分布在一定的范围内1、算法步骤举个例子,班上有 1010 名同学:他们的原创 2021-06-24 16:38:23 · 6296 阅读 · 0 评论 -
排序算法(二):时间复杂度为O(nlogn)的排序算法
一、希尔排序(实际上很少用到,了解即可)1、算法步骤将待排序数组按照一定的间隔进行排序,如此时排序间隔为gap:则从index=gap处的元素开始排序;对于index = i的元素,每次和当前index - gap处的元素进行比较,直到符合插入条件;然后继续比较index = i++的元素,直到数组末尾,完成当前间隔的排序逐渐缩小间隔进行下一轮排序最后一轮时,取间隔为 1,也就相当于直接使用插入排序。但这时经过前面的「宏观调控」,数组已经基本有序了,所以此时的插入排序只需进行少量交换便可完成原创 2021-06-24 13:06:24 · 9108 阅读 · 1 评论 -
二叉树大杂烩
本文记录二叉树相关题目一、把二叉搜索树转换为累加树538.把二叉搜索树转换为累加树给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。1.1解题思路看起来很乱,其实就是将二叉树对应的升序数组从后到前累加求和如原始数组[2,5,13]累加后的数组就是[20,18,13]因此我们右中左遍历二叉树,然后依次累加就可以了1.2class Solution原创 2021-06-21 21:16:44 · 122 阅读 · 2 评论 -
二叉树(十七):二叉搜索树的节点删除与修剪二叉树
450.删除二叉搜索树中的节点给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。一、二叉搜索树的节点删除方法1、二叉搜索树的节点删除主要有两个过程:找到要删除的节点删除该节点,并调整二叉树的结构2、因此,共有两大类五种情况第一类 没找到要删除的节点 :遍历到空节点仍没有找到,直接返回第二类 找到了要删除的节点,该类共有四种情况:待删除节点左右孩子都为空(叶子节点.原创 2021-06-21 18:47:43 · 1163 阅读 · 0 评论 -
二叉树(十六):二叉搜索树中的插入操作
一、二叉搜索树中的插入操作二叉搜索树中的插入操作给定二叉搜索树(BST)的根节点和要插入树中的值,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果 。插入方法:当不考虑改变树的结构是,只要遍历二叉搜索树,找到空节点,插入元素就可以了1、递归方法一(使用返回值完成父子节点赋值操作)(推荐)注意这里通过递归函数返回值完成父子节点原创 2021-06-21 15:42:10 · 1796 阅读 · 0 评论 -
二叉树(十五):二叉树的最近公共祖先
一、二叉树的最近公共祖先二叉树的最近公共祖先给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”1、解题思路要想解决公共祖先问题,就要从下向上查找,因此我们要使用后序遍历来遍历二叉树。递归三要素:递归函数返回值及参数需要递归函数返回值,来告诉我们是否找到节点q或者p,那么返回值为bool类型就原创 2021-06-21 15:07:47 · 597 阅读 · 0 评论 -
二叉树(十四):二叉搜索树
一、二叉树搜索树理论1、二叉搜索树定义二叉搜索树是一个有序树:若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉搜索树二叉搜索树主要用于加速查找2、二叉搜索树的遍历理论给定二叉搜索树(BST)的根节点和一个值。 你需要在BST中找到节点值等于给定值的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 NULL。二叉搜索树由于已经进行了排序,因此我们可以根据当前节点与目标值的大小原创 2021-06-21 10:27:10 · 207 阅读 · 1 评论 -
提高代码效率的技巧和注意事项
一、递归递归函数的参数最好使用引用传值,使用值传递会明显增加内存占用和运行时间。这是由于值传递会创建新的变量副本,而递归函数在递归过程中这些副本都会压入栈中。原创 2021-06-21 08:18:31 · 103 阅读 · 0 评论 -
二叉树(十一):二叉树递归算法中的返回值问题
一、结论对于二叉树的递归算法:如果算法需要遍历整个二叉树,则递归函数不需要返回值如果算法不需要遍历整个二叉树,则递归函数需要有返回值,在找到符合条件的解的是否及时将解返回回去二、例题说明112 路径总和给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。1、解题思路改题目是找到一条路径就可以,因此递归函数需要返回值,返回值应该是一个bool以指示当前是否找到了满足要求的路径对于该题目,我们使用减法来递归,最开始传入目标数targ原创 2021-06-20 22:08:40 · 1584 阅读 · 0 评论 -
二叉树(十):数左下角和右下角的值
513.找树左下角的值给定一个二叉树,在树的最后一行找到最左边的值。一、迭代法1、思路我们可以层次遍历二叉树,记录每一层最左边的值,当遍历结束后,所记录的就是最后一行最左边的值2、代码class Solution {public: int findBottomLeftValue(TreeNode* root) { int res = root->val; queue<TreeNode*> que; que.push(.原创 2021-06-20 20:42:11 · 164 阅读 · 0 评论 -
二叉树(九):左子叶之和
404、左子叶之和一、递归法1、递归思路递归三要素:递归返回值和参数:返回值为当前节点为根节点的子树的左子叶之和,参数为当前节点单层递归逻辑:如果当前根节点具有一个左子叶,则当前节点左子叶之和 = 左子叶的值 + 右子树的左子叶之和如果当前根节点不具有左子叶,则当前节点左子叶之和 = 左子树的左子叶之和 + 右子树的左子叶之和递归终止条件:如果当前节点为空,则返回02、递归代码class Solution {public: //递归函数返回值和参数 int sumOf.原创 2021-06-20 20:23:43 · 587 阅读 · 0 评论 -
二叉树(八):二叉树的全部路径
一、二叉树的全部路径257、二叉树的全部路径给定一个二叉树,返回所有从根节点到叶子节点的路径。1、递归方法获取二叉树的全部路径(推荐)1)递归方法要获取二叉树的全部路径:我们要使用前序遍历,这样才能获取根->孩子节点的访问顺序。同时要使用回溯算法,在访问一个左孩子后回退到根节点再访问由孩子。其算法可视化如图:递归三要素:递归返回值为空,递归参数为当前节点,用于存储当前节点路径的path,用来存放全部路径的res单层递归逻辑:将当前节点添加到当前节点路径中,并继续递归当原创 2021-06-20 16:10:04 · 2155 阅读 · 0 评论 -
二叉树(七):二叉树的高度与平衡二叉树
一、二叉树的深度与高度1、二叉树的深度对于二叉树中的某个节点,其深度是从根节点到该节点的最长简单路径所包含的节点个数,是从上面向下面数的。因此访问某个节点的深度要使用先序遍历2、二叉树的高度对于二叉树中的某个节点其高度是从叶子节点到该节点的最长简单路径包含的节点个数,是从下面向上面数的。因此访问某个节点的高度需要使用后续遍历3、二叉树的深度与高度辨析每层节点的深度和高度如图所示:4、二叉树的深度与高度的联系一个二叉树根节点的高度就是这个二叉树的最大深度二、二叉树的高度1、递归法递归三原创 2021-06-20 15:01:08 · 3947 阅读 · 0 评论 -
二叉树(六):二叉树的最大深度与最小深度
一、二叉树的最大深度二叉树的最大深度二叉树的最大深度可以通过递归法,层次遍历和深度优先遍历实现,但是最简单最容易的就是递归法。1、递归法1)确定递归三要素递归函数的返回值和参数:返回值为当前节点的最大深度,参数为当前节点递归函数的单层逻辑:当前节点的最大深度 = 1 + 左子树或右子树的最大深度递归函数的终止条件:当前节点为空时,当前节点最大深度为02)递归方法代码class Solution {public: //递归参数及返回值 int maxDepth(Tre原创 2021-06-20 12:04:05 · 8427 阅读 · 1 评论 -
二叉树(五):对称二叉树
101.对称二叉树给定一个二叉树,检查它是否是镜像对称的。一、对称二叉树理论对称二叉树如图所示,要判断一个二叉树是否为对称二叉树,实际上就是要判断根节点的左右两个子树是否镜像对称。因此,其解决方案为:按照对称的方式遍历左右子树,比较同时遍历的节点是否一致。而且在遍历过程中,只有两个子树的根节点对称了,继续比较左右子树是否对称才有意义,因此我们使用"中序遍历"(其实不是严格的中序遍历,只是我们先比较根节点)按照遍历依赖的不同,可以分为以下三类方法:递归法基于队列的迭代法基于栈的迭代法.原创 2021-06-19 23:49:00 · 6530 阅读 · 2 评论 -
二叉树(四)、反转二叉树
一、二叉树翻转理论想要翻转二叉树,要进行以下两个步骤:遍历二叉树每一个节点翻转每一个节点的左右孩子节点,没有左右孩子节点的可以视作其左右孩子节点为nullptr二、二叉树翻转代码翻转二叉树1、前序遍历翻转二叉树class Solution {public: TreeNode* invertTree(TreeNode* root) { if (root == NULL) return root; swap(root->left, roo原创 2021-06-19 22:08:46 · 1135 阅读 · 0 评论