LeetCode链表经典题目(二)

1. LeetCode203. 移除链表元素

2. LeetCode707.设计链表

3. LeetCode206. 反转链表

4. LeetCode24. 两两交换链表中的节点​

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

6. LeetCode面试题 02.07. 链表相交

7. LeetCode142. 环形链表 II​


1. LeetCode203. 移除链表元素

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        ListNode*resHead=new ListNode(-1);//虚拟头节点,防止丢失
        resHead->next=head;
        ListNode*tmp=head;//tmp去遍历所有节点
        ListNode*pre=resHead;//tmp的前驱节点
        while(tmp!=NULL){
            if(tmp->val==val){
                pre->next=tmp->next;
            }else{//pre只有当tmp的值不等于val时,才移动。因为如果当前节点要被删除,就无法成为前驱节点
                pre=tmp;
            }
            //tmp无论如何都要往下一个节点移动
            tmp=tmp->next;
        }
        return resHead->next;
    }
};

2. LeetCode707.设计链表

//注意及时return,避免函数后面的操作干扰特殊情况的结果
class MyLinkedList {
public:
    ListNode*head;
    MyLinkedList() {
        //把链表头初始化为空指针
        head=NULL;
    }
    
    int get(int index) {
        //如果链表头为空指针,直接返回-1
        if(head==NULL)return -1;
        //创建头指针副本
        ListNode*tmp=head;
        while(index--){//用后置减的原因:head的索引为0
            tmp=tmp->next;
            //如果index还没到0,但是tmp已经是空指针了,说明index越界了,返回-1
            if(tmp==NULL)return -1;
        }
        //tmp一定不是空指针,直接返回值即可
        return tmp->val;
    }
    
    void addAtHead(int val) {
        //就算链表头是空指针也无妨
        ListNode*newNode=new ListNode(val);
        newNode->next=head;
        head=newNode;
    }
    
    void addAtTail(int val) {
        //如果链表头是空指针,无法调用head->next,所以先判断一下
        ListNode*newNode=new ListNode(val);
        if(head==NULL){
            head=newNode;
            return;
        }
        ListNode*tmp=head;
        while(tmp->next!=NULL){
            tmp=tmp->next;
        }
        tmp->next=newNode;
    }
    
    void addAtIndex(int index, int val) {
        if(index<=0){//index小于0,将其加到链表头
            addAtHead(val);
            return;
        }

        ListNode*tmp=head;
        ListNode*pre=NULL;//前驱节点
        while(index>0&&tmp!=NULL){
            pre=tmp;
            tmp=tmp->next;
            index--;
        }
        if(tmp==NULL&&index>0)return;//索引大于链表长度
        if(tmp==NULL&&index==0){//索引等于链表长度,添加到链表尾,注意及时返回
            addAtTail(val);
            return;
        }

        //tmp!=NULL
        ListNode*newNode=new ListNode(val);
        pre->next=newNode;
        newNode->next=tmp;
    }
    
    void deleteAtIndex(int index) {
        //链表凹凸为空指针,没有可以删除的节点
        if(head==NULL)return;
        //删除索引若为0,意味着删除链表头,直接让链表头后移即可,注意及时return
        if(index==0){
            head=head->next;
            return;
        }

        ListNode*tmp=head;
        ListNode*pre=NULL;//前驱节点
        while(index--){
            pre=tmp;
            tmp=tmp->next;
            if(tmp==NULL)return;
        }
        pre->next=tmp->next;
    }
};

3. LeetCode206. 反转链表

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(head==NULL||head->next==NULL){
            return head;
        }
        ListNode*reverseHead=new ListNode(-1);//前驱节点,防止丢失链表
        ListNode*cur=head;
        ListNode*next=cur->next;
        while(cur!=NULL){
            next=cur->next;//先记录好原链表的next节点
            cur->next=reverseHead->next;
            reverseHead->next=cur;
            cur=next;
        }
        return reverseHead->next;
    }
};

4. LeetCode24. 两两交换链表中的节点

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if(head==NULL||head->next==NULL)return head;
        ListNode*swapHead=new ListNode(-1);//创建前驱节点,防止链表丢失
        ListNode*cur=head;//当前需转换对的第一个节点
        ListNode*next=cur->next->next;//下一对的第一个节点
        ListNode*pre=swapHead;
        while(cur!=NULL&&cur->next!=NULL){//如果最后剩下节点数小于等于1,就不需要再做任何处理了
            next=cur->next->next;//因为要改变cur->next->next,所以先备份
            //由于前一对总是直接连接到后一对的第二个节点,所以会遗漏节点。因此创建一个前驱节点来前后连接
            pre->next=cur->next;
            //前驱节点即为每一对做完交换的后一个节点
            pre=cur;
            cur->next->next=cur;
            cur->next=next;
            cur=next;
        }
        return swapHead->next;
    }
};

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

双指针:快慢指针法
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode*dummyHead=new ListNode(0);
        dummyHead->next=head;
        ListNode*slow=dummyHead;
        ListNode*fast=dummyHead;

        //让fast先走n+1步,然后再让fast和slow一起移动,结束时,slow指向要删除节点的前一个
        while(n--&&fast!=NULL){
            fast=fast->next;
        }
        fast=fast->next;

        while(fast!=NULL){
            slow=slow->next;
            fast=fast->next;
        }

        slow->next=slow->next->next;
        return dummyHead->next;
    }
};

6. LeetCode面试题 02.07. 链表相交

利用A、B链表的长度差,相当于让长的链表先走长度差步
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode*A=headA;
        ListNode*B=headB;
        while(A!=NULL||B!=NULL){//A和B同时为空说明无交点
            if(A==B)return A;
            A=A==NULL?headB:A->next;
            B=B==NULL?headA:B->next;
        }
        return NULL;
    }
};

7. LeetCode142. 环形链表 II

双指针:快慢指针法
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode*fast=head;
        ListNode*slow=head;
        while(fast!=NULL&&fast->next!=NULL){
            fast=fast->next->next;
            slow=slow->next;
            if(fast==slow){
                ListNode*index1=fast;
                ListNode*index2=head;
                while(index1!=index2){
                    index1=index1->next;
                    index2=index2->next;
                }
                return index1;
            }
        }
        return NULL;
    }
};

糊涂版本代码:
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        //定义快慢指针
        ListNode*slow=head;
        ListNode*fast=head;
        //由于一开始对快慢指针的定义,导致函数根本无法进入该循环
        while(fast!=slow){
            fast=fast->next->next;
            slow=slow->next;
        }
        ListNode*index1=head;
        ListNode*index2=slow;
        while(index1!=index2){
            index1=index1->next;
            index2=index2->next;
        }
        return index2;
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Jomo.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值