leetcode-链表

这篇博客详细介绍了LeetCode中涉及链表的多个问题,包括删除倒数第N个节点、合并两个有序链表、合并K个升序链表、两两交换链表节点、旋转链表、删除排序链表中的重复元素、分隔链表、反转链表、K个一组翻转链表、复制带随机指针的链表、环形链表问题、对链表进行插入排序、相交链表、回文链表、奇偶链表以及两个链表相加等。每个问题都有问题描述、解析和代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

List

链表结构

如无特殊说明,链表结构如下:

// 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) {
   }
}

链表模板1

链表的创建,打印,销毁。

#include <iostream>
#include <vector>

using namespace std;

struct ListNode {
   
    int val;
    ListNode* next;
    ListNode():val(0),next(nullptr) {
   }
    ListNode(int v):val(v),next(nullptr) {
   }
    ListNode(int v, ListNode* p):val(0),next(p) {
   }
};

ListNode* createList(const vector<int>& nums)
{
   
    ListNode dummy(0);
    ListNode* node = &dummy;

    for (const int& n: nums)
    {
   
        node->next = new ListNode(n);
        node = node->next;
    }

    return dummy.next;
}

void printList(ListNode* head)
{
   
    while (head)
    {
   
        cout << head->val << " ";
        head = head->next;
    }
    cout << endl;
}

void destroyList(ListNode* head)
{
   
    while (head)
    {
   
        ListNode* delNode = head;
        head = head->next;
        delete delNode;
    }
}

int main(int argc, char* argv[])
{
   
    vector<vector<int>> nums{
   {
   }, {
   1}, {
   1,2,3,4,5,6}};

    for (auto& n: nums)
    {
   
        cout << "---------------" << endl;
        ListNode* head = createList(n);
        printList(head);

        // ... do something here
        printList(head);

        destroyList(head);
    }
    return 0;
}

链表模板2

输入是字符串如:“1->2->3->4”,根据字符串创建链表。

#include <iostream>
#include <vector>

using namespace std;

struct ListNode {
   
    int val;
    ListNode* next;
    ListNode():val(0),next(nullptr) {
   }
    ListNode(int v):val(v),next(nullptr) {
   }
    ListNode(int v, ListNode* p):val(0),next(p) {
   }
};

ListNode* createList(const vector<int>& nums)
{
   
    ListNode dummy(0);
    ListNode* node = &dummy;

    for (const int& n: nums)
    {
   
        node->next = new ListNode(n);
        node = node->next;
    }

    return dummy.next;
}

void printList(ListNode* head)
{
   
    while (head)
    {
   
        cout << head->val;
        head = head->next;
        if (head)    // 注意这里的链表打印!!
            cout << "->";
    }
    cout << endl;
}

void destroyList(ListNode* head)
{
   
    while (head)
    {
   
        ListNode* delNode = head;
        head = head->next;
        delete delNode;
    }
}

// 函数参数是字符串!!
ListNode* createList(string& str)
{
   
    if (str == "")
        return nullptr;

    ListNode dummy(0);
    ListNode* node = &dummy;
    int i = 0;
    int n = str.size();
    int num = 0;

    while (i < n)
    {
   
        if (str[i] >= '0' && str[i] <= '9')
        {
   
            num = num * 10 + (str[i] - '0');
        }
        else if(str[i] == '-')
        {
   
            node->next = new ListNode(num);
            node = node->next;
            num = 0;
        }
        i++;
    }
    node->next = new ListNode(num);
    return dummy.next;
}

int main(int argc, char* argv[])
{
   
    string str1;
    cin >> str1; // 1->2->3

    string str2;
    cin >> str2; // 0->1->4->5

    ListNode* head1 = createList(str1);
    ListNode* head2 = createList(str2);

    // do something ...

    destroyList(head1);
    destroyList(head2);

    return 0;
}

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

问题描述:
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
要求只能使用一趟扫描。
其中:
链表中结点的数目为 sz
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= sz
比如:

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

解析:

  1. 该题可以用快慢指针来实现一趟扫描找出被删除节点。只要让两个节点指针相差(n-1)个节点,然后让快的节点指针指向链表的最后一个节点,那么慢的节点指针自然指向要删除的那个节点。
  2. 注意被删除节点为头节点的情况,也就是n == sz的情况,需要设置哨兵节点。
  3. 让两个快慢两个指针的差距为n,可以减少一个prevNode的变量。

代码实现:

class Solution {
   
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
   
        ListNode dummy(0);
        dummy.next = head;
        ListNode* slow = &dummy;
        ListNode* fast = slow;

        for (int i = 0; i < n; i++)
            fast = fast->next;
        
        while (fast->next)
        {
   
            slow = slow->next;
            fast = fast->next;
        }

        ListNode* temp = slow->next->next;
        delete slow->next;
        slow->next = temp;

        return dummy.next;
    }
};

21. 合并两个有序链表

问题描述:
将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例1:
在这里插入图片描述

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

解析:

  1. 总体思路是:每次比较链表l1和链表l2的值,那个小,就将该节点合入新链表中,然后继续拿小节点的next节点和之前大节点进行比较,直到其中一个链表为空。
  2. 定义一个虚拟节点,取值为INT_MIN,确保在排序之后,始终是第一个节点,那这样的话,虚拟节点的next节点就是真正的新链表指针。

代码实现:

class Solution {
   
public:
    ListNode* mergeTwoLists(</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值