栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

LeetCode-链表专题

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

LeetCode-链表专题

1->2->3->NULL,链表是指向型结构
查找:随机访问的时间复杂度是O(n)
增删:删除和插入元素的时间复杂度都是O(1)

对于链表我们都用头结点来代表整个链表,给你一个链表的时候我们拿到的就是头节点。如果没有头结点证明整个链表为空,如果已经有头结点证明链表不为空。

虚拟头结点:由于链表中是用head节点来代替整个链表的,故头节点经常需要判断(head有还是没有来进行不同的操作)->可以通过设置一个哨兵的技巧简化代码,哨兵节点的值一直是NULL,不用考虑哨兵的问题,在哨兵眼里你是head还是不是head对其来说都是一样的。最后return的是 哨兵->next,因为我们已经不在乎head是不是之前的head了,保持next就行。

遍历:

head;
while (head)
{
    head = head->next;
}

对链表进行修改的时候,有些时候需要将头结点删掉,这样针对头结点有无需要进行判断头结点有无,针对有无的不同情况进行不同的操作(写很多if else)。定义一个哨兵节点(空节点),这样在进行遍历的时候就不用考虑头节点。

dummy; dumm->next = head; p = dummy;
while (p) 
{

}

206 反转链表
注意:对于分析算法题里有一个重要的理念:上来要考虑到入口的边界条件

public:
    ListNode* reverseList(ListNode* head) {
        if (!head) return head;
        ListNode* pre = NULL;
        ListNode* cur = head;

        while (cur)
        {
            auto next = cur->next;
            cur->next = pre;
            pre = cur;
            cur = next;
        }

        return pre;
    }
};

92 反转链表II

class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int left, int right) {
        auto dummy = new ListNode(-1);
        dummy->next = head;
        auto tmp = dummy;

        for (int i = 0; i < left - 1; i ++)
            tmp = tmp->next;
        
        auto pre = tmp->next;
        auto cur = pre->next;
        for (int i = 0; i < right - left; i ++)
        {
            auto next = cur->next;
            cur->next = pre;
            pre = cur;
            cur = next;
        }
        tmp->next->next = cur;
        tmp->next = pre;

        return dummy->next;
    }
};

21 合并两个有序链表
两路归并

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        auto p = list1, q = list2;
        auto dummy = new ListNode(-1);
        auto cur = dummy;

        while (p && q)
        {
            if (p->val <= q->val) 
            {
                cur->next = p;
                p = p->next;
                cur = cur->next;
            }
            else
            {
                cur->next = q;
                q = q->next;
                cur = cur->next;
            }
        }
        if (p) cur->next = p;
        if (q) cur->next = q;

        return dummy->next;
    }
};

快慢指针

19 删除链表的第N个节点
设计到删除头结点的要用到虚拟头结点
快指针先走n步,然后快指针和慢指针同时走,直到快指针走到终点,慢指针就走到了要删除点的前一个点,然后删除即可

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        auto dummy = new ListNode(-1);
        dummy->next = head;
        auto slow = dummy, fast = dummy;

        while (n --)  fast = fast->next;

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

        return  dummy->next;
    }
};

876 链表的中间节点
枚举一下奇偶的情况,奇数点的时候fast->next为空,偶数点的时候fast为空

class Solution {
public:
    ListNode* middleNode(ListNode* head) {
        auto slow = head, fast = head;

        while (fast && fast->next) // && 
        {
            slow = slow->next;
            fast = fast->next->next;
        }
        
        return slow;
    }
};

234 回文链表
不能直接通过索引找到链表的结尾,
找到链表的中点(分奇偶),然后将中点的前半段进行翻转,再对比前后半段链表。
注意:while循环中的顺序必须先让fast走两步,再slow走一步。因为如果是slow走一步的同时要修改指针方向,fast再走两步就到不了原来想到的地方了。

class Solution {
public:
    bool isPalindrome(ListNode* head) {
        auto slow = head, fast = head;
        ListNode* pre = NULL;

        while (fast && fast->next)
        {
            fast = fast->next->next; // fast必须先走,因为后走之后,slow改变了原来的指针指向,fast就到不了该到的位置了    
            auto next = slow->next;
            slow->next = pre;
            pre = slow;
            slow = next;  
        }
        if (fast) slow = slow->next;

        while (pre && slow)
        {
            if (slow->val != pre->val) return false;
            pre = pre->next;
            slow = slow->next;
        }

        return true;
    }
};

160 相交链表

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        auto p = headA, q = headB;

        while (p != q)
        {
            p = p ? p->next : headB;
            q = q ? q->next : headA;
        }

        return p;
    }
};

141 环型链表
有环和没有环的区别:两指针有没有相遇
两个指针有没有再次遇到,如果有环->相当于在环形操场跑->快指针跑的快就一定会慢指针套圈,两指针会相遇
如果没有环->相当于在直道跑->快指针跑的快,两指针一定不会遇到

class Solution {
public:
    bool hasCycle(ListNode *head) {
        auto slow = head, fast = head;

        while (fast && fast->next)
        {
            fast = fast->next->next;
            slow = slow->next;
            if (slow == fast) return true;
        }

        return false;
    }
};
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/836630.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号