leetcode no.2 两数相加
- 题目内容为求两个逆序链表的和(首位是个位数,越大越往后)
- 直接加就可以,留一个存进位的
- 只要l1,l2,tempnum里面有一个不是空,就要再存进去一个数字
- 记得执行完以后->next
- 有可能存在0,所以 每轮的tempnum%10即使是0也要存的
- 如果已在struct里面给出了构造,那么ListNode*temp=new ListNode就不行了,就得ListNode*temp=new ListNode(0);
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { ListNode*ans=new ListNode(0); ListNode*anstemp=new ListNode(0); anstemp=ans; int tempnum=0; while(l1!=NULL || l2!=NULL||tempnum) { if(l1) { tempnum+=l1->val; l1=l1->next; } if(l2) { tempnum+=l2->val; l2=l2->next; } ListNode*tempnode=new ListNode(tempnum%10); anstemp->next=tempnode; tempnum=tempnum/10; anstemp=anstemp->next; } return ans->next; } };
leetcode no.19 删除链表的倒数第N个节点
- 给好的是头就有数据的链表,因此pre->next=head这样比较合适
- 特判遇到删除头节点的情况
- 在找完数字然后找的过程,因为node的起始点进循环就node->next,所以temp=num-n+1以后还要-1(序列五个数字,倒数第二个,正数4,但是只在循环走三次)
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* removeNthFromEnd(ListNode* head, int n) { if(head->next==NULL) return NULL; ListNode*tail=new ListNode(0); ListNode*pre=new ListNode(0); tail=head; int num=0; while(tail->next!=NULL) { num++; tail=tail->next; } num++; ListNode*node=new ListNode(0); node=head; pre->next=head; if(n==num) return head->next; int temp=num+1-n; for(int i=1;i<=temp-1;i++) { node=node->next; pre=pre->next; } pre->next=node->next; delete node; return head; } };
leetcode no.19 更优秀的做法
- 一轮遍历,使用两个指针,两个指针中间隔着n-2个数,即end先走n-1次,之后两个同步移动直至end走到尾巴上
- 注意删除是head的情况
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* removeNthFromEnd(ListNode* head, int n) { ListNode*first=new ListNode(0); ListNode*end=new ListNode(0); first=head; end=head; ListNode*pre=new ListNode(0); pre->next=head; int num=1; while(num<=n-1) { num++; end=end->next; } if(end->next==NULL) return head->next; while(end->next!=NULL) { first=first->next; end=end->next; pre=pre->next; } pre->next=first->next; delete first; return head; } };
leetcode no.23 合并k个排序链表
- 注意特判整个vector空的情况
- 里面每个链表都走到尽头退出循环
- 注意!所有涉及到链表的题目一定要一个ans存结果。一个temp不断temp->next
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* mergeKLists(vector<ListNode*>& lists) { ListNode*ans=new ListNode(0); ListNode*temp=new ListNode(0); if(lists.empty()) return ans->next; temp=ans; int minnum=10000; int mindown=-1; bool notempty=true; while(notempty) { notempty=false; mindown=-1; minnum=10000; for(int i=0;i<=lists.size()-1;i++) { if(lists[i]!=NULL) { notempty=true; if(lists[i]->val<minnum) { minnum=lists[i]->val; mindown=i; } } } if(!notempty) break; temp->next=new ListNode(lists[mindown]->val); temp=temp->next; lists[mindown]=lists[mindown]->next; } return ans->next; } };
leetcode no.23合并k个排序链表
- 可以采用分治的方法,每次计算两个链表,步长每次扩大而
- 注意空的情况,这时候访问lists[0]也是违规的
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode*merge(ListNode*l1,ListNode*l2) { if(l1==NULL) return l2; if(l2==NULL) return l1; ListNode*ans=new ListNode(0); ListNode*temp=new ListNode(0); temp=ans; while(l1 && l2) { if(l1->val<=l2->val) { ListNode*p=new ListNode(l1->val); l1=l1->next; temp->next=p; temp=temp->next; } else { ListNode*p=new ListNode(l2->val); l2=l2->next; temp->next=p; temp=temp->next; } } if(l1) temp->next=l1; if(l2) temp->next=l2; return ans->next; } ListNode* mergeKLists(vector<ListNode*>& lists) { if(lists.empty()==true) return NULL; for(int step=1;step<=lists.size();step=step*2) { for(int i=0;i<=lists.size()-1;i=i+step) { if(i+step<=lists.size()-1) lists[i]=merge(lists[i],lists[i+step]); } } return lists[0]; } };
leetcode no.24两两交换链表中的节点
- 如果只有一个或者为空直接返回
- 前面两个节点的交换要拉出来,因为head发生变化要存储返回值
- 后面的节点要存好pre是交换前的最后一个点,head代表当前要交换的第一个点
- pre->next=head->next head->next=pre->next->next pre->next->next=head 保持原则,一个被用完了以后立即修改
- 前两个点里面:newhead=head->next head->next=newhead->next newhead->next=head newhead成为新的起点。
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* swapPairs(ListNode* head) { if(head==NULL||head->next==NULL) return head; ListNode*newHead=new ListNode(0); newHead=head->next; head->next=newHead->next; newHead->next=head; ListNode*temp=new ListNode(0); temp=head; while(temp->next!=NULL && temp->next->next!=NULL) { head=temp->next; temp->next=head->next; head->next=temp->next->next; temp->next->next=head; temp=head; } return newHead; } };
leetcode no.25 K个一组翻转链表(修改指针指向的方法)
- 注意如果刚好有k个,是需要反转的,即使后面没有了
- count和nownode每次是对应的。指向这组的第几个点count就是几
- prev标记的是k个一组这个组前一个点,nownode在next以后是k个一组的下一个点,中间的就是k个区间
- 中间的每次修改next的指向
- k个找到以后,执行k-1轮,因为最后一轮需要和prev单独标记,此时的cur指向k个一组的原来的最后一个点
- 如果是第一组,那么需要修改head为cur的值
- 不是第一组,那么prev->next=就是最后cur
- 这组中第一个点的next是newnode
- 新一轮的prev是这一组原始的第一个点,是需要标记好的,新一轮的cur就是nownode
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* reverseKGroup(ListNode* head, int k) { ListNode*cur=new ListNode(0); ListNode*pre=new ListNode(0); ListNode*next=new ListNode(0); ListNode*nownode=new ListNode(0); ListNode*prev=new ListNode(0); ListNode*temp=new ListNode(0); bool pd=true; int count=1; cur=head; nownode=head; prev=NULL; while(nownode!=NULL) { if(count==k) { nownode=nownode->next; if(cur==head) pd=true; pre=nownode; temp=cur; for(int i=1;i<k;i++) { next=cur->next; cur->next=pre; pre=cur; cur=next; } if(pd) { head=cur; pd=false; } if(prev!=NULL) prev->next=cur; prev=temp; //temp=cur->next; cur->next=pre; cur=nownode; count=1; } else { count++; nownode=nownode->next; } } return head; } };
leetcode no.61 旋转链表
- 链表后移k个单位,如果k大于len就取余
- 双指针移动,对应temp2就是尾节点,next接原始头
- temp1是倒数第k个点,是新的head
- pre是新的尾节点
- 注意k等于0的时候,不需要转动,这样必须直接返回,不能进到下面,不然pre会有问题。
- 需要修改的点是,修改以后选temp1为新的head,原来的尾节点temp2加next是原来的head,新的head前面最后一个点pre的next成NULL。
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* rotateRight(ListNode* head, int k) { if(head==NULL) return head; ListNode*temp1=new ListNode(0); ListNode*temp2=new ListNode(0); temp1=head;temp2=head; int len=0; while(temp1!=NULL) { len++; temp1=temp1->next; } k=k%len; if(k==0) return head; for(int i=1;i<=k-1;i++) temp2=temp2->next; ListNode*pre=new ListNode(0); pre->next=head; temp1=head; while(temp2->next!=NULL) { pre=pre->next; temp1=temp1->next; temp2=temp2->next; } temp2->next=head; pre->next=NULL; return temp1; } };