算法题专栏
Currybeefer
理想是条不归路,不下战场才能赢
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
Leetcode 148 给链表排序
链表排序这名字就很好记,面试的时候随手就能想到出这一题,然后看你吭哧吭哧写半天,对于他们来说,即不用废自己脑子,又可以折磨你,的确是一种精神上的享受。原创 2023-03-12 13:58:10 · 234 阅读 · 1 评论 -
LeetCode 152 乘积最大子数组,一个奇特的动态规划问题
对于每个dp[i]来说,每次可以做选择,要么选择与dp[i-1]结合,乘积为dp[i-1]*nums[i], 要么就不选择于之前结合,自己另起炉灶,直接等于nums[i]。实际上,这个问题中,我给出的dp定义并不满足动态规划的最优子结构性质,具体来说,[-2,3,-4]中,实际上答案应该是整个数组的相乘才是最大的乘机。我们这里令 Fmax[i]表示到下标为i的元素为止的乘积的极大值,Fmin[i]表示到下标为i的元素为止的乘积的极小值。在这个用例中, 我的算法给出的是3,而真正的答案是24。原创 2023-03-12 13:35:21 · 269 阅读 · 0 评论 -
旋转可重复数组的最小数字
如果你也是使用labuladong的二分模板做的话,可能会有一些疑问,我在注释里写明白了。如果还有疑问,可以查看这里。原创 2022-10-03 01:34:41 · 224 阅读 · 0 评论 -
Leetcode43 字符串相乘以及字符串相加
代码如下,其实就是模拟乘法竖式计算的方法,将单个相乘的结果放入数组,最后数组再做加和处理。原创 2022-09-21 13:04:09 · 309 阅读 · 0 评论 -
从数据流中快速查找中位数
C++中的priority_queue默认是以大根堆存储的,也就是说,堆顶是堆中最大的元素。如果要定义小根堆,那么就得自己写一个仿函数。这题的思路就是维护两个堆,一个大根堆一个小根堆,将数据加入到这两个堆中,这样从两个堆的堆顶就可以获取整个数据的中位数。...原创 2022-07-28 14:27:11 · 394 阅读 · 0 评论 -
LeetCode 239 滑动窗口最大值
题目就是要求我们维护一个滑动窗口,将窗口从头移动到尾,返回每次移动后窗口内的最大值。思路是构造一个单调队列,这个队列是由链表组成(这样好修改)同时队列是递减的。里边保存的是潜在的最大值。时间复杂度:O(n)空间复杂度:O(k) class MonotonicQueue {//这是一个单调递减队列,队列头部为最大的元素 public: list<int> lickedList; void push(int n) { .原创 2022-04-28 11:22:54 · 158 阅读 · 0 评论 -
LeetCode 447. 回旋镖的数量 (排列组合问题)
总的来说就是需要寻找到三个点的组合,i,j,k,其中对于i来说,j和k于i的距离必须相等。暴力枚举法需要三重循环,这样的话时间复杂度是O(n^3)太不划算了。因此我们可以想到排列组合问题,思路就是枚举的时候如果将i点固定,在剩下的点中筛选出距离与i相等的点的集合。假设离i距离为a的点有n个,那么就是从n个里边选出顺序的两个点与i组合,即排列组合问题,An2。用哈希表存储距离为a的组合数量,相加即可。int numberOfBoomerangs(vector<vector<int>.原创 2022-04-21 14:33:38 · 216 阅读 · 0 评论 -
LeetCode 987 垂序遍历二叉树
思路:并没有感觉很难,这题已经给出提示了,所有的二叉树节点都可以用坐标表示。那么我们只需要DFS遍历一遍给所有节点标记对应的坐标并且加入到一个集合里,然后按照某种排序方式输出就好啦 struct node//节点值以及对应的坐标位置 { int val; int x; int y; node(int i_val, int i_x,int i_y):val(i_val),x(i_x),y(i_y){}; }; sta.原创 2022-04-19 01:39:10 · 329 阅读 · 0 评论 -
LeetCode 297 二叉树的序列化和反序列化
二叉树的序列化和反序列化,纯纯的八股文,背住就好了 // Encodes a tree to a single string. string serialize(TreeNode* root) { //空节点用'#'表示 if(root==nullptr) return "#"; string res; queue<TreeNode*> nodeQueue;//构造队列,原创 2022-04-18 05:57:32 · 194 阅读 · 0 评论 -
LeetCode 109. 有序链表转换二叉搜索树
二叉搜索树要求我们根节点的左子树一定小于根节点的值,右子树一定大于跟节点的值。而平衡二叉树要求我们左右两边子树的高度差不超过1。又由于给出的链表已经是排好序的了,所以此时我们只需要寻找到链表的中点,以链表中点为界限,中点左边是二叉搜索树的左孩子们,中点的右边是二叉树的右孩子们,进行递归地构造。这题就解决了。 TreeNode* sortedListToBST(ListNode* head) { if(head==nullptr) return nullptr;原创 2022-04-09 06:37:01 · 604 阅读 · 0 评论 -
leetcode 989. 数组形式的整数加法
思路:这种题目的问题在于,你不能直接将数组转化成数字然后加减。因为测试用例里会有超出long long能表达的数字的数。一个数据结构装不下。因此只能老老实实各个数相加,算进位来做。代码不难,背住就好。vector<int> addToArrayForm(vector<int>& num, int k) { vector<int> res; int n = num.size(); //倒着遍历 .原创 2022-04-04 13:38:27 · 764 阅读 · 0 评论 -
leetcode 394题,字符串解码
思路:使用dfs递归,将字符串分解成字母序列+数字*[字母序列]的形式进行递归求解。括弧里边的都需要放入递归里。具体请看代码string decodeString(string s) { int index=0; return dfs(s, index); } string dfs(string& s, int& index) { string res; while (index <原创 2022-04-04 10:57:40 · 538 阅读 · 0 评论 -
字符串匹配算法,实现strStr()
这一题比较简单,就是返回haystack中第一次遇到needle字符串的位置。但是要快速写出比较清爽的代码会有点难,记录于此以备参考 int strStr(string haystack, string needle) { if(needle.size()==0) return 0; int j=0,flag,i; for(i=0;i<haystack.size();i++) { if(haystack[i]==needle[0]).原创 2022-04-01 05:36:31 · 220 阅读 · 0 评论 -
Leetcode 46题 求全排列
class Solution {public: vector<vector<int>> res;//用于存放返回结果 vector<int> track;//用于存放当前遍历的树 vector<vector<int>> permute(vector<int>& nums) { BackTrack(nums); return res; } voi.原创 2022-03-07 02:11:16 · 289 阅读 · 0 评论 -
C++实现一个包含括号匹配的计算器
这只是先记录一下,后续会完善计算题功能以及添加注释int Caculator(string s){ stack<int> stk; int num = 0; int sign = '+'; for (int i = 0; i < s.size(); i++) { char c = s[i]; if (isdigit(c)) { num = num * 10 + (c - '0原创 2022-02-08 12:18:59 · 1769 阅读 · 0 评论 -
Two Sum, Three Sum, Four Sum 问题的解法
Two Sum问题先来看Two Sum问题有许多种做法,我第一个想到的是用哈希表来做,在C++里也就是unordered_map,用它来存贮nums中的元素以及对应的下标。然后在遇到新的元素的时候进行查找时候存在index[ target-nums[i]]这个键,如果存在就找到了需要的元素。 vector<int> twoSum(vector<int>& nums, int target) { vector<int> ans;.原创 2022-02-05 12:19:14 · 1541 阅读 · 0 评论 -
快速幂的运算
快速幂运算代码。有点绕,建议多看几遍理解int poww (int a, int b) { int base = a, ans = 1; while (b) { if (b & 1) ans *= base; base *= base; b >>= 1; } return ans;}运用此算法可以解决leetcode50题:这里的测试用例会输入负数和一些奇奇怪怪的边角料数字,对于负数很好办,只需要原创 2022-02-03 14:56:56 · 708 阅读 · 0 评论 -
最长回文子串
class Solution {public: string longestPalindrome(string s) { string ret=""; for(int i=0;i<s.size();i++) { //分别找出以i为中心,以及以i+1为中心的回文数 string a=Palidrome(s,i,i); string b=Palidrome(s,i,.原创 2022-02-01 07:12:14 · 479 阅读 · 0 评论 -
01背包问题
背包问题老是做了忘忘了做,索性这次分析记录下来一个可装载重量为W的背包和N个物品,每个物品有重量和价值两个属性。其中第i个物品的重量为wt[i],价值为val[i],现在让你用这个背包装物品,最多能装的价值是多少?例: N = 3, W = 4 wt = [2, 1, 3] val = [4, 2, 3]Output:6明确状态:背包容量,可选择物品定义dp[i][j]: dp[i][j]表述,对于前i个物品,当前背包的容量为j,这种情况下可以装的最大价值是dp[i][j]Base Case原创 2022-01-16 11:31:48 · 353 阅读 · 0 评论 -
01背包问题变体:TargetSum
这道题是01背包问题的变体,我们稍微转换一下思路。假设num[]数组中所有的要加上+变为正数的数字和我们用Sum(P1)表示,num[]数组中所有要加上-变为负数的数组和我们用Sum(P2)表示,则题目要求我们:Sum(P1)+Sum(P2)=target稍微变形一下:2Sum(P1)=target+Sum(P1)+Sum(P2) Sum(P1)=(target+Sum)/2那么我们就可以转换这个题目为背包问题:给你一个数组num[],让你从中选择几个数组,使得他们的和为(targe.原创 2022-01-16 11:20:18 · 688 阅读 · 0 评论 -
LRU算法的实现
参考文章class Node{public: int key; int val; Node* next; Node* prev; Node(int i_key, int i_val) { key=i_key; val=i_val; }};class DoubleList{public: Node* head; Node* tail; int size; .原创 2021-09-27 11:14:12 · 550 阅读 · 0 评论 -
【双指针】【数组】【链表】从已排序的数组(链表)中去重
解题思路:首先可以发现:这个是排好序的数组,那么可以发现,所有的重复元素都是紧挨着的。数组和链表的题目首先要想到双指针法,在这里就可以用双指针法中的快慢指针解决问题。开始的时候,slow指针和fast指针的相隔距离为1,快指针在前边探路,慢指针在后边负责替换。如果快指针发现了不同的数字,令慢指针前进1个单位,同时nums[slow]=nums[fast],然后快指针前进一个单位;如果快指针发现重复的数字,就单纯自增1前进一个单位。通过这种方法,慢指针的所过之处,所有的元素都被替换为不重复的,形成.原创 2020-12-20 11:00:24 · 227 阅读 · 1 评论 -
【单链表】用递归和循环两种方法来反转单链表
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */class Solution {public: ListNode* reverseList(ListNode* head) { //这里输入数据会有空的,所以返原创 2020-12-13 16:16:21 · 471 阅读 · 0 评论 -
【二叉树】求普通二叉树,满二叉树,完全二叉树的节点个数
求普通二叉树的节点个数,只需要遍历一遍即可:int NodeCount(TreeNode* root){ if(root==nullptr) { return 0; } return 1+NodeCount(root->left)+Node(root->right);}求满二叉树的节点个数,可以根据满二叉树的性质:节点个数等于2^N-1,其中N为这棵满二叉树的高度。因此随便挑一个方向往下遍历即可int NodeCount(TreeNode* root){ int he原创 2020-12-12 16:35:31 · 1035 阅读 · 1 评论 -
【程序员面试宝典】检查有向图中两点是否存在路径相连
思路: 这个题目考察的其实是有向图的遍历,图的遍历分为深度优先遍历和广度优先遍历,深度优先遍历用堆栈实现,广度优先遍历用队列实现,在该题目中给出了每个节点的子节点,所以最好用广度优先遍历。图的广度优先遍历和树的层次遍历类似,但是不是完全相同,因为图是连通的,所以我们必须去标志那个节点被访问过,那个节点没有被访问过,最后如果全部访问完以后,还没有找到a到b的路径,则返回false。注意:(1)图中有环,记得标记是否被访问(2)要分别检测两个方向(a->b,b->a)/*struct .转载 2020-11-28 20:52:36 · 1339 阅读 · 2 评论 -
【程序员面试宝典】实现一个集合栈
解析:刚开始没有反应过来题目是什么意思,仔细读了读才梳理出来:输入的参数中ope是一个二维Vector数组,其中第二维度(也就是列)被限制为只有两个元素。例如ope[2][0]和ope[2][1]:当ope[2][0]=1时,表示要入栈,ope[2][1]的值就是要插入的值。当ope[]2[0]=2时,表示要出栈,此时ope[2][1]的值为空。size为集合栈中每个栈的容量class SetOfStacks {public: vector<vector<int> &.原创 2020-11-18 23:32:38 · 171 阅读 · 0 评论 -
【程序员面试宝典】判断是否为翻转子串
解法比较简单,就是把字符串s1进行左移(右移也行),每移动一次就进行判断一次,如果相等就返回trueclass ReverseEqual {public: bool checkReverseEqual(string s1, string s2) { if(s1.size()!=s2.size()) { return false; } for(int i=0;i<s1.size();++i) .原创 2020-10-11 14:54:00 · 174 阅读 · 0 评论 -
【程序员面试宝典】矩阵顺时针旋转90°
思路:第一步:交换第i行到第n-i-1行第二步:先将矩阵以主对角线互换 (如果是逆时针则为主对角线) vector<vector<int> > transformImage(vector<vector<int> > mat, int n) { for(int i=0;i!=n/2;++i) { for(int j=0;j!=n;++j) { .原创 2020-10-09 22:55:43 · 350 阅读 · 0 评论 -
【程序员面试宝典】字符串压缩
思路:就是在for循环中遍历字符串,如果有重复的字符则进入while循环,同时int temp计数,最后加上。class Zipper {public: string zipString(string iniString) { string ret; for(int i=0;i<=iniString.length();++i) { ret+=iniString[i]; int temp.原创 2020-10-08 18:51:49 · 171 阅读 · 0 评论 -
【程序员面试宝典】确定两串乱序同构
题目不难,构建两个map进行遍历查询就好class Same {public: bool checkSam(string stringA, string stringB) { if(stringA.length()!=stringB.length()) { return false; } map<char,int> mapA; map<char,int> m.原创 2020-10-08 18:23:41 · 199 阅读 · 0 评论 -
判定字符串是否只需要一次(或者零次)编辑问题
这题自己想的过于复杂,其实用双指针分别从字符串的头尾遍历就可以了。以下是来自LeetCode题解:分别从两个字符串的两边向中间匹配,一旦不一样就停止,这时剩下的first[i,j]first[i,j]和second[i,k]second[i,k]如果长度均小于等于1(注意临界条件)则结果为True,否则False。时间复杂度:O(n)O(n)空间复杂度:O(1)O(1)public bool OneEditAway(string first, string second) { .转载 2020-08-10 11:35:41 · 325 阅读 · 0 评论 -
已知前序中序重建二叉树的代码实现
解题思路:首先确立使用递归的思路做题,每次递归构造一个节点。传入的数组中前序数组pre的第一个元素就是根节点,将这个根节点的值赋给root,然后在中序数组tin中寻找这个元素。这个元素将tin数组分为两半,前半部分是左子树的节点们,后半部分是右子树的节点们将tin按上述分法分为两个数组,同时pre数组也要照着这个思路分为左右子树两个子数组,然后递归求解,代码如下public TreeNode reConstructBinaryTree(int[] pre, int[] tin) { .原创 2020-07-27 14:56:34 · 312 阅读 · 0 评论 -
用快慢指针法求链表倒数第K个节点
解题思路:用快慢两个指针来解,这两个指针的位置相差k-1个距离,当快指针走到最后一个节点的时候,慢指针指向的位置就是我们要的倒数第k个节点了。思想就是这么简单了,很多链表类的题目都是活用指针就可以解决的,一个指针不可以的时候就两个指针来完成。 public ListNode FindKthToTail(ListNode head, int k) { if(k <= 0) return null; ListNode low = hea.原创 2020-07-25 11:46:44 · 320 阅读 · 0 评论 -
求二进制中1的个数问题
我的思路是将数字转为二进制后再转化为字符串,然后统计1的个数就可以了。但是我在题解中看见一个更好的方法,遂搬运如下:如果一个整数不为0,那么这个整数至少有一位是1。如果我们把这个整数减1,那么原来处在整数最右边的1就会变为0,原来在1后面的所有的0都会变成1(如果最右边的1后面还有0的话)。其余所有位将不会受到影响。举个例子:一个二进制数1100,从右边数起第三位是处于最右边的一个1。减去1后,第三位变成0,它后面的两位0变成了1,而前面的1保持不变,因此得到的结果是1011.我们发现减1的结果是把.原创 2020-07-25 11:45:06 · 226 阅读 · 0 评论 -
判断是否是栈的弹出序列
解题思路:题目问出栈的顺序,那我们就直接创建一个栈,试一试顺序就行具体思路是:先把pushV[0]压栈,然后遍历popV的序列,如果当前popV的元素和栈顶元素相同,就出栈,然后遍历下一个;否则就将pushV的其他元素压入栈。若pushV都入栈了但popV和栈顶元素仍然不匹配,那么返回false。若能成功遍历到底,就返回true public bool IsPopOrder(int[] pushV, int[] popV) { Stack<int> stac.原创 2020-07-24 09:13:50 · 407 阅读 · 0 评论 -
判断是否是二叉树的后序遍历
解题思路: 后序遍历的树节点都有这么一种规律:最后一个节点为头节点,剩下的节点会分为连续的两部分,一部分都比节点大(右子树),另一部分都比节点小(左子树)那么先取出根节点,然后倒叙遍历整个序列,如果经历了“一部分序列比根节点大”,“另一部分比节点小”那么比较成功,继续递归地比较,否则比较失败,返回falsepublic bool VerifySquenceOfBST(int[] sequence) { if(sequence.Length==0)//这个是应付用例测试用的 .原创 2020-07-23 22:54:26 · 415 阅读 · 0 评论 -
使用递归法求字符串的全排列问题
这题的题解理解起来够呛的…我看了半天才看懂。这题需要反复复习,反复回顾,不然可能今天看懂了,明天又忘了…先搬运牛客的官方题解:如图所示的全排列可以发现,链接:https://www.nowcoder.com/questionTerminal/fe6b651b66ae47d7acce78ffdd9a96c7?answerType=1&f=discussion来源:牛客网对于这个排列,我们是固定A不动,然后交换B与C,从而得到"ABC" 和 “ACB”同理,对于"BAC"、“BCA” .原创 2020-07-21 23:21:21 · 658 阅读 · 0 评论 -
用动态规划求解丑数问题
解题思路:依照题意,丑数也就是因子只含有2、3、5的数。如何获取丑数?我们可以从已有的丑数上进行拓展获取。也就是在已经有的数字的基础上乘2或乘3或乘5就能获取到一个新的丑数。我们所已知的丑数有1,2,3,5那么解题方法就是: **在已有的丑数的基础上进行*2,3,5,所得到的结果中最小的那个数字就是下一个丑数。如果还是感觉云里雾里,那么结合代码看看应该就清楚我所说的意思了:using System;class Solution{ public int GetUglyNumber_S.原创 2020-07-20 22:50:51 · 256 阅读 · 0 评论 -
用归并排序解决数组逆序对问题
吐槽一下这个题目,题目说的好歹清楚一些啊,我看半天以为是相邻的两个数字算是逆序对,写了半天没给我过,看题解才知道是什么意思。还有,这个%1000000007是什么鬼啊???为什么要弄个这种东西。言归正传,这道题用到了归并排序的思想,其实暴力法也行,但是会提示超时。解题思路就是按照归并排序的思想,在归并左右两个数组的时候进行计数操作由于归并left和right的时候已经默认排好序了,所以一旦出现left[i]>right[j]的情况,则left[i]后边的数(比如left[i+1],left[i.原创 2020-07-20 19:09:23 · 338 阅读 · 0 评论 -
用双指针法求解两个链表的公共节点问题
自己反正没有解出来,但是看了题解才知道怎么做。解析如下:先举个例子:如图是两个链表,为方便说明我将最后那个空节点也列出来:A链表:4-1-8-4-5-nullB链表:5-0-1-8-4-5-null双指针法想要做到的事情是:让两个指针从两个链表的头部出发以相同的速度开始遍历链表,他们相遇的第一个节点,就是我们要求的公共节点。那么问题来了:如果让两个指针p1,p2从各自链表的头部开始以相同的速度开始遍历,两个指针是不会遇见的。因为在共同的节点之前的路程长度是不同的。那么我们该怎么做呢?那就.原创 2020-07-18 20:38:35 · 350 阅读 · 0 评论
分享