数据结构(二)—— 链表(2)

news2024/10/6 5:42:18

文章目录

  • 1 143 重排链表
    • 1.1 找到原链表的中点(「876. 链表的中间结点」)。
    • 2.2 将原链表的右半端反转(「206. 反转链表」)
    • 3.3 交叉合并两个链表(与「21. 合并两个有序链表」思路不同)
    • 3.4 补充 21 合并两个有序链表
  • 2 328 奇偶链表
  • 3 单向链表
  • 4 双向链表
  • 5 双向循环链表


1 143 重排链表

笨方案一:利用线性表存储该链表,而后直接按顺序访问指定元素,重建该链表即可。
在这里插入图片描述

void reorderList(ListNode* head) {
        if(head == nullptr) return;
        
        vector<ListNode*> vec;
        while(head != nullptr){
            vec.push_back(head);
            head = head->next;
        }

        int i = 0;
        int j = vec.size() - 1;
        while(i < j){
            vec[i]->next = vec[j];
            ++i;
            if (i == j) {
                break;
            }
            vec[j]->next = vec[i];
            --j;
        }
        vec[i]->next = nullptr;
}

方案二:寻找链表中点 + 链表逆序 + 合并链表
注意到目标链表即为将原链表的左半端和反转后的右半端合并后的结果。

这样任务可划分为三步:

1.1 找到原链表的中点(「876. 链表的中间结点」)。

使用快慢指针找到链表的中间节点。
在这里插入图片描述

2.2 将原链表的右半端反转(「206. 反转链表」)

使用迭代法实现链表的反转。

3.3 交叉合并两个链表(与「21. 合并两个有序链表」思路不同)

保证l2的长度小于l1,这里的写法与21不同。
在这里插入图片描述

class Solution {
public:
    void reorderList(ListNode* head) {
        if(head == nullptr) return;
        ListNode* mid = middleNode(head);
        ListNode* reverse = reverseList(mid->next);
        mid->next = nullptr;   // 将链表切断
        mergeList(head, reverse);
    }

    ListNode* middleNode(ListNode* head) {
        ListNode* slow = head;
        ListNode* fast = head;
        while(fast->next != nullptr && fast->next->next != nullptr){
            fast = fast->next->next;
            slow = slow->next;
        }
        return slow;
    }

    ListNode* reverseList(ListNode* head) {
        ListNode* cur = head;
        ListNode* pre = nullptr;
        while(cur != nullptr){
            ListNode* temp = cur->next;
            cur->next = pre;
            pre = cur;
            cur = temp;
        }
        return pre;
    }

    void mergeList(ListNode* l1, ListNode* l2) {
        while(l2 != nullptr){
            ListNode* templ1 = l1->next;
            l1->next = l2;
            l1 = templ1;

            ListNode* templ2 = l2->next;
            l2->next = l1;
            l2 = templ2;
        }
    }
    
};

与21相同的思路代码如下,注意返回值为ListNode*了

ListNode* mergeList(ListNode* l1, ListNode* l2) {
        ListNode* dummyhead = new ListNode(999);
        ListNode* cur = dummyhead;
        while(l1 != nullptr && l2 != nullptr){
            cur->next = l1;
            l1 = l1->next;
            cur = cur->next;
            cur->next = l2;
            l2 = l2->next;
            cur = cur->next;
        }
        if(l1 != nullptr) cur->next = l1;
        if(l2 != nullptr) cur->next = l2;
        return dummyhead->next;
}

3.4 补充 21 合并两个有序链表

在这里插入图片描述

ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        if(list1 == nullptr) return list2;
        if(list2 == nullptr) return list1;

        ListNode* dummyhead = new ListNode(0);
        ListNode* cur = dummyhead;
        while(list1 != nullptr && list2 != nullptr) {
            if(list1->val < list2->val){
                cur->next = list1;
                cur = cur->next;
                list1 = list1->next;
            }else{
                cur->next = list2;
                cur = cur->next;
                list2 = list2->next;
            }
        }
        
        if(list1 != nullptr) cur->next = list1;
        if(list2 != nullptr) cur->next = list2;
        
        return dummyhead->next;
}

2 328 奇偶链表

在这里插入图片描述

while的退出条件是画图得出的

ListNode* oddEvenList(ListNode* head) {
        if(head == nullptr) return head;

        ListNode* odd = head;
        ListNode* even = head->next;
        ListNode* evenhead = even;
        while(even != nullptr && even->next != nullptr) {
            odd->next = even->next;    // 1
            even->next = odd->next->next;   // 2
            odd = odd->next;
            even = even->next;
        }
        odd->next = evenhead;
        return head;
}

3 单向链表

#include<iostream>

using namespace std;


class MyLinkedList {
public:
    struct ListNode {
        int val;
        ListNode* next;
        ListNode(int val) 
            : val(val)
            , next(nullptr) 
        {}
    };

    MyLinkedList() {
        node_ = new ListNode(0);
        size_ = 0;
    }
    
    int get(int index) {
        if (index >= size_ || index < 0) return -1;
        ListNode* cur = node_;
        while (index--) {
            cur = cur->next;
        }
        cur = cur->next;
        return cur->val;
    }
    
    void addAtHead(int val) {
        ListNode* newNode = new ListNode(val);
        newNode->next = node_->next;
        node_->next = newNode;
        size_++;
    }
    
    void addAtTail(int val) {
        ListNode* newNode = new ListNode(val);
        ListNode* cur = node_;
        while (cur->next != nullptr) {
            cur = cur->next;
        }
        cur->next = newNode;
        size_++;
    }
    
    void addAtIndex(int index, int val) {
        if (index > size_ || index < 0) return; // index可以为size_
        ListNode* newNode = new ListNode(val);
        ListNode* cur = node_;

        while (index--) {
            cur = cur->next;
        }
        newNode->next = cur->next;
        cur->next = newNode;
        size_++;
    }
    
    void deleteAtIndex(int index) {
        if (index >= size_ || index < 0) return;
        ListNode* cur = node_;
        while (index--) {
            cur = cur->next;
        }
        ListNode* temp = cur->next;
        cur->next = cur->next->next;
        delete temp;
        size_--;
    }

    void show() {
        ListNode* cur = node_->next;

        while (cur != nullptr) {
            cout << cur->val << " ";
            cur = cur->next;
        }
        cout << endl;
    }

private:
    int size_;
    ListNode* node_;
};

int main() {
    MyLinkedList link;
    link.addAtHead(7);
    link.addAtHead(2);
    link.addAtHead(1);
    link.addAtTail(8);

    link.show();

    link.deleteAtIndex(2);
    link.show();
    
    return 0;
}

4 双向链表

#include<iostream>

using namespace std;

struct Node {
    int data_;
    Node* pre_;
    Node* next_;

    Node(int data)
        : data_(data)
        , pre_(nullptr)
        , next_(nullptr) 
    {}

    Node()
    {
        pre_ = nullptr;
        next_ = nullptr;
    }    
};

class DoubleLink {
public:
    DoubleLink() {
        head_ = new Node();
    }
    ~DoubleLink() {
        Node* p = head_;
        while (p != nullptr) {
            head_ = head_->next_;
            delete p;
            p = head_;
        }
    }

public:
    void insert_head(int val) {
        Node* node = new Node(val);
        node->next_ = head_->next_;
        node->pre_ = head_;

        if (head_->next_ != nullptr) head_->next_->pre_ = node;  //原来链表里有第一个节点  确认head后面一个不为空
        head_->next_ = node;
    }

    // 尾插法

    void InsertTail(int val) {
        Node* p = head_;

        while (p->next_ != nullptr) {
            p = p->next_;
        }

        Node* node = new Node(val);
        node->pre_ = p;
        p->next_ = node;
    }

    void Remove(int val) {
        Node* p = head_->next_;
        while (p != nullptr) {
            if (p->data_ == val) {
                p->pre_->next_ = p->next_;
                if (p->next_ != nullptr) p->next_->pre_ = p->pre_;
                delete p;
                return;
            } else {
                p = p->next_;
            }
        }
    }

    bool Find(int val) {
        Node* p = head_->next_;
        while (p != nullptr) {
            if (p->data_ == val) {
                return true;
            } else {
                p = p->next_;
            }
        }
    }

    void show() {
        Node* p = head_->next_;
        while (p != nullptr) {
            cout << p->data_ << " ";
            p = p->next_;
        }
        cout << endl;
    }
private:
    Node* head_;
};

int main() {
    DoubleLink dlink;
    dlink.InsertTail(20);
    dlink.InsertTail(23);
    dlink.InsertTail(89);
    dlink.InsertTail(15);
    dlink.InsertTail(36);
    dlink.InsertTail(78);
    dlink.InsertTail(56);
    dlink.InsertTail(41);
    dlink.InsertTail(32);
    dlink.show();

    dlink.insert_head(200);
    dlink.show();

    dlink.Remove(200);
    dlink.show();

    dlink.Remove(78);
    dlink.show();

    return 0;
}

5 双向循环链表

#include<iostream>

using namespace std;

struct Node {
    int data_;
    Node* pre_;
    Node* next_;

    Node(int data)
        : data_(data)
        , pre_(nullptr)
        , next_(nullptr) 
    {}

    Node()
    {
        pre_ = nullptr;
        next_ = nullptr;
    }    
};

class DoubleCircleLink {
public:
    DoubleCircleLink() {
        head_ = new Node();
        head_->next_ = head_;
        head_->pre_ = head_;
    }
    ~DoubleCircleLink() {
        Node* p = head_->next_;
        while (p != head_) {
            head_->next_ = p->next_;
            p->next_->pre_ = head_;
            delete p;
            p = head_->next_;
        }
        delete head_;
        head_ = nullptr;
    }

public:
    void insert_head(int val) {
        Node* node = new Node(val);
        node->next_ = head_->next_;
        node->pre_ = head_;

        if (head_->next_ != nullptr) head_->next_->pre_ = node;  //原来链表里有第一个节点  确认head后面一个不为空
        head_->next_ = node;
    }

    // 尾插法

    void InsertTail(int val) {
        Node* p = head_->pre_;

        Node* node = new Node(val);
        node->pre_ = p;
        p->next_ = node;
        node->next_ = head_;
        head_->pre_ = node;
    }

    void Remove(int val) {
        Node* p = head_->next_;
        while (p != head_) {
            if (p->data_ == val) {
                p->pre_->next_ = p->next_;
                p->next_->pre_ = p->pre_;
                delete p;
                return;
            } else {
                p = p->next_;
            }
        }
    }

    bool Find(int val) {
        Node* p = head_->next_;
        while (p != head_) {
            if (p->data_ == val) {
                return true;
            } else {
                p = p->next_;
            }
        }
    }

    void show() {
        Node* p = head_->next_;
        while (p != head_) {
            cout << p->data_ << " ";
            p = p->next_;
        }
        cout << endl;
    }
private:
    Node* head_;
};

int main() {
    DoubleCircleLink dlink;
    dlink.InsertTail(20);
    dlink.InsertTail(23);
    dlink.InsertTail(89);
    dlink.InsertTail(15);
    dlink.InsertTail(36);
    dlink.InsertTail(78);
    dlink.InsertTail(56);
    dlink.InsertTail(41);
    dlink.InsertTail(32);
    dlink.show();

    dlink.insert_head(200);
    dlink.show();

    dlink.Remove(200);
    dlink.show();

    dlink.Remove(78);
    dlink.show();

    return 0;
}

感谢博主 @-特立独行的猪-
实在是太强了555

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/589235.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaScript高级一、作用域解构箭头函数

零、文章目录 JavaScript高级一、作用域&解构&箭头函数 1、作用域 &#xff08;1&#xff09;局部作用域 局部作用域分为函数作用域和块作用域。 **函数作用域&#xff1a;**在函数内部声明的变量所在作用域。 函数内部声明的变量&#xff0c;在函数外部无法被访问…

项目冲突3大管理原则及管理模式

1、系统思考原则 此原则即从全局出发&#xff0c;追求全局最优。系统思考原则的关键在于能够从全局出发&#xff0c;发现冲突的“杠杆点”&#xff0c;即可引起结构上重要而持久改善的点。一旦找到最佳的杠杆点&#xff0c;我们便能以小而专注的行动&#xff0c;创造最大的效果…

笔试强训4

作者&#xff1a;爱塔居 专栏&#xff1a;笔试强训 作者简介&#xff1a;大三学生&#xff0c;希望和大家一起进步 目录 day4 day5 day4 1. 下列与队列结构有关联的是&#xff08;&#xff09; A 函数的递归调用 B 数组元素的引用 C 多重循环的执行D 先到先服务的作业调度 对列…

数据表示(二进制、进制转换、补码计算)

目录 1.进制2.进制转换2.1 R进制转十进制2.2 十进制转R进制2.3 m进制转n进制方法1&#xff1a;十进制中转方法2&#xff1a;直接转化 3.进制计算3.1 机器数3.2 编码方式&#xff08;原码、反码、补码、移码&#xff09;3.3 表示范围定点整数定点小数 3.4 定点表示法 4.浮点数4.…

小破站有许多“高质量”东西,怀揣着“学习”的目的,我用Python将它们通通采集下来

前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 事情是这样的&#xff0c;昨晚室友拉着我去他的电脑&#xff0c;说带我欣赏一点高雅的作品~ 于是这一坐下&#xff0c;便是一晚上… 作为一个乐于分享的博主&#xff0c;本来我是决定直接分享的&#xff0c; 但是转念一想&a…

MySQL锁详解

五.锁 5.1 概述 锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中&#xff0c;除传统的计算资源CPU、 RAM、I/O的争用以外&#xff0c;数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题&#xff0c;锁冲…

「实在RPA·零售数字员工」助力零售运营化”零“为整

零售行业是指以面向消费者销售商品和服务的行业&#xff0c;它涵盖了各种类型的商店、百货公司、超市、购物中心、电商平台等&#xff0c;是全球最大的行业之一&#xff0c;在经济增长中有着举足轻重的作用。随着科技的发展&#xff0c;消费者需求的变化以及运营成本的增长&…

软件测试用例的设计以及分类

文章目录 测试用例设计1.测试用例2.设计测试用例的方法1) 等价类2) 边界值3) 判定表法4) 正交法5) 场景设计法6) 错误猜测法 3. 测试分类1) 按测试对象划分2) 按是否查看代码划分黑盒测试白盒测试灰盒测试为什么不直接使用灰盒测试常见的测试方法有哪些&#xff1f;哪些方法用的…

终于拿下腾讯25K的offer,面试官问我的面试题+回答,他都听懵了...

前言 自动化测试面试题总结&#xff1a; 1、你会封装自动化测试框架吗&#xff1f; 这个问得最多&#xff0c;很多公司直接写在招聘要求中。 自动化框架主要的核心框架就是分层PO模式&#xff1a;分别为&#xff1a;基础封装层BasePage&#xff0c;PO页面对象层&#xff0c;T…

【移动计算技术(Android)】期末复习

目录 选择题 选择题知识点汇总 Activity Intent Broadcast BroadcastReceiver 如何自定义Receiver 如何注册接收器 Service SharedPreferences 三种访问模式 如何创建 如何存储/修改 如何读取 内部存储 openFileOutput openFileInput SD卡 资源文件 SQLite…

【学习笔记】Unity基础(七)【uGUI基础、利用render Texture实现小地图功能】

目录 一 Canvas1.1 三种Render Space渲染空间 screen1.2 canvas scaler画布缩放器1.3sprite1.4 sprite packer1.5 unity目录1.6 RuleTile Tilemap1.7 sprite packer1.8 sorting layer 二 rect transform2.1 pivot 中轴 中心点2.2 anchor 锚点2.3 uGUI源代码 三 EventSystem3.1 …

【paddlecls】多机多卡-linux

1. 安装docker&#xff08;引擎&#xff09;&#xff1a; &#xff08;https://docs.docker.com/engine/install/ubuntu/&#xff09; Install Docker Engine on Ubuntu To get started with Docker Engine on Ubuntu, make sure you meet the prerequisites, and then follo…

助力工业物联网,工业大数据之工业大数据之油站维度设计【十四】

文章目录 01&#xff1a;油站维度设计02&#xff1a;油站维度构建 01&#xff1a;油站维度设计 目标&#xff1a;掌握油站维度的需求与设计 路径 step1&#xff1a;需求step2&#xff1a;设计 实施 需求&#xff1a;构建油站维度表&#xff0c;得到油站id、油站名称、油站所属…

北美机器人市场迎来销售放缓,未来路在何方?

原创 | 文 BFT机器人 引言 Introduction 北美机器人销售在2022年创下了历史记录&#xff0c;但在2023年第一季度放缓。据推进自动化协会&#xff08;A3&#xff09;提供的数据显示&#xff0c;2023年第一季度&#xff0c;北美公司仅订购了9,168台机器人&#xff0c;较2022年同…

C++进阶 —— map

目录 一&#xff0c;map介绍 类pair 函数模板make_pair 二&#xff0c;map使用 一&#xff0c;map介绍 map是关联容器&#xff0c;按照特定的次序存储元素&#xff08;由键key和值value组合而成的&#xff09;&#xff1b;键key通常用于排序及唯一标识元素&#xff0c;而值…

不愧是华为出来的大佬,实在是太强了.....

前段时间公司缺人&#xff0c;也面了许多测试&#xff0c;一开始瞄准的就是中级水准&#xff0c;当然也没指望能来大牛&#xff0c;提供的薪资在15-20k这个范围&#xff0c;来面试的人有很多&#xff0c;但是平均水平真的让人很失望。看了简历很多上面都是写有4年工作经验&…

Pillow(PIL)入门教程(非常详细)以及python实现jpg,png、ico、bmp格式互转大全

概述 Pillow库的特点&#xff1a; python3安装pillow&#xff1a; ​Pillow是什么 Pillow创建Image对象&#xff1a; jpg,png&#xff1a; jpg与png格式互转代码&#xff1a; 概述 Pillow 库&#xff08;有时也称 PIL 库&#xff09; 是 Python 图像处理的基础库&#xf…

计划学习网络安全,需要学习哪些知识,应该怎么学习?

虽然现在的网络安全大都是指渗透测试&#xff0c;但是并不代表只有渗透测试这一个方向&#xff0c;除此之外还有二进制逆向这个方向。以下会对这两个方向分别对您进行详解。 渗透测试方向 1、学习编程语言 &#xff08;1&#xff09;网站如何搭建的&#xff1f;HTML、CSS、J…

SpingBoot+LayUI 实现酒店管理系统编写

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

晚上12点接到面试邀约电话,待业一个月的我却拒绝了....

前言 一位测试朋友最近一直在找工作&#xff0c;前两天刚拒绝了一个面试。那天晚上12点多&#xff0c;他接到一个HR的面试电话&#xff0c;让他第二天早上10点去公司面试。朋友和HR聊了两句&#xff0c;了解到这位HR经常加班&#xff0c;于是果断拒绝了这个面试。 我还为他可惜…