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;
}
相关推荐
wclass-zhengge2 分钟前
数据结构与算法篇(树 - 常见术语)
数据结构·算法
夜雨翦春韭9 分钟前
【代码随想录Day31】贪心算法Part05
java·数据结构·算法·leetcode·贪心算法
C++忠实粉丝6 小时前
前缀和(8)_矩阵区域和
数据结构·c++·线性代数·算法·矩阵
ZZZ_O^O6 小时前
二分查找算法——寻找旋转排序数组中的最小值&点名
数据结构·c++·学习·算法·二叉树
代码雕刻家7 小时前
数据结构-3.9.栈在递归中的应用
c语言·数据结构·算法
Kalika0-09 小时前
猴子吃桃-C语言
c语言·开发语言·数据结构·算法
代码雕刻家9 小时前
课设实验-数据结构-单链表-文教文化用品品牌
c语言·开发语言·数据结构
小字节,大梦想10 小时前
【C++】二叉搜索树
数据结构·c++
我是哈哈hh11 小时前
专题十_穷举vs暴搜vs深搜vs回溯vs剪枝_二叉树的深度优先搜索_算法专题详细总结
服务器·数据结构·c++·算法·机器学习·深度优先·剪枝
丶Darling.11 小时前
LeetCode Hot100 | Day1 | 二叉树:二叉树的直径
数据结构·c++·学习·算法·leetcode·二叉树