- 博客(75)
- 收藏
- 关注
原创 常见排序实现
假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动。把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列。
2023-10-28 10:40:51 233
原创 二叉树讲解
有一个特殊的结点,称为根结点,根节点没有前驱结点,除根节点外,其余结点被分成M(M>0)个互不相交的集合T1、T2、……学习二叉树结构,最简单的方式就是遍历,所谓二叉树遍历是按照某种特定的规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作一次,访问结点所做的操作依赖于具体的应用问题,遍历是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础。:若一个节点含有子节点,则这个节点称为其子节点的父节点。:一个节点含有的子树的根节点称为该节点的子节点。:一个节点含有的子树的个数称为该节点的度。
2023-10-06 20:54:41 290
原创 栈和队列的概念和实现
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作,进行数据插入和删除操作的一端称为栈顶,另一端称为栈底,栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些,因为数组在尾上插入数据的代价比较小。压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
2023-10-01 10:00:02 351
原创 顺序表和链表
线性表在逻辑上是线性结构,也就说是连续的一条直线,但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储,在数组上完成数据的增删查改。链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。10. 将两个有序链表合并为一个新的有序链表并返回,新链表是通过拼接给定的两个链表的所有结点组成的。9. 输入一个链表,输出该链表中倒数第k个结点。
2023-09-29 08:38:29 243
原创 ZZNUOJ_C语言算法题目(AC代码)
郑州师范学院在线评测系统全新开启。本次网站更新更改了大部分的网站页面布局和结构,旨在给大家带来更好的体验。希望大家可以尝试使用并给出建议或意见。【注意】本OJ在低版本的IE上部分内容不能正常显示,怎么办呢?1. 如果您在学校内机房,请在开机时尽量选择Windows 7操作系统,IE8虽然部分组件不能正常显示但网站框架没有问题。2. 建议您更换新的浏览器浏览本OJ,更多建议可前往第一条给出的旧版OJ地址查看。
2023-09-23 17:45:45 412
原创 程序环境和预处理
FILE//进行编译的源文件LINE//文件当前的行号DATE//文件被编译的日期TIME//文件被编译的时间STDC//如果编译器遵循ANSI C,其值为1,否则未定义1000register//为 register这个关键字,创建一个简短的名字for;;//用更形象的符号来替换一种实现break;case//在写case语句的时候自动把 break写上。// 如果定义的 stuff过长,可以分成几行写,除了最后一行外,每行的后面都加一个反斜杠(续行符)。printf。
2023-09-20 20:17:19 225
原创 自定义类型:结构体,枚举,联合
enum Day//星期Mon,Tues,Wed,Thur,Fri,Sat,Sunenum Sex//性别MALE,FEMALE,SECRETenum Color//颜色RED,GREEN,BLUE联合也是一种特殊的自定义类型这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以联合也叫共用体)
2023-09-15 19:35:41 317
原创 代码随想录第六十天| 84.柱状图中最大的矩形
本题要记录记录每个柱子 左边第一个小于该柱子的下标,而不是左边第一个小于该柱子的高度,所以需要循环查找,也就是下面在寻找的过程中使用了while,详细请看下面注释,整理思路在题解:42. 接雨水中已经介绍了。如果数组本身是降序的,例如 [8,6,4,2],在 8 入栈后,6 开始与8 进行比较,此时我们得到 mid(8),rigt(6),但是得不到 left。如果数组本身就是升序的,例如[2,4,6,8],那么入栈之后 都是单调递减,一直都没有走 情况三 计算结果的哪一步,所以最后输出的就是0了。
2023-09-10 10:00:00 192
原创 代码随想录算法训练营第五十九天| 503.下一个更大元素II,42. 接雨水
首先,如果按照列来计算的话,宽度一定是1了,我们再把每一列的雨水的高度求出来就可以了,可以看出每一列雨水的高度,取决于,该列 左侧最高的柱子和右侧最高的柱子中最矮的那个柱子的高度。因为一旦发现添加的柱子高度大于栈头元素了,此时就出现凹槽了,栈头元素就是凹槽底部的柱子,栈头第二个元素就是凹槽左边的柱子,而添加的元素就是凹槽右边的柱子。此时的栈顶元素st.top(),就是凹槽的左边位置,下标为st.top(),对应的高度为height[st.top()](就是图中的高度2)i < height.size();
2023-09-09 21:57:49 138
原创 代码随想录算法训练营第五十八天 | 739. 每日温度,496.下一个更大元素 I
nums1 中数字 x 的 下一个更大元素 是指 x 在 nums2 中对应位置 右侧 的 第一个 比 x 大的元素,给你两个 没有重复元素 的数组 nums1 和 nums2 ,下标从 0 开始计数,其中nums1 是 nums2 的子集,对于每个 0
2023-09-09 21:36:09 216
原创 代码随想录算法训练营第五十七天 | 647. 回文子串,516.最长回文子序列
如果这矩阵是从上到下,从左到右遍历,那么会用到没有计算过的dp[i + 1][j - 1],也就是根据不确定是不是回文的区间[i+1,j-1],来判断了[i,j]是不是回文,那结果一定是不对的,所以一定要从下到上,从左到右遍历,这样保证dp[i + 1][j - 1]都是经过计算的。那么dp[i][j]一定是取最大的,即:dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);如果s[i]与s[j]相同,那么dp[i][j] = dp[i + 1][j - 1] + 2;
2023-09-06 20:14:31 64
原创 代码随想录算法训练营第五十六天 | 583. 两个字符串的删除操作,72. 编辑距离
那最后当然是取最小值,所以当word1[i - 1] 与 word2[j - 1]不相同的时候,递推公式:dp[i][j] = min({dp[i - 1][j - 1] + 2, dp[i - 1][j] + 1, dp[i][j - 1] + 1});if (word1[i - 1] == word2[j - 1]) 那么说明不用任何编辑,dp[i][j] 就应该是 dp[i - 1][j - 1],即dp[i][j] = dp[i - 1][j - 1];
2023-09-05 21:21:59 77
原创 代码随想录算法训练营第五十五天 | 392.判断子序列,115.不同的子序列
if (s[i - 1] == t[j - 1]),那么dp[i][j] = dp[i - 1][j - 1] + 1;= t[j - 1]),此时相当于t要删除元素,t如果把当前元素t[j - 1]删除,那么dp[i][j] 的数值就是 看s[i - 1]与 t[j - 2]的比较结果了,即:dp[i][j] = dp[i][j - 1];从递推公式可以看出dp[i][j]都是依赖于dp[i - 1][j - 1] 和 dp[i][j - 1],所以dp[0][0]和dp[i][0]是一定要初始化的。
2023-09-04 21:05:59 33
原创 代码随想录算法训练营第五十三天 | 1143.最长公共子序列,1035.不相交的线,53. 最大子序和 动态规划
如果text1[i - 1] 与 text2[j - 1]不相同,那就看看text1[0, i - 2]与text2[0, j - 1]的最长公共子序列 和 text1[0, i - 1]与text2[0, j - 2]的最长公共子序列,取最大的。如果text1[i - 1] 与 text2[j - 1]相同,那么找到了一个公共元素,所以dp[i][j] = dp[i - 1][j - 1] + 1;即:dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
2023-09-02 21:10:30 118
原创 代码随想录算法训练营第五十二天 | 300.最长递增子序列,674. 最长连续递增序列,718. 最长重复子数组
dp[i]表示i之前包括i的以nums[i]结尾的最长递增子序列的长度,为什么一定表示 “以nums[i]结尾的最长递增子序” ,因为我们在 做 递增比较的时候,如果比较 nums[j] 和 nums[i] 的大小,那么两个递增子序列一定分别以nums[j]为结尾 和 nums[i]为结尾, 要不然这个比较就没有意义了,不是尾部元素的比较那么 如何算递增呢。但dp[i][0] 和dp[0][j]要初始值,因为 为了方便递归公式dp[i][j] = dp[i - 1][j - 1] + 1;
2023-09-01 19:04:54 165
原创 代码随想录算法训练营第五十一天 | 309.最佳买卖股票时机含冷冻期,714.买卖股票的最佳时机含手续费
dp[i][1] 表示第i天不持有股票所得最多现金,如果第i天持有股票即dp[i][0], 那么可以由两个状态推出来,第i-1天就持有股票,那么就保持现状,所得现金就是昨天持有股票的所得现金 即:dp[i - 1][0],第i天买入股票,所得现金就是昨天不持有股票的所得现金减去 今天的股票价格 即:dp[i - 1][1] - prices[i],所以:dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]);或者是前一天就是卖出股票状态,一直没操作)
2023-08-31 22:13:16 279
原创 代码随想录算法训练营第五十天 | 123.买卖股票的最佳时机III,188.买卖股票的最佳时机IV
dp[i][j]中 i表示第i天,j为 [0 - 4] 五个状态,dp[i][j]表示第i天状态j所剩最大现金,需要注意:dp[i][1],表示的是第i天,买入股票的状态,并不是说一定要第i天买入股票,这是容易陷入的误区,例如 dp[i][1] ,并不是说 第i天一定买入股票,有可能 第 i-1天 就买入了,那么 dp[i][1] 延续买入股票的这个状态。一定是选最大的,所以 dp[i][1] = max(dp[i-1][0] - prices[i], dp[i - 1][1]);
2023-08-30 18:13:46 170
原创 代码随想录算法训练营第四十九天 | 121. 买卖股票的最佳时机,122.买卖股票的最佳时机II
如果第i天不持有股票即dp[i][1], 也可以由两个状态推出来,第i-1天就不持有股票,那么就保持现状,所得现金就是昨天不持有股票的所得现金 即:dp[i - 1][1],第i天卖出股票,所得现金就是按照今天股票价格卖出后所得现金即:prices[i] + dp[i - 1][0],同样dp[i][1]取最大的,dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]);如果第i天持有股票即dp[i][0], 那么可以由两个状态推出来。
2023-08-29 21:03:45 136
原创 代码随想录算法训练营第四十八天 | 198.打家劫舍,213.打家劫舍II,337.打家劫舍III
如果偷第i房间,那么dp[i] = dp[i - 2] + nums[i] ,即:第i-1房一定是不考虑的,找出 下标i-2(包括i-2)以内的房屋,最多可以偷窃的金额为dp[i-2] 加上第i房间偷到的钱。从dp[i]的定义上来讲,dp[0] 一定是 nums[0],dp[1]就是nums[0]和nums[1]的最大值即:dp[1] = max(nums[0], nums[1]);然后dp[i]取最大值,即dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);
2023-08-29 20:50:33 120
原创 指针(进阶)
根据上面的代码我们发现,其实&arr和arr,虽然值是一样的,但是意义应该不一样的,实际上: &arr 表示的是数组的地址,而不是数组首元素的地址,本例中 &arr 的类型是: int(*)[10] ,是一种数组指针类型,数组的地址+1,跳过整个数组的大小,所以 &arr+1 相对于 &arr 的差值是40。结合,说明p是一个指针变量,然后指着指向的是一个大小为10个整型的数组,所以p是一个指针,指向一个数组,叫数组指针。能够指向浮点型数据的指针。输出的是两个地址,这两个地址是 test 函数的地址。
2023-08-28 22:39:44 169
原创 代码随想录算法训练营第四十六天 | 139.单词拆分
如果确定dp[j] 是true,且 [j, i] 这个区间的子串出现在字典里,那么dp[i]一定是true。从递推公式中可以看出,dp[i] 的状态依靠 dp[j]是否为true,那么dp[0]就是递推的根基,dp[0]一定要为true,否则递推下去后面都都是false了。“apple”, “pen” 是物品,那么我们要求 物品的组合一定是 “apple” + “pen” + “apple” 才能组成 “applepenapple”题目中说是拆分为一个或多个在字典中出现的单词,所以这是完全背包。
2023-08-27 11:28:12 295
原创 代码随想录算法训练营第四十五天 | 70. 爬楼梯 (进阶),322. 零钱兑换,279.完全平方数
本题呢,dp[i]有几种来源,dp[i - 1],dp[i - 2],dp[i - 3] 等等,即:dp[i - j]凑足总额为j - coins[i]的最少个数为dp[j - coins[i]],那么只需要加上一个钱币coins[i]即dp[j - coins[i]] + 1就是dp[j](考虑coins[i])既然递归公式是 dp[i] += dp[i - j],那么dp[0] 一定为1,dp[0]是递归中一切数值的基础所在,如果dp[0]是0的话,其他数值都是0了。
2023-08-25 21:23:47 139
原创 代码随想录算法训练营第四十四天 | 完全背包,518. 零钱兑换 II,377. 组合总和 Ⅳ
01背包中二维dp数组的两个for遍历的先后循序是可以颠倒了,一维dp数组的两个for循环先后循序一定是先遍历物品,再遍历背包容量,在完全背包中,对于一维dp数组来说,其实两个for循环嵌套顺序是无所谓的!如果把遍历nums(物品)放在外循环,遍历target的作为内循环的话,举一个例子:计算dp[4]的时候,结果集只有 {1,3} 这样的集合,不会有{3,1}这样的集合,因为nums遍历放在外层,3只能出现在1后面!首先dp[0]一定要为1,dp[0] = 1是 递归公式的基础。
2023-08-24 16:58:40 121
原创 代码随想录算法训练营第四十三天 | 1049. 最后一块石头的重量 II,494. 目标和,474.一和零
题目链接视频讲解有一堆石头,用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量,每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x
2023-08-23 19:19:13 126
原创 代码随想录算法训练营第四十二天 | 01背包问题,01背包问题(滚动数组),416. 分割等和子集
与其把dp[i - 1]这一层拷贝到dp[i]上,不如只用一个一维数组了,只用dp[j](一维数组,也可以理解是一个滚动数组)这就是滚动数组的由来,需要满足的条件是上一层可以重复利用,直接拷贝到当前层,读到这里估计大家都忘了 dp[i][j]里的i和j表达的是什么了,i是物品,j是背包容量,dp[i][j] 表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少,一定要时刻记住这里i和j的含义,要不然很容易看懵了。(也就是容量为j的背包,放入物品i了之后的价值即:dp[j])
2023-08-22 20:51:06 152
原创 代码随想录算法训练营第四十一天 | 343. 整数拆分,96.不同的二叉搜索树
那有人问了,j怎么就不拆分呢?j是从1开始遍历,拆分j的情况,在遍历j的过程中其实都计算过了。那么从1遍历j,比较(i - j) * j和dp[i - j] * j 取最大的。递推公式:dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));也可以这么理解,j * (i - j) 是单纯的把整数拆分为两个数相乘,而j * dp[i - j]是拆分成两个以及两个以上的个数相乘。
2023-08-21 11:03:02 124
原创 数据在内存中的存储(deeper)
使用这个类型开辟内存空间的大小(大小决定了使用范围)如何看待内存空间的视角(1)整形charshortintsigned intlong(2)浮点型(3)构造类型> 数组类型> 结构体类型 struct> 枚举类型 enum> 联合类型 union(4)指针类型int *pi;char *pc;float* pf;void* pv;(5)空类型void 表示空类型(无类型)通常应用于函数的返回类型、函数的参数、指针类型。
2023-08-19 20:42:44 219
原创 代码随想录算法训练营第三十九天 | 62.不同路径,63. 不同路径 II
本文分别给出了深搜,动规,数论三种方法,深搜当然是超时了,然后在给出动规的方法,依然是使用动规五部曲,这次我们就要考虑如何正确的初始化了,初始化和遍历顺序其实也很重要本题是62.不同路径的障碍版,整体思路大体一致,但就算是做过62.不同路径,在做本题也会有感觉遇到障碍无从下手,其实只要考虑到,遇到障碍dp[i][j]保持0就可以了。
2023-08-19 14:56:24 955
原创 代码随想录算法训练营第三十八天 | 理论基础,509. 斐波那契数,70. 爬楼梯,746. 使用最小花费爬楼梯
视频讲解如果某一问题有很多重叠子问题,使用动态规划是最有效的,所以动态规划中每一个状态一定是由上一个状态推导出来的,这一点就区分于贪心,贪心没有状态推导,而是从局部直接选最优的,例如:有N件物品和一个最多能背重量为W 的背包,第i件物品的重量是weight[i],得到的价值是value[i],每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大,动态规划中dp[j]是由dp[j-weight[i]]推导出来的,然后取max(dp[j], dp[j - weight[i]] + value[i]),但
2023-08-18 15:06:37 716
原创 代码随想录算法训练营第三十七天 | 738.单调递增的数字,968.监控二叉树
本题只要想清楚个例,例如98,一旦出现strNum[i - 1] > strNum[i]的情况(非单调递增),首先想让strNum[i - 1]减一,strNum[i]赋值9,这样这个整数就是89,就可以很自然想到对应的贪心解法了,想到了贪心,还要考虑遍历顺序,只有从后向前遍历才能重复利用上次比较的结果,最后代码实现的时候,也需要一些技巧,例如用一个flag来标记从哪里开始赋值9。
2023-08-17 13:40:18 283
原创 代码随想录算法训练营第三十六天 | 435. 无重叠区间,763.划分字母区间,56. 合并区间
本题其实和452.用最少数量的箭引爆气球非常像,弓箭的数量就相当于是非交叉区间的数量,只要把弓箭那道题目代码里射爆气球的判断条件加个等号(认为[0,1][1,2]不是相邻区间),然后用总区间数减去弓箭数量 就是要移除的区间数量了本题找不出局部最优推出全局最优的过程,就是用最远出现距离模拟了圈字符的行为,但这道题目的思路是很巧妙的,所以有必要做一做,感受一下其实很多区间的合并操作看起来都是常识,其实贪心算法有时候就是常识。
2023-08-16 17:26:02 414
原创 代码随想录算法训练营第三十五天 | 860.柠檬水找零,406.根据身高重建队列,452. 用最少数量的箭引爆气球
分析清楚之后,会发现逻辑其实非常固定关于出现两个维度一起考虑的情况,已经做过两道题目了,另一道就是135. 分发糖果,其技巧都是确定一边然后贪心另一边,两边一起考虑,就会顾此失彼模拟射气球的过程,实时把气球从数组中移走,这么写的话就复杂了,而且寻找重复的气球,寻找重叠气球最小右边界,其实都有代码技巧,贪心题目有时候就是这样,看起来很简单,思路很直接,但是一写代码就感觉贼复杂无从下手。
2023-08-15 15:21:03 161
原创 代码随想录算法训练营第三十四天 | 1005.K次取反后最大化的数组和,134. 加油站 ,135. 分发糖果
如果没有贪心的思考方式(局部最优,全局最优),很容易陷入贪心简单题凭感觉做,贪心难题直接不会做,其实这样就锻炼不了贪心的思考方式了对于第一种贪心方法,就是一种直接从全局选取最优的模拟操作,对于第二种贪心方法,用局部最优可以推出全局最优,进而求得起始位置这在leetcode上是一道困难的题目,其难点就在于贪心的策略,如果在考虑局部的时候想两边兼顾,就会顾此失彼那么本题我采用了两次贪心的策略:一次是从左到右遍历,只比较右边孩子评分比左边大的情况一次是从右到左遍历,只比较左边孩子评分比右边大的情况。
2023-08-14 17:37:44 233
原创 代码随想录算法训练营第三十二天 | 122.买卖股票的最佳时机II,55. 跳跃游戏,45.跳跃游戏II
本题中理解利润拆分是关键点!不要整块的去看,而是把整体利润拆为每天的利润这道题目关键点在于:不用拘泥于每次究竟跳几步,而是看覆盖范围,覆盖范围内一定是可以跳过来的,不用管是怎么跳的以最小的步数增加最大的覆盖范围,直到覆盖范围覆盖了终点,这个范围内最小步数一定可以跳到,不用管具体是怎么跳的,不纠结于一步究竟跳一个单位还是两个单位。
2023-08-12 17:31:37 259
原创 代码随想录算法训练营第三十一天 | 理论基础,455.分发饼干,376. 摆动序列,53. 最大子序和
贪心的本质是选择每一阶段的局部最优,从而达到全局最优想清楚局部最优,想清楚全局最优,感觉局部最优是可以推出全局最优,并想不出反例,那么就试一试贪心也可以用两棵线段树来维护区间的最大值每次更新dp[i][0],则在tree1的nums[i]位置值更新为dp[i][0]每次更新dp[i][1],则在tree2的nums[i]位置值更新为dp[i][1]则 dp 转移方程中就没有必要 j 从 0 遍历到 i-1,可以直接在线段树中查询指定区间的值即可。
2023-08-11 12:43:46 128
原创 代码随想录算法训练营第三十天 | 332.重新安排行程,51. N皇后,37. 解数独
这里我明确给出了棋盘的宽度就是for循环的长度,递归的深度就是棋盘的高度,这样就可以套进回溯法的模板里了解数独可以说是非常难的题目了,如果还一直停留在单层递归的逻辑中,这道题目可以让大家瞬间崩溃,所以在开篇就提到了二维递归,可以帮助大家理解解数独的搜索过程。
2023-08-10 13:39:42 63
原创 代码随想录算法训练营第二十九天 | 491.递增子序列,46.全排列,47.全排列 II
相信大家在本题中处处都能看到是回溯算法:求子集问题(二)的身影,但处处又都是陷阱大家此时可以感受出排列问题的不同:每层都是从0开始搜索而不是startIndex需要used数组记录path里都放了哪些元素了跟上一道题相比多了一步去重的步骤,可以跟之前一样用used数组来去重。
2023-08-09 18:57:10 146
原创 代码随想录算法训练营第二十八天 | 93.复原IP地址,78.子集,90.子集II
在131.分割回文串中我列举的分割字符串的难点,本题都覆盖了,而且本题还需要操作字符串添加逗号作为分隔符,并验证区间的合法性要清楚子集问题和组合问题、分割问题的的区别,子集是收集树形结构中树的所有节点的结果,而组合问题、分割问题是收集树形结构中叶子节点的结果。
2023-08-08 17:28:39 153
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人