leetcode刷题记录 1.1 链表

参考:labuladong的算法小抄,自己按照思路手写了一遍 https://labuladong.github.io/algo/di-ling-zh-bfe1b/shuang-zhi-0f7cc/

链表

Checklist

  1. 如果要创造一个新表,用dummy指针避免空指针的处理情况,代码更简洁
  2. 分割链表:记得断开原链表的next,否则结果有环
  3. 快慢指针应用
  • 倒数第k个:fast先跑k步,slow开始跑
  • 环形链表:fast跑两步,slow跑一步
  • 环形链表交点:画图。相交之后把任意一个放到起点再跑,再相交时就是交点
  • 两表相交:p1:跑完1再跑2,p2:跑完2再跑1。while(p1!=p2)

leetcode 21: 合并有序列表

https://leetcode.com/problems/merge-two-sorted-lists/

Tips:

  1. dummy结点的运用,避免处理空指针,让代码更简洁,在创造一条新链表的时候有用
class Solution {
    public:
        ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
            ListNode* dummy = new ListNode(-1);
            ListNode* p = dummy;
            ListNode* l1 = list1;
            ListNode* l2 = list2;
            while(l1 != NULL && l2 != NULL){
                if(l1->val < l2->val){
                    p->next = l1;
                    l1 = l1->next;
                } else {
                    p->next = l2;
                    l2 = l2->next;
                }
                p = p->next;
            }
            if (l1 != NULL) {
                p->next = l1;        
            }
            if (l2 != NULL) {
                p->next = l2;
            }
            return dummy->next;
            
    }
};

leetcode 86 partition list(分割链表)

https://leetcode.com/problems/partition-list/

Tips

  • 思路:将小于x和大于等于x的节点分别放在两个链表中
  • 注意:不能直接p = p->next, 要记得断开原链表中每个结点的next指针,否则最后返回的结果中有环
class Solution {
public:
    ListNode* partition(ListNode* head, int x) {
        ListNode* dummy1 = new ListNode(-1);
        ListNode* dummy2 = new ListNode(-1);
        ListNode* l1 = dummy1;
        ListNode* l2 = dummy2;
        ListNode* p = head;
        while (p != NULL){
            if (p->val < x) {
                l1->next = p;
                l1 = l1->next;

            } else {
                l2->next = p;
                l2 = l2->next;
         
            }            
            ListNode* temp = p->next;
            p->next = NULL;
            p = temp;
        }
        l1->next = dummy2->next;
        return dummy1->next;
    }
};

leetcode 23 合并K个有序链表

要用到优先队列,有点难。。。先跳过

leetcode 19 删除链表的倒数第k个节点

https://leetcode.com/problems/remove-nth-node-from-end-of-list/description/

思路:遍历一次链表,找到倒数第k个结点,双指针。

  • 先让p1跑到k的位置
  • 然后p2从头开始和p1一起跑,一直把p1跑到链表结尾,此时p2的位置就是倒数第k个

注意

  • 注意虚拟指针的运用,要新建3个指针,dummy和p1和p2,一开始指向head的前一个结点。
  • 删除指针的操作,直接p2->next = p2->next->next即可,不用创建临时节点
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode *dummy = new ListNode(-1);
        dummy->next = head;
        ListNode *p1 = dummy, *p2 = dummy;
        for(int i=0; i<n; i++){
            p1 = p1->next;
        }
        while(p1!=NULL and p1->next != NULL){
            p1 = p1->next;
            p2 = p2->next;
        }
        p2->next = p2->next->next;
        return dummy->next;
    }
};

leetcode 876 Middle of the linked list(单链表的中点)

https://leetcode.com/problems/middle-of-the-linked-list/description/

快慢指针,没啥好说的

class Solution {
public:
    ListNode* middleNode(ListNode* head) {    
        ListNode *p1 = head, *p2 = head;
        while (p1 != NULL and p1->next != NULL) {
            p1 = p1->next->next;           
            p2 = p2->next;
        }
        return p2;
    }
};

leetcode 141 Linked list cycle(环形链表)

https://leetcode.com/problems/linked-list-cycle/

快慢指针,没啥好说的

class Solution {
public:
    ListNode* middleNode(ListNode* head) {    
        ListNode *p1 = head, *p2 = head;
        while (p1 != NULL and p1->next != NULL) {
            p1 = p1->next->next;           
            p2 = p2->next;
        }
        return p2;
    }
};

leetcode 142 Linked List Cycle II (环形链表2)

https://leetcode.com/problems/linked-list-cycle-ii/description/
找出环形链表的起始结点

  1. 快慢指针找到相交点
  2. 把任意一个指针放到起点,再相同速度走,再相遇的时候就是环的起点
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode *p1 = head, *p2 = head;
        int k = 0;
        while(p1 && p1->next) {
            p1 = p1->next->next;
            p2 = p2->next;
           
            if(p1 == p2) {
                 p1 = head;
                 while(p1!=p2){
                     p1 = p1->next;
                     p2 = p2->next;
                 }               
                return p1;
            } 
        }
        return NULL;       
    }
};

leetcode 160:Intersection of two linked list(链表是否相交)

https://leetcode.com/problems/intersection-of-two-linked-lists/

双指针,跑完A后,再跑B。如果有交点,两个指针最终会落在交点上;如果没有交点,两个指针都是NULL. 思路是逻辑上让2个指针走同样的距离,消除长短差

代码实现的时候,注意循环条件是while(p1!=p1)即可。这种写法可以覆盖到不相交的的情况。

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
     ListNode *p1 = headA, *p2 = headB;
     while(p1 != p2) {
         if(p1) {
             p1 = p1->next;             
         } else {
             p1 = headB;
         }
         if(p2) {
             p2 = p2->next;             
         } else {
             p2 = headA;
         }
     }
     return p1;
    }
};
  • 19
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值