代码随想录额外题目| 链表 ●234回文链表●143重排链表 ●141环形链表

news2024/11/24 3:03:39

#234回文链表 

简单方法很简单(转成vector判断),难的方法有点难, 很巧妙 

简单方法:

 bool isPalindrome(ListNode* head) {
        vector<int> vec;
        ListNode* cur=head;
        while(cur){
            vec.push_back(cur->val);
            cur=cur->next;
        }
        int start=0; int end=vec.size()-1;
        while(start<=end){
            if(vec[start]!=vec[end]) return false;
            start++; end--;
        }
        return true;
        
    }

难的方法: 

学习随想录+一些自己的实现。要点:

1.找到LL中间点:

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

pre->next = nullptr;  

一定要用slow前面那个,然后前半段比后半段是奇数的话少一个,要使用slow整个就不对了。不知道怎么想出来的,但是测试一下是这样的

2.随想录的翻转和我写的略微有不同:其实不用管cur->next是不是null。但现在是第二遍做翻转LL写出来了,算是会了吧。

ListNode* reverseList(ListNode* head) {
        ListNode* temp; // 保存cur的下一个节点
        ListNode* cur = head;
        ListNode* pre = nullptr;
        while(cur) {
            temp = cur->next;  // 保存一下 cur的下一个节点,因为接下来要改变cur->next
            cur->next = pre; // 翻转操作
            // 更新pre 和 cur指针
            pre = cur;
            cur = temp;
        }
        return pre;
    }

整体代码: 

bool isPalindrome(ListNode* head) {
        if (head->next == nullptr) return true;
        ListNode* slow = head; // 慢指针,找到链表中间分位置,作为分割
        ListNode* fast = head;
        ListNode* pre = head; // 记录慢指针的前一个节点,用来分割链表
        while (fast && fast->next) {
            pre = slow;
            slow = slow->next;
            fast = fast->next->next;
        }
        pre->next = nullptr; 

        ListNode* cur1 = head;  // 前半部分
        ListNode* cur2 = reverseList(slow); 
        

        while (cur1) {//equal of cur1 longer
            if (cur1->val != cur2->val) return false;
            cur1 = cur1->next;
            cur2 = cur2->next;
        }
        return true;
    }

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

#143重排链表

用纯粹的链表法就会和#234回文LL很像,我想的&&我写的:

void reorderList(ListNode* head) {
        if(!head->next) return;
        ListNode* slow=head;
        ListNode* fast=head;
        ListNode* pre=head;
        while(fast && fast->next){
            pre=slow;
            slow=slow->next;
            fast=fast->next->next;
        }
        pre->next=nullptr;
        //slow is the head2, LL1 shorter
        
        ListNode* cur1=head;
        ListNode* cur2=reverse(slow);
        ListNode* tmp;
        ListNode* tmp2;
        while(cur1 && cur1->next){
            tmp=cur1->next;
            tmp2=cur2->next;
            cur1->next=cur2;
            cur2->next=tmp;

            cur1=tmp;
            cur2=tmp2;
        }
        cur1->next=cur2;
        
    }

    ListNode* reverse(ListNode* head){
        ListNode* pre=nullptr;
        ListNode* cur=head;
        ListNode* tmp=nullptr;

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

思路和随想录一样的:

 但是随想录主函数实现和我略有不同:

void reorderList(ListNode* head) {
        if (head == nullptr) return;
        // 使用快慢指针法,将链表分成长度均等的两个链表head1和head2
        // 如果总链表长度为奇数,则head1相对head2多一个节点
        ListNode* fast = head;
        ListNode* slow = head;
        while (fast && fast->next && fast->next->next) {
            fast = fast->next->next;
            slow = slow->next;
        }
        ListNode* head1 = head;
        ListNode* head2;
        head2 = slow->next;
        slow->next = nullptr;

        // 对head2进行翻转
        head2 = reverseList(head2);

        // 将head1和head2交替生成新的链表head
        ListNode* cur1 = head1;
        ListNode* cur2 = head2;
        ListNode* cur = head;
        cur1 = cur1->next;
        int count = 0; // 偶数取head2的元素,奇数取head1的元素
        while (cur1 && cur2) {
            if (count % 2 == 0) {
                cur->next = cur2;
                cur2 = cur2->next;
            } else {
                cur->next = cur1;
                cur1 = cur1->next;
            }
            count++;
            cur = cur->next;
        }
        if (cur2 != nullptr) { // 处理结尾
            cur->next = cur2;
        }
        if (cur1 != nullptr) {
            cur->next = cur1;
        }
    }

 其他方法:1. LL放到vec然后一前一后双指针 2.把链表放进双向队列,然后通过双向队列一前一后弹出数据,来构造新的链表 (从来没写过双向队列,真是神奇的东西)

void reorderList(ListNode* head) {
        deque<ListNode*> que;
        ListNode* cur = head;
        if (cur == nullptr) return;

        while(cur->next != nullptr) {
            que.push_back(cur->next);
            cur = cur->next;
        }

        cur = head;
        int count = 0; // 计数,偶数去后面,奇数取前面
        ListNode* node;
        while(que.size()) {
            if (count % 2 == 0) {
                node = que.back();
                que.pop_back();
            } else {
                node = que.front();
                que.pop_front();
            }
            count++;
            cur->next = node;
            cur = cur->next;
        }
        cur->next = nullptr; // 注意结尾
    }

#141环形链表

constraints真的很重要,看了一眼蛮小的:number of the nodes in the list is  [0, 10^4]

就想了个神奇方法,用个数判断

    bool hasCycle(ListNode *head) {
        ListNode *cur=head;
        int cnt=0;
        while(cur){
            cnt++;
            if(cnt>10000) return true;
            cur=cur->next;
        }
        return false;
    }

又写了个用set装的:时间和空间表现都不好 

bool hasCycle(ListNode *head) {
        set<ListNode *> myset;
        ListNode* cur=head;
        while(cur){
            if(myset.find(cur)==myset.end()) myset.insert(cur);
            else return true;
            cur=cur->next;
        }

        return false;
    }

随想录方法:快慢指针相遇判断成环(好重要的方法) ,142.环形链表II 这道重要的题就是这样做的,还要用数学计算,我居然忘了

bool hasCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;
        while(fast && fast->next) {
            slow = slow->next;
            fast = fast->next->next;
            
            if (slow == fast) return true;
        }
        return false;
    }

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

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

相关文章

Window和linux使用samba实现文件共享

开发环境 开发平台&#xff1a;IMX6 虚拟机环境&#xff1a;Ubuntu16.04 Samba版本&#xff1a;3.4.17 目的 实现无论IMX6作为客户端还是服务端&#xff0c;IMX6系统下与window系统、ubuntu系统文件共享。 Samba移植 下载Samba源码,这个网上一搜大把&#xff0c;我用的版本…

C++ | 构造与析构

目录 普通构造 构造函数基础 显示调用与隐式调用 explicit关键字 初始化列表 拷贝构造 拷贝构造的写法 深拷贝和浅拷贝 拷贝构造的调用时机 返回值优化 析构函数 析构函数基础 析构函数的作用 注意事项 如果无法调用构造函数&#xff0c;那么就无法实例化出对象…

python进阶书籍的推荐 知乎,python入门后如何进阶

本篇文章给大家谈谈python进阶书籍的推荐 知乎&#xff0c;以及python入门后如何进阶&#xff0c;希望对各位有所帮助&#xff0c;不要忘了收藏本站喔。 1、Python应该怎么学_python应该怎么学 想要学习Python&#xff0c;需要掌握的内容还是比较多的&#xff0c;对于自学的同…

java设计模式之模板模式(结合示例)

文章目录 &#x1f4cb;模板模式概念&#x1f4d6;组成要素&#x1f516;代码示例 &#x1f4c8;总结 &#x1f4cb;模板模式概念 在Java中&#xff0c;模板模式&#xff08;Template Pattern&#xff09;是一种行为设计模式&#xff0c;它定义了一个操作中的算法框架&#xf…

Unity游戏源码分享-街机捕鱼2017版本

Unity游戏源码分享-街机捕鱼2017版本 完整的单机游戏 功能玩法&#xff0c;积分系统都已经齐全的了。 项目源码地址&#xff1a;https://download.csdn.net/download/Highning0007/88105459

音视频——帧内预测

H264编码(帧内预测) 在帧内预测模式中&#xff0c;预测块P是基于已编码重建块和当前块形成的。对亮度像素而言&#xff0c;P块用于44子块或者1616宏块的相关操作。44亮度子块有9种可选预测模式&#xff0c;独立预测每一个44亮度子块&#xff0c;适用于带有大量细节的图像编码&…

C语言中的函数(超详细)

C语言中的函数&#xff08;超详细&#xff09; 一、函数概述二、C语言中函数的分类1.库函数2.自定义函数三、函数的参数1.实际参数&#xff08;实参&#xff09;2.形式参数&#xff08;形参&#xff09;四、函数的调用1.传值调用2.传址调用五、函数的嵌套调用和链式访问1.嵌套调…

【手机】三星手机刷机解决SecSetupWizard已停止

三星手机恢复出厂设置之后&#xff0c;出现SecSetupWizard已停止的解决方案 零、问题 我手上有一部同学给的三星 GT-S6812I&#xff0c;这几天搞了张新卡&#xff0c;多余出的卡就放到这个手机上玩去了。因为是获取了root权限的&#xff08;直接使用KingRoot就可以&#xff0…

C++ 提高编程

C 提高编程 主要针对C泛型编程和STL技术 一、 模板 1、 概念 模板就是建立通用的模具&#xff0c;大大提高代码的复用性 模板特点 模板不可以直接使用&#xff0c;它只是一个框架 ​ 模板的通用并不是万能的 2、 函数模板 C 另一种编程思想为泛型编程&#xff0c;主要利用的…

ChatGPT如何帮助学生学习

​ 一些教育工作者担心学生可能使用ChatGPT作弊。因为这个AI工具能写报告和计算机代码&#xff0c;画出复杂图表……甚至已经有许多学校把ChatGPT屏蔽。 研究发现&#xff0c;学生作弊的主要原因是想考得好。是否作弊与作业和考试的打分方式有关&#xff0c;所以这与技术的便…

浅谈前端跨平台框架

概述 前端跨端实践是指在开发过程中&#xff0c;使用统一的代码库或框架来实现在不同平台上运行的应用程序。 这种实践旨在减少重复开发和维护成本&#xff0c;并提高开发效率和用户体验。 以下是一些前端跨端实践的方法和技术&#xff1a; 响应式设计&#xff08;Responsiv…

0-虚拟机补充知识

虚拟机克隆 如果想要构建服务器集群&#xff0c;没有必要一台一台的去进行安装&#xff0c;只要通过克隆就可以。 快速获得多台服务器主要有两种方式&#xff0c;分别为&#xff1a;直接拷贝操作和vmware的克隆操作 直接拷贝 将之前安装虚拟机的所有文件进行拷贝&#xff0…

聊聊单片机编程测量电机的电流

要测量电机的电流&#xff0c;可以使用电流传感器来实现。常见的电流传感器有霍尔效应传感器和电阻式传感器。 在单片机编程中&#xff0c;可以通过 ADC&#xff08;模拟数字转换器&#xff09;模块来实现对电流传感器输出电压的采样和转换。下面是一个简单的步骤&#xff1a;…

笔记本充满电后,充电器可以长期不拔,会有安全隐患吗?

笔记本充满电后&#xff0c;一直插着不拔 1.建议人在身边可以暂时不拔&#xff0c;偶尔还是要使用电池当笔记本电池充满之后&#xff0c;电脑会自动使用电源供电&#xff0c;不会使用电池供电 2.笔记本电池都带有电池保护机制&#xff0c;在电池充满电后会自动停止充电 3.现在…

Ceph的应用

文章目录 一、创建 CephFS 文件系统 MDS 接口1&#xff09;在管理节点创建 mds 服务2&#xff09;查看各个节点的 mds 服务3&#xff09;创建存储池&#xff0c;启用 ceph 文件系统4&#xff09;查看mds状态&#xff0c;一个up&#xff0c;其余两个待命&#xff0c;目前的工作的…

Python - Opencv + pyzbar实时摄像头识别二维码

直接上代码&#xff1a; import cv2 from pyzbar.pyzbar import decodecap cv2.VideoCapture(0) # 打开摄像头while True: # 循环读取摄像头帧ret, frame cap.read()# 在循环中&#xff0c;将每一帧作为图像输入&#xff0c;使用pyzbar的decode()函数识别二维码barcodes …

gitignore文件使用方法(gitignore教程)(git status --ignored)(git check-ignore -v <file>)

文章目录 Gitignore文件使用描述Gitignore基本语法1. 基本语法★★★★★2. 配置方法 匹配示例示例1示例2示例3 其他命令git status --ignored&#xff08;用于显示被Git忽略的文件和文件夹的状态&#xff09;git check-ignore -v <file>&#xff08;用于检查指定文件是否…

springMVC--异常处理

文章目录 springMVC--异常处理基本介绍局部异常应用实例演示局部异常处理机制代码实现测试(页面方式) 全局异常应用实例应用实例需求代码实现完成测试(页面方式) 自定义异常应用实例应用实例需求应用实例-代码实现完成测试 全局异常处理---SimpleMappingExceptionResolver基本说…

Docker 阿里云容器镜像服务

阿里云-容器镜像服务ACR 将本地/服务器docker image&#xff08;镜像&#xff09;推送到 阿里云容器镜像服务仓库 1. 在容器镜像服务ACR中创建个人实例 2. 进入个人实例 > 命名空间 创建命名空间 3. 进入个人实例 > 镜像仓库 创建镜像仓库 4. 进入镜像仓库 > 基本信…

商品分类新建,修改,删除。手机扫码开单打印进销存,商贸批发生产企业仓库条码管理软件系统

商品分类新建&#xff0c;手机扫码开单打印进销存&#xff0c;商贸批发生产企业仓库条码管理软件系统&#xff0c;超市便利店五金茶叶烟酒鞋帽门店零售手机收银管理软件APP_哔哩哔哩_bilibili本期视频讲解&#xff1a;商品分类新建, 视频播放量 1、弹幕量 0、点赞数 0、投硬币枚…