leetcode LCR24反转单链表

反转单链表

题目描述

题目分析 

先来说迭代的思想:

上面next = cur->next应该放在cur->next = pre前面执行,这里笔误 

再来说递归的思想:

 题目代码

这个代码里面我加了我自己写的测试数据,自己可以去找对应的部分,直接粘贴赋值就可以在leetcode提交成功,我们就没有把迭代与递归单独分开了,里面还有大量的注释说明,请结合题目分析仔细观看

java版本

package com.pxx.test;

import sun.awt.image.ImageWatched;

class LinkList {
    private ListNode head;
    private int length;//长度

    //链表结点的一个定义
    static class ListNode {
        int value;
        ListNode next;

        //初始化一个结点
        public ListNode(int value) {
            this.value = value;
            this.next = null;
        }
    }

    public ListNode getHead() {
        return this.head;
    }

    //实现数据的尾插
    public void insertEnd(int value) {
        ListNode newNode = new ListNode(value);
        if (newNode != null) {
            if (head == null) {
                head = newNode;//指向第一个结点
            } else {
                ListNode cur = head;
                //移动到最后一个结点的位置
                while (cur.next != null) {
                    cur = cur.next;
                }

                //最后一定是在cur加入结点
                cur.next = newNode;
            }
            length++;
        }
    }

    //打印
    public void printList(ListNode head) {
        ListNode cur = head;
        while (cur != null) {
            System.out.print(cur.value + " ");
            cur = cur.next;
        }
        System.out.println();
    }

    //利用递归反转链表
    //返回反转之后的链表头
    public ListNode reverse(ListNode head) {
        //安全检查都必须先进行操作
        if (head == null || head.next == null) {
            return head;
        } else {
            ListNode pre = head , cur = head.next;
            //接收最后一次的返回,就是最后一个节点,中间是没有结点要返回的
            //这里为什么传入pre.next,而不是cur.next
            //目的其实就是为了每一个值都能被链上,为什么那么说呢
            //1(pre) 2(cur) 3 4 5
            //如果按照cur.next来进行移动
            //1 <- 2这一部分递归了之后,就会进入 3(pre(cur会直接到3变成pre))   4(内部的cur)
            //那么我请问2 3中间这条线被狗吃了吗?所以以pre.next往下递归
            //上面pre循环到5号结点,也就是最后一组递归就要结束,因此有head.next = null就结束递归
            ListNode res = reverse(pre.next);
            cur.next = pre;
            //目的把第一个结点的next指向null
            //这里千万不能吧pre.next 与 cur.next进行比较
            //否则会造成最开头的两个数据一直轮替
            //这样来说 1  2  3  4(pre)  5(cur)假设当前指针是这样来指的
            //4 <- 5 此时4也还是4->5的,进入pre.next把指向变为了null(注意这是递归所以从后往前分析)
            //不太懂的请结合我的递归分析图来看
            //null <- 4 <- 5
            //那么就行往前递归3(pre) 4(cur) 5,也就是null <- 3 <- 4 <- 5
            //我们注意到一个问题就是4的pre已经在中间的时候被改向了第一个结点
            //那么对于1(pre) <- 2(cur)来说,1的.next又等于cur,所以1.pre = null
            //null <- 1 <- 2......这个时候,程序已经全部执行完
            if (pre.next == cur) {
                pre.next = null;
            }
            return res;
        }
    }

    //利用迭代思想实现
    public ListNode reverse1(ListNode head) {
        //空结点,直接返回一个null
        if (head == null) {
            return null;
        }
        //定义三个指针进行迭代
        ListNode pre = head, cur = head.next, next;//next用于在中间轮替指针可以先不用初值
        //没循环之前先把第一个结点next指向null
        head.next = null;
        while (cur != null) {
            //这里迭代就是
            // null <- 1(pre) 2(cur) 3(next) 4        5
            // null <- 1 <-   2(pre) 3(cur)  4(next)  5
            // null <- 1 <-   2 <-   3(pre)  4(cur)   5(next)
            // null <- 1 <-   2 <-   3 <-    4(pre)   5(cur)   next(这个时候还会进入循环里面更改cur.next指针)
            //这个时候cur == null,结束,pre指向最后一个结点返回

            //保留next指向
            next = cur.next;//这一步必须放在cur.next前面,不然cur.next就被先改变了,next的位置就不对了
            cur.next = pre;
            //改变pre与cur
            pre = cur;//这一步放在cur=next,这里就是先赋值pre,在改变cur
            cur = next;
        }
        //最后一定是pre指向了最后一个结点
        return pre;
    }

}


public class Test4 {

    public static void main(String[] args) {
        LinkList linkList = new LinkList();

        //开始插入数据
        linkList.insertEnd(1);
        linkList.insertEnd(2);
        linkList.insertEnd(3);
//        linkList.insertEnd(4);
//        linkList.insertEnd(5);


        linkList.printList(linkList.getHead());

        //反转链表
        LinkList.ListNode head = linkList.reverse(linkList.getHead());

        linkList.printList(head);

    }
}

 c语言版本测试代码,仅做参考

#include <stdio.h>
#include <stdlib.h>

// 链表结点的定义
struct ListNode {
    int value;
    struct ListNode* next;
};

// 链表的定义
struct LinkedList {
    struct ListNode* head;
    int length;
};

// 初始化链表
void initLinkedList(struct LinkedList* list) {
    list->head = NULL;
    list->length = 0;
}

// 在链表末尾插入一个新节点
void insertEnd(struct LinkedList* list, int value) {
    struct ListNode* newNode = (struct ListNode*)malloc(sizeof(struct ListNode));
    if (newNode != NULL) {
        newNode->value = value;
        newNode->next = NULL;

        if (list->head == NULL) {
            list->head = newNode;
        } else {
            struct ListNode* cur = list->head;
            while (cur->next != NULL) {
                cur = cur->next;
            }
            cur->next = newNode;
        }
        list->length++;
    }
}

// 打印链表的元素
void printList(struct ListNode* head) {
    struct ListNode* cur = head;
    while (cur != NULL) {
        printf("%d ", cur->value);
        cur = cur->next;
    }
    printf("\n");
}

// 递归反转链表
struct ListNode* reverse(struct ListNode* head) {
    if (head == NULL || head->next == NULL) {
        return head;
    } else {
        struct ListNode* pre = head;
        struct ListNode* cur = head->next;
        struct ListNode* res = reverse(pre->next);
        cur->next = pre;
        if (pre->next == cur) {
            pre->next = NULL;
        }
        return res;
    }
}

int main() {
    struct LinkedList linkList;
    initLinkedList(&linkList);

    // 开始插入数据
    insertEnd(&linkList, 1);
    insertEnd(&linkList, 2);
    insertEnd(&linkList, 3);

    printList(linkList.head);

    // 反转链表
    linkList.head = reverse(linkList.head);

    printList(linkList.head);

    return 0;
}

好了,祝早安,午安,晚安

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

springboot整合redis+自定义注解+反射+aop实现分布式锁

1.定义注解 import java.lang.annotation.*; import java.util.concurrent.TimeUnit;/** Author: best_liu* Description:* Date: 16:13 2023/9/4* Param * return **/ Retention(RetentionPolicy.RUNTIME) Target({ElementType.METHOD}) Documented public interface RedisLo…

OpenCV | 傅里叶变换——低通滤波器与高通滤波器

import cv2 #opencv 读取的格式是BGR import numpy as np import matplotlib.pyplot as plt #Matplotlib是RGB %matplotlib inline def cv_show(img,name):cv2.imshow(name,img)cv2.waitKey()cv2.destroyAllWindows() 傅里叶变换 傅里叶变换的作用 高频&#xff1a;变化剧烈…

Java抽象类:类的幕后黑手,提供继承和扩展的框架。

&#x1f451;专栏内容&#xff1a;Java⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;前路未远&#xff0c;步履不停 目录 一、抽象类的概念二、注意事项三、抽象类的作用 一、抽象类的概念 在面向对象的概念中&#xff0c;所有的对象都是通过类来描绘…

Facebook的这份开源协议使React四面楚歌

如果你觉得一些科技公司看起来很美好&#xff0c;每天都在“改变世界”……你应该看看他们的用户条款和法律文书&#xff0c;藏污纳垢之严重令人震惊。 最近&#xff0c;百度和阿里巴巴内部的软件工程团队不约而同做了一件事——弃用 React。 解释下&#xff1a; React 是一个…

Web框架与Django路由层

Web框架 一 web框架 Web框架&#xff08;Web framework&#xff09;是一种开发框架&#xff0c;用来支持动态网站、网络应用和网络服务的开发。这大多数的web框架提供了一套开发和部署网站的方式&#xff0c;也为web行为提供了一套通用的方法。web框架已经实现了很多功能&…

MicroPython STM32F4 RTC功能使用介绍

MicroPython STM32F4 RTC功能使用介绍 &#x1f516;STM32和ESP32 RTC功能差不多&#xff0c;相关篇《MicroPython ESP32 RTC功能使用介绍》&#x1f4cc;固件刷可参考前面一篇《STM32刷Micropython固件参考指南》&#x1f33f; 相关篇《Micropython STM32F4入门点灯》&#x1…

java设计模式 开闭原则

开闭原则&#xff08;Open-Closed Principle&#xff0c;OCP&#xff09;是面向对象设计中的一个重要原则&#xff0c;它指导着我们如何设计和组织代码&#xff0c;以便使系统在扩展性和可维护性方面更加优秀。 开闭原则的定义是&#xff1a;软件实体&#xff08;类、模块、函数…

纵行科技获评“汽车物流行业优秀技术装备供应商”

近日&#xff0c;由中国物流与采购联合会主办&#xff0c;中物联汽车物流分会承办的“2023年全国汽车物流行业年会”在湖北十堰盛大召开。本次年会集合了汽车整车、零部件、售后备件、进出口物流企业和物流装备技术企业、科研机构及院校等&#xff0c;分享汽车物流行业现状、相…

java文件上传以及使用阿里云OSS

JavaWeb 文件上传本地存储阿里云OSS配置文件 yml配置文件 文件上传 前端页面三要素&#xff1a; 表单项type“file” 表单提交方式post 表单的enctype属性multipart/form-data 本地存储 保证上传的文件不重复 //获取原始文件名String originalFilename image.getOriginalFi…

0-1背包的初始化问题

题目链接 这道题的状态转移方程比较易于确定。dp[i][j]表示能放前i个物品的情况下&#xff0c;容量为j时能放物品的数量&#xff08;这道题歌曲数量对应物品数量&#xff0c;容量对应时间&#xff09;。 技巧&#xff08;收获&#xff09; 二维dp数组可以视情况优化为一维dp数组…

Spring Boot 3 + Spring Security 6 最新版本修改 Json 登录后 RememberMe 功能问题失效的解决方案

当 Spring Boot 版本更新到 3 之后&#xff0c;最低要求的 JDK 版本变为 17&#xff0c;相应的 最新版本的 Spring Security 的配置也发生了变化&#xff0c;一下主要讲解一些新的 Spring Security 的配置方法 1. 配置由继承WebSeucrityConfigurerAdapter变成只需添加一个Secur…

人工智能-优化算法之梯度下降

梯度下降 尽管梯度下降&#xff08;gradient descent&#xff09;很少直接用于深度学习&#xff0c; 但了解它是理解下一节随机梯度下降算法的关键。 例如&#xff0c;由于学习率过大&#xff0c;优化问题可能会发散&#xff0c;这种现象早已在梯度下降中出现。 同样地&#x…

一款多功能露营专用氛围灯

一、主要功能 使用COB灯丝3D打印构建精妙的螺旋线条露营灯 选用IP5328P作为电源主控&#xff0c;支持双向PD快充&#xff0c;支持PPS档位输出 电池仓结构设计兼容26650&#xff08;不可更换&#xff09;或21700/18650&#xff08;可更换&#xff09;电池 使用WS2812灯组成顶…

内置函数【MySQL】

文章目录 MySQL 内置函数日期和时间函数字符串函数数学函数信息函数参考资料 MySQL 内置函数 MySQL 的内置函数主要分为以下几种&#xff1a; 字符串函数&#xff1a;用于对字符串进行操作&#xff0c;如连接、截取、替换、反转、格式化等。数值函数&#xff1a;用于对数值进…

【vue】v-model在表单元素上的应用

表单元素&#xff1a; https://blog.csdn.net/m0_67930426/article/details/134655644 使用模板 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head><body>&l…

小程序静默授权获取unionid

文章目录 导文文章重点 导文 小程序静默授权获取unionid 文章重点 用wx.login(Object object)放到app.js里面 wx.login({success (res) {console.log(123);if (res.code) {//发起网络请求// wx.request({// url: https://example.com/onLogin,// data: {// code: res.…

软著项目推荐 深度学习二维码识别

文章目录 0 前言2 二维码基础概念2.1 二维码介绍2.2 QRCode2.3 QRCode 特点 3 机器视觉二维码识别技术3.1 二维码的识别流程3.2 二维码定位3.3 常用的扫描方法 4 深度学习二维码识别4.1 部分关键代码 5 测试结果6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天…

linux获得帮助_如何查看命令的用法、作用

Linux获得帮助 多层次的帮助&#xff1a; whatis command --help man and info /usr/share/doc/ Red Hat documentation 、Ubuntu documentation 软件项目网站 其它网站 搜索 whatis 使用数据库来显示命令的简短描述。 [rootlocalhost ~]# whatis rm rm (1) …

基于FPGA的五子棋游戏设计

基于FPGA的五子棋游戏设计 本文基于FPGA设计五子棋游戏&#xff0c;使用按键输入&#xff0c;使用VGA接口输出。五子棋的棋具与围棋相同&#xff0c;棋子分为黑白两色&#xff0c;棋盘为1010&#xff0c;棋子放置于棋盘线交叉点上。两人对局&#xff0c;各执一色&#xff0c;轮…

仿美团外卖源码/在线外卖平台源码PHP/支持多商户+多样化配送费+本土外卖+支持第三方配送

源码简介&#xff1a; 进云仿美团外卖源码&#xff0c;作为外卖平台源码&#xff0c;它不仅支持多商户、多样化配送费、本土外卖&#xff0c;还支持第三方配送。 进云仿美团外卖源码是一个进云源生插件&#xff0c;支持多商户多样化配送费模式本土外卖平台支持第三方配送&…