![](https://img-blog.csdnimg.cn/20201014180756738.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
剑指offerc c++
记录学习方法与心得
通信仿真爱好者
phd在读,爱好通信领域相关仿真,包括调制解调,OFDM,MMIMO,信道编码(ldpc,polar,卷积)等,也擅长可见光(VLC),多址接入(NOMA,RSMA),无人机(UAV),智能反射面(RIS)等通信优化问题相关的资源分配算法,如sca,拉格朗日等,也擅长使用强化学习解决通信相关问题。所展示的仿真图均有完整代码一键运行出图
展开
-
华为机试 放苹果
题解:动态规划采用dp[i][j] 表示 i个苹果放入j个盘子的不同分法数。状态转移:我们首先要明确一点,j个苹果放入i个盘中中,总共有下列两种情况:盘子全部放满至少有一个盘子不放(为空)一.当i>j 时,也就是苹果数多于盘子数时。1)考虑盘子全部放满的情况,那么我们可以先每个盘子都放入一个苹果占位置。则剩下dp[i-j][j] 。等价于求解把i-j 个苹果放入j个盘子。2)考虑至少有一个盘子不放的情况,也就相当于求解dp[i][j-1]。由上我们可以得到i>j 时的状.原创 2021-07-17 16:52:17 · 316 阅读 · 2 评论 -
leetcode 两数之和与三数之和
1两数之和注意图中圈出来的特殊情况。思路1:排序后,采用双指针可以轻松求出这两个数的值。但是,题目要求的是满足条件的下标而不是两个数值。故,我们可以复制一下原数组,对新数组排序后,双指针拿到两个目标数字。再去元素组中一一对比获得目标数字在原数组中的下标。class Solution {public: vector<int> twoSum(vector<int>& nums, int target) { vector<int> ne原创 2021-07-17 15:11:21 · 115 阅读 · 0 评论 -
leetcode234 回文链表
解题思路:只要把链表从中间断开,再把其中一个链表反转,就可以依次比较节点值是否相同。1.寻找链表中间节点,可采用快慢指针,快指针是慢指针速度的两倍,那么,当快指针走到尾部时,慢指针走到链表中间。2. 反转其中一个链表,之间做过。class Solution {public: ListNode* reverse_list(ListNode* head) { ListNode* pre = nullptr; ListNode* cur = head;.原创 2021-07-16 21:41:08 · 80 阅读 · 0 评论 -
剑指offer-刷题总结
1.前言 大概过了一两遍剑指offer,思路基本上是复制网上大佬的思想。希望面试的时候能自己默写出来把,现在把剑指offer的题型和结题思路总结一下,便于后序复习和进阶。2.1 链表题剑指offer_T3_从尾到头打印链表_C++思路1:利用栈先入后出的特性,顺序存入,倒序打印思路2:利用两个节点(双指针)原地反转后再打印出来思路3:利用stl的reverse() 函数实现反转后再打印JZ14 链表中倒数最后k个结点思路1:可以直接暴力遍历,如果已知链表的长度,则顺序遍历的长度就已知了思原创 2021-07-16 13:20:03 · 601 阅读 · 0 评论 -
leetcode上关于两道链表反转题的解法
链表题,图解是行之有效的方法。本博客总结迭代法,也就是原地反转。1.反转整个链表如图所示,我们定义两个指针指向该链表。其中一个前驱指针pre初始化为空节点,它的next指针指向head(相当于虚拟了一个头节点)。另外一个当前指针cur初始化为头节点。那么,我们要使得1->2 变为2->1。就是使得 cur->nexrt = pre。但是先这样操作会使得2这个节点丢失了。所以我们要定义一个临时节点temp把2保存下来,也就是`‘ListNode * temp 。操作完之后如下图:原创 2021-07-16 11:36:16 · 277 阅读 · 2 评论 -
leetcode上两道关于回文字符串的题解
这两道题都是关于回文串的题目。之前在语言入门的时候,我们做过 判断一个字符串是否回文,我们知道可以用双指针的方法解法:即左右夹逼,往中间靠拢,找出s[i]!=s[j]则返回false。做了这两道题之后,参考别人的解答,发现除了“左右往中间靠拢”的方法外,还可以使用“中间往两边发散”的方法。如下面两道题题目一解法1 暴力搜索看到题目很直接的思路,遍历搜索出所有字串,依次判断是否为回文串即可。双重循环,外层控制字符串起始位置,内层循环遍历字符串终止位置。class Solution {publ原创 2021-07-15 12:57:12 · 148 阅读 · 0 评论 -
买卖股票的最佳时机 III (最多交易2次)
分析,这里不同于其他几道题,有交易次数的限制。对于任意一天 i,我们有五种可选择的状态,(因为题目限制了买入之前必须卖出)不操作只买入一次买一次,卖一次买一次,卖一次,再买一次买一次,卖一次,再买一次,再卖一次。因此有:1.定义dp数组:下标从0开始dp[i][0] 表示第i天交易完之后 ,不操作的最大利润。dp[i][1] 表示第i天交易完之后 ,只买入一次的最大利润。dp[i][2] 表示第i天交易完之后 ,买一次,卖一次的最大利润。dp[i][3] 表示第i天交易完之后 .原创 2021-07-07 21:43:51 · 617 阅读 · 1 评论 -
714. 买卖股票的最佳时机含手续费
分析,同前几题的分析类似,dp状态定义都相同,只是状态转移的时候略有不同。1.定义dp数组:下标从0开始dp[i][0] 表示第i天交易完之后 ,手里没有股票的最大利润。dp[i][1] 表示第i天交易完之后 ,手里有股票的最大利润。则我们要的结果为:第n-1天交易完后,手里没有股票的最大利润。2.状态转移方程:一:dp[i][0] = max(dp[i-1][0],dp[i-1][1]+price[i]-fee)解释:第i天交易完后,手里没有股票。可能的情况有:第i-1天就没有.原创 2021-07-07 17:29:04 · 83 阅读 · 0 评论 -
309. 最佳买卖股票时机含冷冻期
分析:这题同前题类似,只是加了一个冷冻期为1天。1.dp数组定义dp[i][0] 表示第i天交易完后,有股票的最大收益。dp[i][1] 表示第i天交易完后,没股票,且在冷冻期的最大收益。dp[i][2] 表示第i天交易完后,没股票,不在冷冻期的最大收益。2.状态转移方程dp[i][0] = max(dp[i-1][0],dp[i-1][2]-price[i])分析:dp[i][0] 可能由下面两个状态转移而来:第i-1天仍有股票。第i-1天没有股票,且不在冷冻期,第i天买入了股票.原创 2021-07-05 22:35:19 · 77 阅读 · 0 评论 -
122. 买卖股票的最佳时机 II (可交易多次)
这题和前一题的不同之处在于这里可以多次交易(一次交易是指一次买入和卖出完成)。1.定义dp数组:下标从0开始dp[i][0] 表示第i天交易完之后 ,手里没有股票的最大利润。dp[i][1] 表示第i天交易完之后 ,手里有股票的最大利润。则我们要的结果为:第n-1天交易完后,手里没有股票的最大利润。2.状态转移方程:一:dp[i][0] = max(dp[i-1][0],dp[i-1][1]+price[i])解释:第i天交易完后,手里没有股票。可能的情况有:第i-1天就没有股票,原创 2021-07-05 21:54:19 · 167 阅读 · 0 评论 -
剑指 Offer 63. 股票的最大利润(只交易一次)
定义dp数组:下标从0开始dp[i][0] 表示第i天交易完之后 ,手里没有股票的最大利润。dp[i][1] 表示第i天交易完之后 ,手里有股票的最大利润。则我们要的结果为:第n-1天交易完后,手里没有股票的最大利润。状态转移方程:一:dp[i][0] = max(dp[i-1][0],dp[i-1][1]+price[i])解释:第i天交易完后,手里没有股票。可能的情况有:第i-1天就没有股票,所哟为:dp[i-1][0]第i-1天有股票,但是第i天把它卖了。所以为:dp[i-.原创 2021-07-05 21:36:59 · 93 阅读 · 0 评论 -
2021-07-05
dp数组定义:dp[i] 表示以下标为i结尾的连续子串的最大和那么,我们要求的答案便是所有以i结尾的字串的最大和中,最大的那一个。状态转移:dp[i] = max(dp[i-1]+num[i],num[i])解释:若dp[i-1]<0,那么对dp[i]产生了负面影响,我们不要前面的dp[i-1],只需要当前的num[i]。对应的就是max(dp[i-1]+num[i],num[i]), 即取(dp[i-1]+num[i],num[i])中较大的那一个。初始情况:dp[0] = num.原创 2021-07-05 21:04:02 · 281 阅读 · 0 评论 -
213. 打家劫舍 (环形)
定义dp数组dp[i]表示打劫前 下标为i个房子获得的最高金钱。状态转移方程对房子i,有抢或者不抢两种选择。抢的话,那么说明准备抢这栋房子前,获得的钱数为dp[i-2],抢完后,获得的最高金钱为dp[i-2]+nums[i]。不抢的话,说明此时的获得的最大钱数为dp[i-1]。所以取两种选择的最大值:dp[i] = max(dp[i-2]+nums[i],dp[i-1])。同时:若打劫下标为0的房子,则不能打劫最后一个房子。若打劫最后一个房子,则不能打劫下标为0的房子。求出着两种选择.原创 2021-07-05 16:44:23 · 547 阅读 · 0 评论 -
198. 打家劫舍 (数组)
定义dp数组dp[i]表示打劫前 下标为i个房子获得的最高金钱。状态转移方程对房子i,有抢或者不抢两种选择。抢的话,那么说明准备抢这栋房子前,获得的钱数为dp[i-2],抢完后,获得的最高金钱为dp[i-2]+nums[i]。不抢的话,说明此时的获得的最大钱数为dp[i-1]。所以取两种选择的最大值:dp[i] = max(dp[i-2]+nums[i],dp[i-1])初始化:dp[0] = nums[0]dp[1] = max(nums[0],nums[1]);class Sol.原创 2021-07-05 16:29:25 · 77 阅读 · 0 评论 -
64. 最小路径和(iii)
定义dp数组:dp[i][j]的含义为移动到点i,j的最小路径和。状态转移方程dp[i][j] = min(dp[i-1][j],dp[i][j-1])+array[i][j];即:当前点的最小路径和等于(左边和上边点的路径和的较小的一个)+ 当前点的值。初始化根据状态转移方程,我们需要初始化第0行和第0列。即:dp[i][0] =dp[i-1][0]+array[i][0]; //即第0列第i行的最小路径和等于第0列第i-1行的最小路径和加上当前点的值。另外一个同理。同时,上述初始化需.原创 2021-07-05 16:16:08 · 71 阅读 · 0 评论 -
63. 不同路径 II
定义dp数组:dp[i][j] 表示到达坐标为i,j点时总共有dp[i][j] 条路径。状态转移:因为只能右或者下:dp[i][j] = dp[i-1][j]+dp[i][j-1];即:当前点的路径数=左边点的路径数+上边点的路径数。同时注意障碍物的问题,当 走到障碍物时,dp[i][j]==0;初始化:对dp数组第一行的数据,由于都只能往右走,故 全为1,注意障碍物对dp数组第一列的数据,由于都只能往下走,故全为1,注意障碍物class Solution {public: .原创 2021-07-05 15:57:50 · 59 阅读 · 0 评论 -
62. 不同路径
定义dp数组:dp[i][j] 表示到达坐标为i,j点时总共有dp[i][j] 条路径。状态转移:因为只能右或者下:dp[i][j] = dp[i-1][j]+dp[i][j-1];即:当前点的路径数=左边点的路径数+上边点的路径数。初始化:对dp数组第一行的数据,由于都只能往右走,故 全为1;对dp数组第一列的数据,由于都只能往下走,故全为1.代码如下:class Solution {public: int uniquePaths(int m, int n) { .原创 2021-07-05 15:48:29 · 49 阅读 · 0 评论 -
JZ45 扑克牌顺子
思路1:模拟,统计0的个数和数字之间的差距,比较即可。注意存在元素相等则不对class Solution {public: bool IsContinuous( vector<int> numbers ) { if(numbers.size()!=5) return false; int zero = 0; sort(numbers.begin(),numbers.end()); int t=0;//记录不为0的起点.原创 2021-07-02 16:47:51 · 106 阅读 · 0 评论 -
JZ46 孩子们的游戏(圆圈中最后剩下的数)
思路1:模拟法,按照题目给的过程,模拟整个过程的实现。class Solution {public: int LastRemaining_Solution(int n, int m) { if(n<=0||m<=0) return -1; list<int> lt; for(int i=0;i<n;i++) lt.push_back(i); auto iter = lt.beg.原创 2021-07-02 16:19:53 · 95 阅读 · 0 评论 -
二叉搜索树的后序遍历序列
思路1:循环判断。最右边的是根节点。每次都记录下节点个数先小于再大于最右边节点的个数,若小于size-1.则说明不满足。class Solution {public: bool VerifySquenceOfBST(vector<int> sequence) { if(sequence.size()==0) return false; int size = sequence.size()-1; int i=0; //小.原创 2021-07-02 15:16:17 · 96 阅读 · 0 评论 -
JZ57 二叉树的下一个节点
思路1:先找根节点,再中序遍历存下节点,再找出下一个节点即可。/*struct TreeLinkNode { int val; struct TreeLinkNode *left; struct TreeLinkNode *right; struct TreeLinkNode *next; TreeLinkNode(int x) :val(x), left(NULL), right(NULL), next(NULL) { }};*/.原创 2021-06-30 11:04:32 · 87 阅读 · 0 评论 -
JZ53 表示数值的字符串
本题思路是参考leetcode上的一位大佬的,具体地址找不到了。其思路很清晰,将数值分为底数和指数部分,再分别判断底数和指数即可。class Solution {public: bool isNumeric(string s) { //1、从首尾寻找s中不为空格首尾位置,也就是去除首尾空格 int i=s.find_first_not_of(' '); if(i==string::npos)return false; i.原创 2021-06-30 10:35:04 · 99 阅读 · 0 评论 -
JZ31 整数中1出现的次数(从1到n整数中1出现的次数)
思路1:直接法,遍历每个数。每次循环求整数的1出现的次数(取余后整除得到位数)。class Solution {public: int NumberOf1Between1AndN_Solution(int n) { int count = 0; for(int i=1;i<=n;i++) { int per_num = i; while(per_num!=0) { .原创 2021-06-29 21:48:20 · 83 阅读 · 0 评论 -
JZ11 二进制中1的个数
思路1:利用库函数 bitset 将十进制数转换为二进制数。再将该二进制数转换为字符串遍历即可。class Solution {public: int NumberOf1(int n) { bitset<32> t = n; int count=0; string s1 = t.to_string(); for(int i=0;i<s1.size();i++) { .原创 2021-06-29 20:41:57 · 94 阅读 · 0 评论 -
JZ44 翻转单词序列
思路:这题的思路跟剑指里的另一道很像,我们只要先反转每个单词的,再整体翻转即得到结果。class Solution {public: string ReverseSentence(string str) { vector<int> v_end; for(int i=0;i<str.size();i++) //记录空格的位置 { if(str[i]==' ') v_end.p.原创 2021-06-29 16:53:13 · 135 阅读 · 0 评论 -
JZ43 左旋转字符串
思路1:这个题目的思路,我们可以先旋转前3个字符,再选择后面的字符。最后再旋转所有的字符,即可以得到想要的结果。写的时候注意下标即可。class Solution {public: string LeftRotateString(string str, int n) { swap_str(str,0,n-1); swap_str(str,n,str.size()-1); swap_str(str,0,str.size()-1); .原创 2021-06-29 15:32:35 · 88 阅读 · 0 评论 -
JZ24 二叉树中和为某一值的路径
思路1:回溯法很典型的回溯思路,代码如下/*struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) { }};*/class Solution {public: vector<vector<int>> res; vector<int> p.原创 2021-06-28 22:32:46 · 74 阅读 · 0 评论 -
JZ5 用两个栈实现队列
思路:本题的目的是采用栈的数据结构,实现一个队列。题目给了两个栈s1和s2,push操作直接假定使用s1进行push。那么在pop操作的时候,我们要实现先入先出的性质,直接使用s1来pop是不行的。可以借用s2来进行两个翻转实现先入后出。那么问题来了,假如pop的时候s2是空的,我们则需要先把s1的数据添加到s2中,s2再pop出来。同时,在添加的过程中,要保证s1非空。代码如下:class Solution{public: void push(int node) { s.原创 2021-06-28 21:25:04 · 103 阅读 · 0 评论 -
JZ27字符串的排列
思路:这题与数字的全排列思路一样,只不过解法换成了字符串的,去重等等问题可见这篇文章。回溯法刷题入门总结代码如下:class Solution {public: vector<string> res; string path; vector<string> Permutation(string str) { vector<bool> used(str.size(),false); sort(str.begi.原创 2021-06-28 16:56:07 · 127 阅读 · 0 评论 -
JZ64 滑动窗口的最大值
思路1:遍历,一层循环确定左指针,则右指针为左指针+3。遍历求出最大值即可class Solution {public: vector<int> maxInWindows(const vector<int>& num, unsigned int size) { vector<int> res; if(num.size()==0||size>num.size()||size<=0) return res;.原创 2021-06-28 16:24:02 · 89 阅读 · 0 评论 -
JZ63 数据流中的中位数
思路1暴力求解,根据题目意思排序后输出,注意讨论奇数和偶数个数:class Solution {public: vector<int> v; void Insert(int num) { v.push_back(num); } double GetMedian() { if(v.size()==0) return 0; sort(v.begin(),v.end()); int size =.原创 2021-06-28 16:19:18 · 76 阅读 · 0 评论 -
JZ51 构建乘积数组
思路1:暴力法,双重循环,外层循环确定A数组的每一个元素,内层循环在B中排除A数组中的元素。class Solution {public: vector<int> multiply(const vector<int>& A) { vector<int> res; if(A.size()<=1) return res; for(int i=0;i<A.size();i++)原创 2021-06-28 16:14:25 · 76 阅读 · 0 评论 -
剑指offer-数组中重复的数字
本题为剑指offer中的第三题。题目如下:有三种思路:1.先把该数组a排好序,然后遍历该数组a,一旦存在a[i]==a[i+1],则表示该数字a[i]重复了。2.哈希表3.抽屉原理。抽屉原理很简单,例如有4个苹果放到3个抽屉里面,那么一定会存在某个抽屉里面放进去了两个苹果。在这里,充分利用题目的条件:“长度为n的数组,范围都在0~n-1的范围内”,也就是说,假如不存在重复的数字,那么假如我们对该数组进行排序后,该数组的元素都在正确的位置(下标)上。例如,元素0在下标0处;元素1在下标1处;元原创 2021-06-25 22:16:03 · 99 阅读 · 0 评论 -
JZ42 和为S的两个数字
思路一左右指针滑动,初始化左指针指向起点,右指针指向边界。考录到数组有序,循环中,若二指针指向元素之和sum<target,则左指针右移。若sum>target,则右指针左移。class Solution {public: vector<int> FindNumbersWithSum(vector<int> array,int sum) { vector<int> res; int l=0; in.原创 2021-06-25 22:09:50 · 106 阅读 · 0 评论 -
JZ41 和为S的连续正数序列
思路1暴力穷举,双重循环,外层循环控制左边界,内层循环控制右边界,输出符合条件的结果。class Solution {public: vector<vector<int> > FindContinuousSequence(int sum) { vector<vector<int>> v; if(sum==1||sum==2) return v; for(.原创 2021-06-25 22:03:10 · 85 阅读 · 0 评论 -
JZ40 数组中只出现一次的两个数字
思路1:次数问题用hash表,遍历即可。class Solution {public: vector<int> FindNumsAppearOnce(vector<int>& array) { // write code hereD vector<int> v; unordered_map<int, int> map; for(int i=0;i<array.原创 2021-06-25 21:54:25 · 108 阅读 · 0 评论 -
JZ35 数组中的逆序对
思路1暴力穷举,双重循环,外层循环确定待比较的数,内层循环选择后面的数与待比较的数进行比较,计数器进行对应操作。class Solution {public: int InversePairs(vector<int> data) { long count=0; for(int i=0;i<data.size();i++) { for(int j=i+1;j<data.size();j++) .原创 2021-06-25 21:49:49 · 52 阅读 · 0 评论 -
JZ19 顺时针打印矩阵
题目描述:思路1用visited数组标记元素是否被访问过;class Solution {public: vector<int> printMatrix(vector<vector<int> > matrix) { vector<int> res; if(matrix.empty()) return res; int r = matrix.size(); int c = matr原创 2021-06-25 21:27:52 · 97 阅读 · 0 评论 -
JZ55 链表中环的入口结点
//参考文章//https://blog.csdn.net/weixin_41888257/article/details/103926828//修改的是,x=d+(k-1)s,可见,当k=1时,意味着两个指针第一次相遇,此时x=d,意味着,重置其中一个指针到起点,//当再次相遇,便可求出结果。class Solution {public: ListNode* EntryNodeOfLoop(ListNode* pHead) { if(!pHead||!pHead-原创 2021-06-25 19:01:18 · 112 阅读 · 0 评论 -
JZ66两个链表的第一个公共结点
题目描述:思路1:暴力穷举class Solution {public: ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) { if(!pHead1 || !pHead2) return nullptr; ListNode * p1= pHead1; ListNode * p2= pHead2; while(p1) {原创 2021-06-25 17:36:29 · 110 阅读 · 1 评论