题目链接
开始纠结为什么持有股票的递推公式也要取max,不应该取最小的吗,后来发现,因为卡哥是直接取了负号,那自然原本越小的正数加了负号就会变得更大。
本题最后一定是不持有股票比持有股票的金额要多,因为前面持有股票是一个负数,卖出后加一个正数,一定会更大。
本题每一天有两种状态,持有和不持有。
因为只能买卖一次,所以买之前手头上的钱一定是0。
class Solution {
public:
int maxProfit(vector& prices) {
vector> dp(prices.size(),vector(2));
dp[0][0]=-prices[0];//正常的顺也肯定是先持有再不持有
dp[0][1]=0;
for(int i=1;i
题目链接
本题和上一题唯一的区别在于,买之前手头上的现金不一定是0了,可能是买卖多次所收获的利润,所以递推公式为dp[i][0]=max(dp[i-1][0],dp[i-1][1]-prices[i])。
class Solution {
public:
int maxProfit(vector& prices) {
int len=prices.size();
vector> dp(len,vector(2));
dp[0][0]=-prices[0];
dp[0][1]=0;
for(int i=1;i
题目链接
这题简单多了,因为题目中说了,保证链表中节点的值互不相同,并且不需要free或者delete被删除的节点。
首先在原链表直接删除。
class Solution {
public:
ListNode* deleteNode(ListNode* head, int val) {
if(head!=NULL&&head->val==val){
head=head->next;
}
ListNode* cur=head;//必须从head开始,因为我们要删除的是cur->next
while(cur!=NULL&&cur->next!=NULL){
if(cur->next->val==val){
cur->next=cur->next->next;
}
else{
cur=cur->next;
}
}
return head;
}
};
我们可以设一个虚拟头结点,统一删除操作。
class Solution {
public:
ListNode* deleteNode(ListNode* head, int val) {
ListNode* dummyhead=new ListNode(0);
dummyhead->next=head;//错因,这句话没有写
ListNode* cur=dummyhead;
while(cur->next){//因为我们删除的是cur->next,所以只要cur->next不为空就好了
if(cur->next->val==val){
cur->next=cur->next->next;
}else{
cur=cur->next;
}
}
return dummyhead->next;
}
};
错因:设了虚拟头结点之后没有和原链表连起来。
题目链接
思路:双指针。一个快指针先走k-1步,然后同时移动快慢指针,最后返回满指针即可。
class Solution {
public:
ListNode* getKthFromEnd(ListNode* head, int k) {
ListNode* slow=head;
ListNode* fast=head;
k--;
while(k--){
fast=fast->next;
}
while(fast->next){
slow=slow->next;
fast=fast->next;
}
return slow;
}
};
slow和fast要分开定义,这个还是不太懂。
题目链接
思路:归并排序,新设置一个dummy节点,方便后续操作。本题相当于操作三个链表,自然要优三个指针进行处理,l1,l2就直接移动头指针即可(反正最后要返回的是合并后的新链表),新链表用cur指针进行遍历。
该题的图解思路参考B站视频
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* dummy=new ListNode(0);//实例化
ListNode* cur=dummy;
while(l1&&l2){
if(l1->val<=l2->val){
cur->next=l1;//开始实例化了一个dummy节点,所以不用担心cur为空,不会报空指针异常的错误
l1=l1->next;//移动l1指针,反正最后返回的是dummy->next,改变l1,l2无所谓
}else{
cur->next=l2;
l2=l2->next;
}
cur=cur->next;
}
cur->next=(l1==NULL)?l2:l1;
return dummy->next;
}
};
题目链接
思路:第一种思路是分别计算两个链表的长度,假设差值是a-b,然后让长的链表先多走a-b步,再同时走就能找到公共节点,就不写代码了。
第二种是两个同时走如果第一轮(恰好公共节点之前两个链表的长度相同)没有找到的话,就让A指针指回headB,B指针指回headA,然后再同时走即可,当然不相交的话,也可能A和B同时走到NULL,那最后返回A或B就是NULL,也没问题。
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if(headA==NULL||headB==NULL) return NULL;
ListNode* A=headA;
ListNode* B=headB;//新设两个指针,因为如果第一轮没找到公共节点,还要指回去
while(A!=B){
A=(A==NULL)?headB:A->next;
B=(B==NULL)?headA:B->next;
}
return A;
}
};
注意开始要判断一下,只要有一个为空的话直接返回NULL。
注意三目运算符的使用。