leetcode链表的基本操作---C++实现

83 删除排序链表中的重复元素

leetcode 83 删除排序链表中的重复元素

给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。

示例 1:

输入:head = [1,1,2]
输出:[1,2]

示例 2:

输入:head = [1,1,2,3,3]
输出:[1,2,3]

代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        if(head==nullptr)
        {
            return nullptr;
        }
        ListNode* cur=head;
        while(cur && cur->next)
        {
            if(cur->val==cur->next->val)
            {
                cur->next=cur->next->next;
            }
            else
            {
                cur=cur->next;
            }
        }

        return head;
    }
};

203 移除链表元素

leetcode移除链表元素

题述:
给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

示例1:
在这里插入图片描述

输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]

示例二:

输入:head = [], val = 1
输出:[]

示例三:

输入:head = [7,7,7,7], val = 7
输出:[]

我们可以设置一个虚头结点,方便操作,这样原链表的所有节点就都可以按照统一的方式进行移除了。
C++代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        ListNode* VirtualHead=new ListNode(0);
        VirtualHead->next=head;
        ListNode* cur=VirtualHead;
        
        if(head==nullptr)
        {
            return nullptr;
        }

        while(cur->next)
        {
            if(cur->next->val==val)
            {
                ListNode* tmp=cur->next;  //记录值为val的结点
                cur->next=cur->next->next;

                delete tmp;
            }
            else
            {
                cur=cur->next;
            }
        }

        return VirtualHead->next;
        delete VirtualHead;
    }
};

707.设计链表

leetcode 707设计链表
题述:
设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。

在链表类中实现这些功能:

  • get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。
  • addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
  • addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
  • addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
  • deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。
class MyLinkedList {
public:
    struct LinkedNode
    {
        int val;
        LinkedNode* next;
        LinkedNode(int val)
        :val(val)
        ,next(nullptr)
        {

        }
    };
    MyLinkedList()
    {
        _VairtualHead=new LinkedNode(0);
        _size=0;
    }
    
    int get(int index) 
    {
        if(index>(_size-1)||index<0)
        {
            return -1;
        }
        LinkedNode* cur=_VairtualHead->next;
        while(index--)
        {
            cur=cur->next;
        }

        return cur->val;
    }
    
    void addAtHead(int val) 
    {
        LinkedNode* newNode=new LinkedNode(val);
        newNode->next=_VairtualHead->next;
        _VairtualHead->next=newNode;
        _size++;
    }
    
    void addAtTail(int val) 
    {
        LinkedNode* newNode=new LinkedNode(val);
        LinkedNode* cur=_VairtualHead;
        while(cur->next)
        {
            cur=cur->next;
        }
        cur->next=newNode;
        _size++;
    }
    
    void addAtIndex(int index, int val) 
    {
        if(index>_size)
        {
            return ;
        }
        LinkedNode* newNode=new LinkedNode(val);
        LinkedNode* cur=_VairtualHead;
        while(index--)
        {
            cur=cur->next;
        }
        newNode->next=cur->next;
        cur->next=newNode;
        _size++;
    }
    
    void deleteAtIndex(int index) 
    {
        if(index>=_size || index<0)
        {
            return ;
        }
        LinkedNode* cur=_VairtualHead;
        while(index--)
        {
            cur=cur->next;
        }
        LinkedNode* tmp=cur->next;
        cur->next=cur->next->next;

        delete tmp;
        _size--;
    }
private:
    int _size;
    LinkedNode* _VairtualHead;

};

/**
 * Your MyLinkedList object will be instantiated and called as such:
 * MyLinkedList* obj = new MyLinkedList();
 * int param_1 = obj->get(index);
 * obj->addAtHead(val);
 * obj->addAtTail(val);
 * obj->addAtIndex(index,val);
 * obj->deleteAtIndex(index);
 */

206反转链表

leetcode 206反转链表

题述:
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例一:
在这里插入图片描述

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

示例二:
在这里插入图片描述

输入:head = [1,2]
输出:[2,1]

示例三:

输入:head = []
输出:[]

首先定义一个cur指针,指向头结点,再定义一个pre指针,初始化为nullprt。
然后就要开始反转了,首先要把 cur->next 节点用tmp指针保存一下,也就是保存一下这个节点。
为什么要保存一下这个节点呢,因为接下来要改变 cur->next 的指向了,将cur->next 指向pre ,此时已经反转了第一个了。
接下来,就是循环走如下代码逻辑了,继续移动pre和cur指针。
最后,cur 指针已经指向了null,循环结束,链表也反转完毕了。 此时我们return pre指针就可以了,pre指针就指向了新的头结点

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* cur=head;
        ListNode* pre=nullptr;

        while(cur)
        {
            ListNode* tmp=cur->next;
            cur->next=pre;
            pre=cur;
            cur=tmp;
        }

        return pre;
    }
};

24.两两交换链表中的结点

leetcode 24.两两交换链表中的结点

题述:
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
示例1:
在这里插入图片描述

输入:head = [1,2,3,4]
输出:[2,1,4,3]

示例 2:

输入:head = []
输出:[]

示例 3:

输入:head = [1]
输出:[1]

分析:
初始时,cur指向虚拟头结点,然后进行如下三步:
在这里插入图片描述
操作之后,链表如下:
在这里插入图片描述
直观图:
在这里插入图片描述
代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode *VirtualHead=new ListNode(0);
        VirtualHead->next=head;
        ListNode* cur=VirtualHead;
        while(cur->next && cur->next->next)
        {
            ListNode* tmp=cur->next;
            ListNode* tmp1=cur->next->next->next;

            cur->next=cur->next->next;   //步骤一
            cur->next->next=tmp;         //步骤二
            cur->next->next->next=tmp1;  //步骤三

            cur=cur->next->next;         //跳两步

        }

        return VirtualHead->next;
        delete VirtualHead;
    }
};

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

leetcode 19.删除链表的倒数第N个结点

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

示例 1:

在这里插入图片描述

输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
示例 2:

输入:head = [1], n = 1
输出:[]
示例 3:

输入:head = [1,2], n = 1
输出:[1]

思路:

双指针的经典应用,如果要删除倒数第n个节点,让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。删掉slow所指向的节点就可以了。

思路是这样的,但要注意一些细节。
分为如下几步:

  • 定义fast指针和slow指针,初始值为虚拟头结点,如图:
    在这里插入图片描述
  • fast首先走n + 1步 ,为什么是n+1呢,因为只有这样同时移动的时候slow才能指向删除节点的上一个节点(方便做删除操作),如图:

在这里插入图片描述

  • fast和slow同时移动,直到fast指向末尾,如图:
    在这里插入图片描述

代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* VirtualHead=new ListNode(0);
        VirtualHead->next=head;
        ListNode* slow=VirtualHead;
        ListNode* fast=VirtualHead;

        //fast先走
        while(fast->next && n--)
        {
            fast=fast->next;
        }
        fast=fast->next;
        while(fast)
        {
            slow=slow->next;
            fast=fast->next;
        }
        slow->next=slow->next->next;

        return VirtualHead->next;
        delete VirtualHead;
    }
};

面试题 02.07. 链表相交

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。

图示两个链表在节点 c1 开始相交:
在这里插入图片描述

题目数据 保证 整个链式结构中不存在环。

**注意,**函数返回结果后,链表必须 保持其原始结构 。

示例 1:

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at ‘8’
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。

示例 2:

在这里插入图片描述

输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Intersected at ‘2’
解释:相交节点的值为 2 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。
在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。

示例 3:

在这里插入图片描述

输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。
由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
这两个链表不相交,因此返回 null 。

分析:

简单来说,就是求两个链表交点节点的指针。 这里要注意,交点不是数值相等,而是指针相等。
在这里插入图片描述
我们求出两个链表的长度,并求出两个链表长度的差值,然后让curA移动到,和curB 末尾对齐的位置,如图:

在这里插入图片描述

此时我们就可以比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到交点。
否则循环退出返回空指针。

代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* curA=headA;
        ListNode* curB=headB;
        int lenA=0;
        int lenB=0;

        while(curA)
        {
            lenA++;
            curA=curA->next;
        }

        while(curB)
        {
            lenB++;
            curB=curB->next;
        }
        //再将cur指向head
        curA=headA;
        curB=headB;

        if(lenA<lenB)
        {
            swap(curA,curB);
            swap(lenA,lenB);
        }

        int gap=lenA-lenB;

        //lenA先走
        while(gap--)
        {
            curA=curA->next;
        }

        while(curA)
        {
            if(curA==curB)
            {
                return curA;
            }
            else
            {
                curA=curA->next;
                curB=curB->next;
            }
        }

        return nullptr;
    }
};

142.环形链表II

leetcode 142.环形链表II

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
说明:不允许修改 链表。

示例 1:

在这里插入图片描述

输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:
在这里插入图片描述

输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

在这里插入图片描述

输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。

分析:
可以使用快慢指针法,分别定义 fast 和 slow 指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。

为什么fast 走两个节点,slow走一个节点,有环的话,一定会在环内相遇呢,而不是永远的错开呢
首先第一点:fast指针一定先进入环中,如果fast指针和slow指针相遇的话,一定是在环中相遇,这是毋庸置疑的。
那么来看一下,为什么fast指针和slow指针一定会相遇呢?
可以画一个环,然后让 fast指针在任意一个节点开始追赶slow指针。

因为fast是走两步,slow是走一步,其实相对于slow来说,fast是一个节点一个节点的靠近slow的,所以fast一定可以和slow重合。

如果有环,如何找到这个环的入口
此时已经可以判断链表是否有环了,那么接下来要找这个环的入口了。

假设从头结点到环形入口节点 的节点数为x。 环形入口节点到 fast指针与slow指针相遇节点 节点数为y。 从相遇节点 再到环形入口节点节点数为 z。 如图所示:

在这里插入图片描述
那么相遇时: slow指针走过的节点数为: x + y, fast指针走过的节点数:x + y + n (y + z),n为fast指针在环内走了n圈才遇到slow指针, (y+z)为 一圈内节点的个数A。

因为fast指针是一步走两个节点,slow指针一步走一个节点, 所以 fast指针走过的节点数 = slow指针走过的节点数 * 2:

(x + y) * 2 = x + y + n (y + z)

两边消掉一个(x+y): x + y = n (y + z)

因为要找环形的入口,那么要求的是x,因为x表示 头结点到 环形入口节点的的距离。

所以要求x ,将x单独放在左面:x = n (y + z) - y ,

再从n(y+z)中提出一个 (y+z)来,整理公式之后为如下公式:x = (n - 1) (y + z) + z 注意这里n一定是大于等于1的,因为 fast指针至少要多走一圈才能相遇slow指针。

这个公式说明什么呢?

先拿n为1的情况来举例,意味着fast指针在环形里转了一圈之后,就遇到了 slow指针了。

当 n为1的时候,公式就化解为 x = z,

这就意味着,从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是 环形入口的节点。

也就是在相遇节点处,定义一个指针index1,在头结点处定一个指针index2。

让index1和index2同时移动,每次移动一个节点, 那么他们相遇的地方就是 环形入口的节点。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* fast=head;
        ListNode* slow=head;

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

            // 快慢指针相遇,此时从head 和 相遇点,同时查找直至相遇
            if(slow==fast)
            {
                ListNode* index1=head;
                ListNode* index2=fast;

                while(index1!=index2) //当没有相遇时
                {
                    index1=index1->next;
                    index2=index2->next;
                }
                //相遇时
                return index2; //也可以返回index1,毕竟两个结点相遇了。
            
            }
        }
        return nullptr;

    }
};

21 合并两个有序的链表

leetcode 21 合并两个有序的链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

示例 1:
在这里插入图片描述

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]

示例 2:

输入:l1 = [], l2 = []
输出:[]

示例 3:

输入:l1 = [], l2 = [0]
输出:[0]

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        ListNode* VirtualHead=new ListNode(0);
        ListNode* cur=VirtualHead;
        ListNode* cur1=list1;
        ListNode* cur2=list2;

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

        //若cur1剩余结点
        if(cur1)
        {
            cur->next=cur1;
        }
        //若cur2剩余结点
        if(cur2)
        {
            cur->next=cur2;
        }

        return VirtualHead->next;
        delete VirtualHead;
    }
};

143.重排链表

leetcode 143.重排链表

给定一个单链表 L 的头节点 head ,单链表 L 表示为:

L0 → L1 → … → Ln - 1 → Ln

请将其重新排列后变为:

L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …

不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

示例 1:

输入:head = [1,2,3,4]
输出:[1,4,2,3]

示例 2:

输入:head = [1,2,3,4,5]
输出:[1,5,2,4,3]

分析:申请一个数组,直接将结点复制在数组中,进行操作
代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    void reorderList(ListNode* head) {
         vector<ListNode*> vec;
        ListNode* cur=head;
        if(cur==nullptr)
        {
            return ; //终止程序,不是返回空指针。
        }
        while(cur)
        {
            vec.push_back(cur);
            cur=cur->next;
        }
        cur=head;
        int count=0; //作用是根据计数的奇偶进行重排
        int left=1;
        int right=vec.size()-1;
        
        while(left<=right)
        {
            if(count%2==0)
            {
                cur->next=vec[right--];
                cur=cur->next;
            }
            else
            {
                cur->next=vec[left++];
                cur=cur->next;
            }
            count++;
        }
        cur->next=nullptr;
    }
};

86 分割链表

leetcode 86分割链表

题述:

给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。

你应当 保留 两个分区中每个节点的初始相对位置。

示例1:
在这里插入图片描述

输入:head = [1,4,3,2,5,2], x = 3
输出:[1,2,2,4,3,5]

示例 2:

输入:head = [2,1], x = 2
输出:[1,2]

分析: 首先根据题目中给的特定值x,然后将链表分割成结点值val小于x的一个链表和节点值val大于等于x值得链表。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* partition(ListNode* head, int x) {
        ListNode* headA=new ListNode(0);
        ListNode* headB=new ListNode(0);
        ListNode* curA=headA;
        ListNode* curB=headB;
        ListNode* cur=head;
        while(cur)
        {
            if(cur->val<x)
            {
                curA->next=cur;
                curA=curA->next;
            }
            else
            {
                curB->next=cur;
                curB=curB->next;
            }
            cur=cur->next;
        }
        curA->next=headB->next;
        curB->next=nullptr;
        delete headB;
        
        return headA->next;
        delete headA;
    }
};

234. 回文链表

leetcode 234. 回文链表
给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。

示例 1:

在这里插入图片描述

输入:head = [1,2,2,1]
输出:true

示例 2:
在这里插入图片描述

输入:head = [1,2]
输出:false

分析: 可以将结点值放入数组中,进行判断回文(左右指针思想)

 ListNode *cur=head;
        int count=0;

        //计算结点数
        while(cur)
        {
            count++;
            cur=cur->next;
        }
        vector<int> vec;
        vec.resize(count,0);
        int i=0;
        cur=head;
        while(cur)
        {
            vec[i++]=cur->val;
            cur=cur->next;
        }

        int left=0;
        int right=count-1;

        while(left<=right)
        {
            if(vec[left]!=vec[right])
            {
                return false;
            }
            else
            {
                left++;
                right--;
            }
        }

        return true;

148.排序链表

leetcode 148排序链表

题述:
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。

示例 1:
在这里插入图片描述

输入:head = [4,2,1,3]
输出:[1,2,3,4]

示例 2:

在这里插入图片描述

输入:head = [-1,5,3,4,0]
输出:[-1,0,3,4,5]
示例 3:

输入:head = []
输出:[]

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* sortList(ListNode* head) {
        if(head==nullptr)
        {
            return nullptr;
        }
        vector<int> vec;
        ListNode* cur=head;
        while(cur)
        {
            vec.push_back(cur->val);
            cur=cur->next;
        }

        cur=head;
        sort(vec.begin(),vec.end());
        int i=0;
        //int *p=&vec[0];
        while(cur)
        {
        	cur->val=vec[i++];
            //cur->val=*p;
            cur=cur->next;
            // *p++;
        }
        return head;
    }
};

23.合并K个升序链表

题述:

给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。

示例 1:

输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
1->4->5,
1->3->4,
2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6

示例 2:

输入:lists = []
输出:[]

示例 3:

输入:lists = [[]]
输出:[]

分析: 本题借助了 leetcode 148排序链表 的思想
代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
     ListNode* sortList(ListNode* head) {
        if(head==nullptr)
        {
            return nullptr;
        }
        ListNode* cur=head;
        vector<int> vec;
        while(cur)
        {
            vec.push_back(cur->val);
            cur=cur->next;
        }
        sort(vec.begin(),vec.end());

        cur=head;
        //int *p=&vec[0];
        int i=0;
        while(cur)
        {
            cur->val=vec[i++];
            cur=cur->next;
            //p++;
        }

        return head;
    }
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        int size=lists.size();
        vector<int> vec;
        for(int i=0;i<size;i++)
        {
            ListNode* cur=lists[i];
            while(cur)
            {
                vec.push_back(cur->val);
                cur=cur->next;
            }
        }
        int len=vec.size();
        ListNode* VirtualHead=new ListNode(0);
        ListNode* cur1=VirtualHead;
        for(int i=0;i<len;i++)
        {
            ListNode* newNode=new ListNode(vec[i]);
            cur1->next=newNode;
            cur1=newNode;
        }
        cur1->next=nullptr;
        sortList(VirtualHead->next);
        
        return VirtualHead->next;
        delete VirtualHead;

    }
};

876.链表的中间结点

leetcode 876.链表的中间结点

给定一个头结点为 head 的非空单链表,返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

示例 1:

输入:[1,2,3,4,5]
输出:此列表中的结点 3 (序列化形式:[3,4,5])
返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
注意,我们返回了一个 ListNode 类型的对象 ans,这样:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.

示例 2:

输入:[1,2,3,4,5,6]
输出:此列表中的结点 4 (序列化形式:[4,5,6])
由于该列表有两个中间结点,值分别为 3 和 4,我们返回第二个结点。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* middleNode(ListNode* head) {
        if(head==nullptr)
        {
            return nullptr;
        }
       
        ListNode* slow=head;
        ListNode* fast=head;
        while(fast && fast->next)
        {
            slow=slow->next;
            fast=fast->next->next;
        }

        return slow;
    }
};

2. 两数相加

leetcode 2. 两数相加

题述:
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例 1:
在这里插入图片描述

输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.

示例 2:

输入:l1 = [0], l2 = [0]
输出:[0]

示例 3:

输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]

代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode* VirtualHead=new ListNode(0);
        ListNode* cur=VirtualHead;

        ListNode* cur1=l1;
        ListNode* cur2=l2;
        int carry=0;

        while(cur1 || cur2 || carry)
        {
            if(cur1)
            {
                carry+=cur1->val;
            }
            if(cur2)
            {
                carry+=cur2->val;
            }
            ListNode* tmp=new ListNode(carry%10);
            cur->next=tmp;
            cur=cur->next;
            if(cur1)
            {
                cur1=cur1->next;
            }
            if(cur2)
            {
                cur2=cur2->next;
            }

            carry=carry/10;
        }
        cur->next=nullptr;
        
        return VirtualHead->next;
        delete VirtualHead;
    }
};

声明:本文主要参考卡尔哥的算法思想,整理是自己复习,不作为任何商业传播意图。感谢卡尔哥!!!

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Rust 是一种现代的编程语言,特别适合处理内存安全和线程安全的代码。在 LeetCode 中,链表是经常出现的题目练习类型,Rust 语言也是一种非常适合处理链表语言。接下来,本文将从 Rust 语言的特点、链表的定义和操作,以及 Rust 在 LeetCode链表题目的练习等几个方面进行介绍和讲解。 Rust 语言的特点: Rust 是一种现代化的高性能、系统级、功能强大的编程语言,旨在提高软件的可靠性和安全性。Rust 语言具有如下几个特点: 1. 内存安全性:Rust 语言支持内存安全性和原语级的并发,可以有效地预防内存泄漏,空悬指针以及数据竞争等问题,保证程序的稳定性和可靠性。 2. 高性能:Rust 语言采用了“零成本抽象化”的设计思想,具有 C/C++ 等传统高性能语言的速度和效率。 3. 静态类型检查:Rust 语言支持静态类型检查,可以在编译时检查类型错误,避免一些运行时错误。 链表的定义和操作: 链表是一种数据结构,由一个个节点组成,每个节点保存着数据,并指向下一个节点。链表的定义和操作如下: 1. 定义:链表是由节点组成的数据结构,每个节点包含一个数据元素和一个指向下一个节点的指针。 2. 操作:链表的常用操作包括插入、删除、查找等,其中,插入操作主要包括在链表首尾插入节点和在指定位置插入节点等,删除操作主要包括删除链表首尾节点和删除指定位置节点等,查找操作主要包括根据数据元素查找节点和根据指针查找节点等。 Rust 在 LeetCode链表题目的练习: 在 LeetCode 中,链表是常见的题目类型,而 Rust 语言也是一个非常适合练习链表题目的语言。在 Rust 中,我们可以定义结构体表示链表的节点,使用指针表示节点的指向关系,然后实现各种操作函数来处理链表操作。 例如,针对 LeetCode 中的链表题目,我们可以用 Rust 语言来编写解法,例如,反转链表,合并两个有序链表,删除链表中的重复元素等等,这样可以更好地熟悉 Rust 语言的使用和链表的操作,提高算法和编程能力。 总之,在 Rust 中处理链表是非常方便和高效的,而 LeetCode 中的练习也是一个非常好的机会,让我们更好地掌握 Rust 语言链表数据结构的知识。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值