Leedcode刷题——3 链表

注:以下代码均为c++

1


思路:

cpp 复制代码
//注:这里的链表都没有头节点
ListNode* removeNthFromEnd(ListNode* head, int n) {
    ListNode* dummy = new ListNode(-1);  //因为有可能删除第一个节点,所以建一个头节点指向第一个节点,便于将第一个节点与其他节点统一处理。
    dummy->next = head;
    ListNode* first = dummy, *second = dummy;
    while(n--)  //first先走n步
        first = first->next;
    while(first->next){  //first走到头时,second走到倒数n+1个
        first = first->next;
        second = second->next;
    }
    second->next = second->next->next;
    return dummy->next;
}

2



思路:

"伪装"

我们知道要想删除当前节点必须知道它的上一节点,但我们只有当前要删除的节点地址,无法找到上一节点。

所以,我们将要删除的node伪装成下一个点,再将下一个点删掉。

cpp 复制代码
void deleteNode(ListNode* node) {
    //node->val = node->next->val;
    //node->next = node->next->next;

    // 可以将上面两句话合并为一句话,因为链表的数据结构为结构体,其存储的val和next的地址是相邻的,
    // 我们将当前节点的val,next复制为下一节点的val,next,可以一起操作。
    *(node) = *(node->next);  //当前节点的地址 = 下一节点的地址
}

3


思路:

cpp 复制代码
ListNode* deleteDuplicates(ListNode* head){
    ListNode* cur = head;
    while(cur){
        if(cur->next && cur->next->val == cur->val)
            cur->next = cur->next->next;
        else
            cur = cur->next;
    }
    return head;
}

4


cpp 复制代码
ListNode* deleteDuplicates(ListNode* head) {
    //设头节点
    ListNode* h = new ListNode();
    h->next = head;

    ListNode* first, *second;  //first指向不重复节点的尾部, second寻找下一个不重复节点
    first = h;
    second = first->next;

    while(second && second->next){
        if(second->val == second->next->val){
            while(second->next && second->val == second->next->val)
                second = second->next;
            second = second->next;
        }
        else{
            first->next = second;
            first = second;
            second = second->next;
        }
    }
    first->next = second;
    return h->next;
}

5


思路:

cpp 复制代码
ListNode* rotateRight(ListNode* head, int k) {
    if(head == NULL)
        return head;
    int n = 0;
    for(ListNode* p = head; p; p = p->next)
        n++;
    k = k % n;
    ListNode* first, *second;
    first = head;
    second = head;
    while(k--)
        second = second->next;
    while(second->next){
        first = first->next;
        second = second->next;
    }
    second->next = head;
    head = first->next;
    first->next = NULL;

    return head;
}

6


思路:

cpp 复制代码
//2 建立头节点,因为对第一个节点进行操作,所以设置头节点来处理较为容易
ListNode* swapPairs(ListNode* head){
    ListNode* dummy = new ListNode();
    dummy->next = head;
    ListNode* p = dummy;
    while(p->next && p->next->next){
        ListNode *a = p->next, *b = p->next->next;
        p->next = b;
        a->next = b->next;
        b->next = a;
        p = a;
    }
    return dummy->next;
}

7


思路:

cpp 复制代码
ListNode* reverseList(ListNode* head) {
    if(head == NULL || head->next == NULL)
        return head;
    ListNode* p = head, *q = p->next, *t = q->next;
    while(t){
        q->next = p;
        p = q;
        q = t;
        t = t->next;
    }
    q->next = p;  //这一步容易遗忘,当t=NULL时没有进入循环,直接退出了,需要补充一句。
    head->next = NULL;
    head = q;  //也可以不要这一句,直接返回q
    return head;
}

8


思路:

cpp 复制代码
ListNode* reverseBetween(ListNode* head, int left, int right) {
    if(left == right)
        return head;

    int i;
    //建立头节点
    ListNode* dummy = new ListNode();
    dummy->next = head;
    head = dummy;
    //找到first和second的位置,first->next是第一个要翻转的点,second是最后一个要翻转的点。
    ListNode* first = head, *second;
    for(i = 1; i < left; i++)
        first = first->next;
    second = first->next;
    for(i = 1; i <= right - left; i++)
        second = second->next;
    //翻转
    ListNode* p = first->next, *q = p->next, *t = q->next;
    while(t != second->next){
        q->next = p;
        p = q;
        q = t;
        t = t->next;
    }
    q->next = p;
    first->next->next = t;
    first->next = second;

    return head->next;
}

9



思路:

cpp 复制代码
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
    ListNode* p = headA, *q = headB;
    while(p != q){  //注意这个while循环内部一定是if-else,这种结构的语句,不然会出现问题。
        if(p == NULL)
            p = headB;
        else
            p = p->next;
        if(q == NULL)
            q = headA;
        else
            q = q->next;
    }
    return p;
}

10



思路1:哈希表 (我看这道题的第一个想法)

一个非常直观的思路是:我们遍历链表中的每个节点,并将它记录下来;一旦遇到了此前遍历过的节点,就可以判定链表中存在环。借助哈希表可以很方便地实现。
思路2:快慢指针

(1)

快指针:一次走两步(红色)

慢指针:一次走一步(蓝色)

快慢指针一起走,假设当慢指针走到b点时,快指针走到c'点,那么快慢指针将在c点相遇。

(2)

快慢指针相遇后,将慢指针指向链表头部,快慢指针均一次走一步,快慢指针将在b点相遇,即环的起始点。

cpp 复制代码
ListNode *detectCycle(ListNode *head) {
    ListNode *quick = head, *slow = head;
    //注意开始需要将quick和slow走起来,因为如果开始不走,quick=slow,无法进入下面while循环
    if(quick == NULL || (quick != NULL && quick->next == NULL))
        return NULL;
    quick = quick->next->next;
    slow = slow->next;

    while(quick != slow  && quick && quick->next){  //注意quick和quick->next需要判空
        quick = quick->next->next;
        slow = slow->next;
    }
    if(quick != slow)  //如果遇到空就说明不是环,返回NULL
        return NULL;
    slow = head;
    while(quick != slow){
        quick = quick->next;
        slow = slow->next;
    }
    return quick;
}
相关推荐
Doopny@5 分钟前
计算星期几(信息学奥赛一本通-1083)
数据结构·算法
ん贤1 小时前
【数据结构】链表
数据结构·链表
a_j581 小时前
算法与数据结构(回文数)
数据结构
呵呵哒( ̄▽ ̄)"1 小时前
绪论数据结构基本概念(刷题笔记)
数据结构
熊峰峰1 小时前
数据结构第八节:红黑树(初阶)
开发语言·数据结构·c++·算法
f狐0狸x2 小时前
【蓝桥杯每日一题】3.8
数据结构·c++·算法·蓝桥杯
我想吃余2 小时前
【初探数据结构】带环链表:原理、判断与数学证明
数据结构·链表
*.✧屠苏隐遥(ノ◕ヮ◕)ノ*.✧9 小时前
C语言_数据结构总结8:链式队列
c语言·开发语言·数据结构·链表·visualstudio·visual studio
不知道取啥耶10 小时前
C++ 滑动窗口
数据结构·c++·算法·leetcode
Murphy_lx11 小时前
数据结构(树)
数据结构