力扣第206题-反转链表

news2024/10/7 16:20:46

反转链表的效果示意图

要改变链表结构时,通常加入一个创建的临时头结点会更容易操作

时间复杂度:遍历2遍,2n

空间复杂度:额外创建一个栈,n

(空间创建一个数组长度最大为5000,你说这个数组是栈也可以,只要光通过一端对它进行操作就可以了)

/**
 * 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 h;//临时头结点
    h.next = head;

    //利用栈
    stack<int>s;//创建栈
    for(ListNode*p=head;p!=NULL;p=p->next)//从头遍历
    {
        //入栈
       s.push(p->val);//将val值挨个放入栈 
    }
    for(ListNode*p=head;p!=NULL;p=p->next)
    {
        //出栈
        p->val=s.top();
        s.pop();//让s.top出栈
    }

    return h.next;
    
    }
};

利用单链表的头插法进行逆置,将所有结点从后往前重新头插一遍就好了

但比上面的算法要慢一点,因为修改一两个指针的指向也要花时间的

指针p指向图中位置,将head->next断开,赋值为空,

然后利用头插,将每一个结点再重新头插到这个头结点的单链表里面

先插一个1,再插一个2,因为是头插,所以这个2就在1的前面;同理,4,3,2,1

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* reverseList(struct ListNode* head) {
    if(head==NULL||head->next==NULL)//只有0(无法反转)或1(转完还是自己)个点,
    //直接返回(反转要至少2个数据结点以上)
    return head;
    struct ListNode h;//临时头结点
    h.next=NULL;//头结点为空的单链表,等会用来头插
    //头插需要单独一个指针把后面标记起来,以免找不到数据了
    //struct ListNode*p=head->next;不用初始化,while里面有
    struct ListNode*p;//用p记录
    while(head!=NULL)//后面还有结点
    {
        //头插,先绑后面,再绑前面
        p=head->next;//初始化
        //把head头插到h中
        head->next=h.next;// head->next=NULL,右
        h.next=head;//左
        head=p;//结点往后走
    }

    return  h.next;
}

即双指针解法

一个指针current指向头结点head,正常正向链表head的next指向后(右)边下一个结点

现在要反转,就是说head的next要反过来指向前(左)边,即head成了最后一个结点指向空

则需要另一个指针pre,定义pre为cur指针结点的前一个位置的指针,方便让cur从指向后一位的方向改成指向前一位,所以pre定义在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* reverseList(ListNode* head) {
    ListNode* temp; // 保存cur的下一个节点
        ListNode* cur = head;//初始化,cur指向头结点
        ListNode* pre = NULL;//初始化,
        //pre在cur的前一个,方便反转操作cur->next = pre;为空是cur第一次反转后就从头结点变成尾结点了
        while(cur)//cur!=NULL为循环终止条件 
        {
            temp = cur->next;  // 保存一下 cur的下一个节点,绑住后面,因为接下来要改变cur->next
            cur->next = pre; // 翻转操作
            // 更新pre 和 cur指针
            pre = cur;//pre先向后走移动,将2边连接住
            //同时,若先移动cur,即cur = temp;那么此时cur的值已经改变了,
            //就不能 pre = cur向后移动了,那么pre就不能移动到cur当初的位置了
            cur = temp;//cur再向后走
        }//出循环遍历则cur==NULL,此时pre指向反转完的新头结点,原尾结点
        return 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* reverse(ListNode* pre,ListNode* cur)//反转链表函数
     {
        if(cur == NULL)//循环终止条件,这里是递归终止条件
        return pre;
        ListNode* temp = cur->next;//暂存后面
        cur->next = pre;//反转方向
        // 可以和双指针法的代码进行对比,如下递归的写法,其实就是做了这两步
        // pre = cur;
        // cur = temp;
        //向后移动在双指针里面是一层循环,在递归里面是进入下一层递归
        //下一层递归里面参数pre = cur;cur = temp;所以把(cur,temp)参数传进去
        return reverse(cur,temp);//reverse(pre,cur)的实参
    }
    ListNode* reverseList(ListNode* head)//力扣给的主函数,里面光调用反转函数就好了
    {
        // 和双指针法初始化是一样的逻辑
        // ListNode* cur = head;
        // ListNode* pre = NULL;
        return reverse(NULL, head);//reverse(pre,cur)的实参
    }
};

上面两第二个图片的运行结果是错的

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

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

相关文章

基于svm的水果识别

1、程序界面介绍 该程序GUI界面包括待检测水果图片加载、检测结果输出、清空可视化框等。其中包括训练模型、加载图片、重置、识别检测按钮。 程序GUI界面 识别玉米识别西瓜 分类器识别水果基本原理&#xff1a; 由于每种水果的外形存在很大差异&#xff0c;比如西瓜与玉米&…

C语言/数据结构——每日一题(设计循环队列)

一.前言 上一次我们分享了关于队列的基本实现——https://blog.csdn.net/yiqingaa/article/details/139033067?spm1001.2014.3001.5502 现在我们将使用队列知识来解决问题——设计循环队列&#xff1a;https://leetcode.cn/problems/design-circular-queue/submissions/533299…

深度神经网络——什么是自动编码器?

自动编码器 自动编码器&#xff08;Autoencoders&#xff09;是无监督学习领域中一种重要的神经网络架构&#xff0c;它们主要用于数据压缩和特征学习。 自动编码器的定义&#xff1a; 自动编码器是一种无监督机器学习算法&#xff0c;它通过反向传播进行训练&#xff0c;目标…

【从C++到Java一周速成】章节10:封装、继承、方法的重写、多态

章节10&#xff1a;封装、继承、方法的重写、多态 【1】封装1.高内聚&#xff0c;低耦合2.代码层面的体现 【2】继承【3】方法的重写【4】多态 【1】封装 1.高内聚&#xff0c;低耦合 高内聚&#xff1a;类的内部数据操作细节自己完成&#xff0c;不允许外部干涉&#xff1b;…

如何使用 CapSolver 扩展找到 Google reCAPTCHA 站点密钥?

网站安全性在当今至关重要&#xff0c;Google reCAPTCHA 作为防止垃圾邮件和滥用行为的前线防御系统起着关键作用。reCAPTCHA 站点密钥是确保网站交互由人类驱动的唯一标识符。了解如何找到这个密钥对于网站管理员和开发人员来说至关重要。 什么是 reCAPTCHA 站点密钥 reCAPT…

智能家居6 -- 配置 ini文件优化设备添加

不知道什么是ini的朋友可以先看这篇:一文带你入门ini格式-CSDN博客 准备 如下图: 在src 下面添加 ini.c 在inc 下面添加 ini.h 在 receive_interface.c 里面包含头文件&#xff0c;把之前添加的设备类注释掉 这时候就可以把相关设备的(.c .h)文件给删掉了 如下图: 修改/添…

CDH6.3.2集成Flink1.17

直接运行脚本即可&#xff0c;一键输出相关依赖包 运行步骤已给到文档 下载地址

更新评估班级、确定评价学生

场景&#xff1a; 义务阶段为何要进行分层分班&#xff0c;这一点大家都心知肚明。你说的答案是不是也和我的一样&#xff1a;为了实行分层教学。"人往高处走&#xff0c;水往低处流"&#xff0c;每次确定分班后&#xff0c;总会有一些学生向上调整&#xff0c;当然也…

python2.x版本安装、安装pip

文章目录 一、安装python二、安装pip2.1、pip简介2.2、pip安装2.3、no such option: -e2.4、pip卸载2.5、pip扩展 本文讲解在windows系统装安装python2.7.13版本 一、安装python 1.下载安装包&#xff0c;官网链接地址&#xff1a;https://www.python.org/downloads/ 直接在…

Pytorch深度学习实践笔记4

&#x1f3ac;个人简介&#xff1a;一个全栈工程师的升级之路&#xff01; &#x1f4cb;个人专栏&#xff1a;pytorch深度学习 &#x1f380;CSDN主页 发狂的小花 &#x1f304;人生秘诀&#xff1a;学习的本质就是极致重复! 视频来自【b站刘二大人】 1 反向传播 Back propaga…

机器视觉HALCON:2.HALCON的预备环境和数据结构

目录 下载基础语法HALCON的数据结构图像和数据类型区域的存储区域的存储连通区域 亚像素轮廓&#xff08;XLD&#xff09;亚像素轮廓介绍亚像素轮廓数据结构 数组数组的赋值与创建数组的存储与读取 字典字典介绍字典的创建和操作 句柄 下载 HALCON的官方网站 下载时需要注册登…

react antd中transfer穿梭框组件中清除搜索框内容

如图&#xff1a;需要清除search搜索框内容 antd的transfer穿梭框组件未提供入口修改input框的值。 2种方法修改。 1、直接操作dom元素设置值&#xff08;不推荐&#xff09; useEffect(() > {const searchInput document.querySelector(.ant-transfer-list-search input)…

Redis常用命令——String篇

前面我们讲解了一些 Redis 的全局命令&#xff08;Redis常用基本全局命令&#xff09;。所谓全局命令&#xff0c;就是可以匹配任意一个数据结构进行使用。但是不同的数据结构&#xff0c;也有自己的操作命令。本篇文章主要讲解的是 String 的操作命令&#xff0c;希望会对你有…

2024电工杯B题:大学生平衡膳食食谱的优化设计及评价

大学时代是学知识长身体的重要阶段&#xff0c;同时也是良好饮食习惯形成的重要时期。这一特 定年龄段的年轻人&#xff0c;不仅身体发育需要有充足的能量和各种营养素&#xff0c;而且繁重的脑力劳动和 较大量的体育锻炼也需要消耗大量的能源物质。大学生中饮食结构不合理以及…

在抖音怎么开店?抖音小店开店步骤详解!建议收藏!

大家好&#xff0c;我是电商小V 想在抖音上面开一家属于自己的抖音店铺去卖点商品赚取个商品的差价&#xff0c;那么开通抖音小店的步骤是什么呢&#xff1f;主要分为几步呢&#xff1f;关于这个问题咱们就来详细的说一下&#xff1a; 开店之前的准备工作&#xff0c;首先需要准…

核心四:线程的一生

4、核心四&#xff1a;线程的一生&#x1f49f; 4.1 New 已创建但还未启动的新线程。 我们new Thread之后&#xff0c;线程已经实现了一些准备工作。但没有运行run方法&#xff0c;因为没有使用start来开启线程。此时&#xff0c;线程处于New状态。 4.2 Runnable&#xff08…

Python模块、包和异常处理

大家好&#xff0c;在当今软件开发领域&#xff0c;Python作为一种简洁、易读且功能强大的编程语言&#xff0c;被广泛应用于各种领域。作为一名测试开发工程师&#xff0c;熟练掌握Python的模块、包和异常处理是提高代码可维护性和错误处理能力的关键。本文将和大家一起探讨Py…

Linux —— 信号量

Linux —— 信号量 什么是信号量P操作&#xff08;Wait操作&#xff09;V操作&#xff08;Signal操作&#xff09;信号量的类型 一些接口POSIX 信号量接口&#xff1a;其他相关命令&#xff1a; 基于循环队列的生产者和消费者模型同步关系 多生产多消费 我们今天接着来学习信号…

5.22R语言初步学习-1

今天上课讲R语言&#xff0c;要干什么没讲&#xff0c;分析什么&#xff0c;目的是什么没讲。助教基本上就是让我们打开窗口&#xff0c;按要求抄代码指令&#xff0c;代码原理也没讲......再加上最近正好在学概率论与数理统计&#xff0c;肯定是有用的&#xff0c;所以还是学习…