目录
新建链表的一个大坑:
这样可以新建!
w->next=new ListNode(1);
w=w->next;
这样写就是新建不了,可能是要先指定连接再新建?反正就是有毒佛了……
w=new ListNode(1);
w=w->next;
就算写成这样也不行,佛了:
ListNode* temp = new ListNode(1);
w->next = temp;
w = w->next;
新建链表类型题目的套路:
这一类满满的套路,对指针的理解要求比较深入,如果不没总结过套路的话,肯定一脸懵逼……
- 首先new一个头指针 ListNode* head = newListNode(0);
- 然后定义一个当前结点,并指向头指针 ListNode* cur = head;
- 接下来对cur结点进行操作;
- 每次一顿操作完之后记得将 cur = cur->next,链表前进,否则最后得到的答案只有一个结点!
- 最后因为当前结点是指向head的指针,所以最后返回的是 head->next 才是想要的答案!返回cur或者head都是错误的!
LeetCode21.合并两个有序链表
直接套上面总结的模板就可以,归并解法,很简单!
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* head = new ListNode(0);//新建一个头结点操作
ListNode* cur = head;//定义一个当前节点指向head头结点方便操作
while(l1!=NULL&&l2!=NULL){
if(l1->val>=l2->val){
cur->next = l2;//直接将整个next指针赋值,单单赋值val肯定不行的
l2 = l2->next;
}else{
cur->next = l1;
l1 = l1->next;
}
//记得加上这一句将链表前后连接起来!否则最后一顿操作后只剩最后一个结点!
cur = cur->next;
}
cur->next = l1?l1:l2;//如果l1或者l2为空,将非空的链表接上去
return head;//因为前面复制赋值是指针操作,所以这个地方head结点没有操作已经连接cur
}
};
其实还能够用递归解法来求解,速度上会快一些
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
//递归解法
if(!l1)
return l2;
if(!l2)
return l1;
if(l1->val<l2->val){
l1->next = mergeTwoLists(l1->next,l2);
return l1;
}else{
l2->next = mergeTwoLists(l1,l2->next);
return l2;
}
}
};
LeetCode19.删除链表的倒数第N个数
- 典型的一道快慢指针问题
- 怎样操作链表删除的方法一定要学会,一定是利用指针间接操作;
- 一定要想清楚直接操作为什么不行!
/**
* 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==NULL||head->next==NULL)
return NULL;
ListNode* node = new ListNode(0);//新建一个头结点
node = head;
ListNode* slow,*fast;//快慢指针
slow = fast = head;
for(int i=0;i<n;i++)
fast = fast->next;
if(!fast)//n等于链表长度时
return head->next;
while(fast->next!=NULL){
slow = slow->next;
fast = fast->next;
}
//因为前面slow是指针操作,所以这里对slow进行操作就能操作head
slow->next = slow->next->next;//删除结点,其实是“跳过”了这个结点;没有释放内存!
return head;
}
};
LeetCode2.两数相加
这道题真是不容易啊不容易,看一下我悲惨的提交记录:
一开始没有补齐的思路:
/**
* 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){
//不把两个链表补成同样长会出现:[8,9,9] [2]这种情况不好处理的!
if(l1==nullptr)
return l2;
if(l2==nullptr)
return l1;
int len1 = getdeep(l1);
int len2 = getdeep(l2);
bool flag = false;
ListNode* pre;//定义前结点的重要性!
if(len1>=len2){
ListNode* head = l1;
while(l2!=nullptr){
l1->val = l1->val+l2->val;
if(flag){
l1->val++;
flag = false;
}
if(l1->val>=10){
flag = true;
l1->val%=10;
}
pre = l1;
l1 = l1->next;
l2 = l2->next;
}
if(flag){
if(l1!=nullptr){
l1->val++;
if(l1->val>=10){
l1->val%=10;
l1->next = new ListNode(1);
}
}
else
pre->next = new ListNode(1);
}
return head;
}
ListNode* head = l2;
while(l1!=nullptr){
l2->val = l1->val+l2->val;
if(flag){
l2->val++;
flag = false;
}
if(l2->val>=10){
flag = true;
l2->val%=10;
}
pre = l2;
l1 = l1->next;
l2 = l2->next;
}
if(flag){
if(l2!=nullptr){
l2->val++;
if(l2->val>=10){
l2->val%=10;
l2->next = new ListNode(1);
}
}
else
pre->next = new ListNode(1);
}
return head;
}
int getdeep(ListNode* head){
int num = 0;
while(head!=nullptr){
num++;
head = head->next;
}
return num;
}
};
一定要补齐!!!啊啊啊我佛了
/**
* 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) {
int len1=1;//记录l1的长度
int len2=1;//记录l2的长度
ListNode* p=l1;
ListNode* q=l2;
while(p->next!=NULL)//获取l1的长度
{
len1++;
p=p->next;
}
while(q->next!=NULL)//获取l2的长度
{
len2++;
q=q->next;
}
if(len1>len2)//l1较长,在l2末尾补零
{
for(int i=1;i<=len1-len2;i++)
{
q->next=new ListNode(0);
q=q->next;
}
}
else//l2较长,在l1末尾补零
{
for(int i=1;i<=len2-len1;i++)
{
p->next=new ListNode(0);
p=p->next;
}
}
p=l1;
q=l2;
bool count=false;//记录进位
ListNode* l3=new ListNode(-1);//存放结果的链表
ListNode* w=l3;//l3的移动指针
int i=0;//记录相加结果
while(p!=NULL&&q!=NULL)
{
i=count+p->val+q->val;
w->next=new ListNode(i%10);
count=i>=10?true:false;
w=w->next;
p=p->next;
q=q->next;
}
if(count)//若最后还有进位
{
w->next=new ListNode(1);
w=w->next;
}
return l3->next;
}
};
LeetCode23.合并K个排序链表
几天前做的时候根本不熟悉新建链表操作,捣鼓半天还没搞定
现在再做,两分钟搞定哈哈哈
就是sort排序再新建一个链表
/**
* 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) {
vector<int> v;
for(int i=0;i<lists.size();i++){
while(lists[i]!=nullptr){
v.push_back(lists[i]->val);
lists[i] = lists[i]->next;
}
}
sort(v.begin(),v.end());
ListNode* pre = new ListNode(-1);
ListNode* dummy = pre;
for(int i=0;i<v.size();i++){
pre->next = new ListNode(v[i]);
pre = pre->next;
}
return dummy->next;
}
};
先不管什么归并法和优先队列,一步步来