新建链表——从LeetCode题海中总结常用套路

目录

新建链表的一个大坑:

新建链表类型题目的套路:

LeetCode21.合并两个有序链表

LeetCode19.删除链表的倒数第N个数

LeetCode2.两数相加


新建链表的一个大坑:

这样可以新建!

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;
    }
};

先不管什么归并法和优先队列,一步步来

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沉迷单车的追风少年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值