【算法】009、单双链表反转
【算法】009、单双链表反转
文章目录
- 一、单链表反转
- 1.1 实现思路
- 1.2 多语言解法
- 二、双链表反转
- 2.1 实现思路
- 2.2 多语言解法
一、单链表反转
1.1 实现思路
维护 pre 变量。
从前向后遍历 head,首先记录 next = head.next,其次反转指针使 head.next = pre. 再向后迭代使 pre = head,head = next。
直到遍历完 head == nil 为止。最终 pre 就是原链表的尾节点(即新链表的头节点),返回 pre 即可。
// go
package mainimport "fmt"// single
type Node struct {val intnext *Node
}func main() {la := la()laCheck(reverse(la))lb := lb()if reverse(lb) != lb {panic("error for lb")}lnil := lnil()if reverse(lnil) != nil {panic("error for nil")}print("ok")
}func la() *Node {a := &Node{val: 0}b := &Node{val: 1}c := &Node{val: 2}a.next = bb.next = creturn a
}func laCheck(h *Node) error {ans := make([]int, 0)for iter := h; iter != nil; iter = iter.next {ans = append(ans, iter.val)}if len(ans) != 3 {return fmt.Errorf("err len")}if ans[0] != 3 {return fmt.Errorf("err val")}if ans[1] != 1 {return fmt.Errorf("err val")}if ans[2] != 0 {return fmt.Errorf("err val")}return nil
}func lb() *Node {return &Node{val: 5, next: nil}
}func lnil() *Node {var n *Node = nilreturn n
}func reverse(head *Node) *Node {if head == nil {return nil}var pre *Node = nilvar next *Node = nilfor head != nil {next = head.next // 备份 head.next, 因为下一行就要改其指向了head.next = pre // 反转的关键, 指针方向变了, 原来 head.next 指向 next, 现在 head.next 指向 prepre = head // 向后迭代head = next // 同上}return pre
}
1.2 多语言解法
C p p / G o / P y t h o n / R u s t / J s / T s Cpp/Go/Python/Rust/Js/Ts Cpp/Go/Python/Rust/Js/Ts
// cpp
#include <iostream>
#include <vector>
#include <algorithm>using namespace std;
struct Node
{int val;Node *next;
};Node *la()
{Node *c = new Node{2, nullptr};Node *b = new Node{1, c};Node *a = new Node{0, b};return a;
}void laCheck(Node *head)
{vector<int> ans;Node *iter = head;while (iter != nullptr){ans.push_back(iter->val);iter = iter->next;}if (ans.size() != 3){throw runtime_error("length error");}if (ans[0] != 2){throw runtime_error("0 error");}if (ans[1] != 1){throw runtime_error("1 error");}if (ans[2] != 0){throw runtime_error("2 error");}
}Node *lb()
{return new Node{5, nullptr};
}void lbCheck(Node *head)
{vector<int> ans;Node *iter = head;while (iter){ans.push_back(iter->val);iter = iter->next;}if (ans.size() != 1){throw runtime_error("length error");}if (ans[0] != 5){throw runtime_error("5 error");}
}Node *lnone()
{return nullptr;
}Node *reverse(Node *head)
{Node *pre = nullptr;Node *iter = head;while (iter){Node *next = iter->next;iter->next = pre;pre = iter;iter = next;}return pre;
}int main()
{Node *l = la();Node *r = reverse(l);laCheck(r);l = lb();r = reverse(l);lbCheck(r);l = lnone();r = reverse(l);if (r != nullptr){throw runtime_error("error for lnone");}cout << "ok" << endl;
}
// go 同上
# python
class Node(object):def __init__(self, v, n):self.val = vself.next = ndef la():c = Node(2, None)b = Node(1, c)a = Node(0, b)return adef laCheck(n):ans = []while n:ans.append(n.val)n = n.nextif ans != [2, 1, 0]:raise ValueErrordef lb():return Node(5, None)def reverse(head):pre = Nonenext = Nonewhile head:next = head.nexthead.next = prepre = headhead = nextreturn predef main():l = la()l = reverse(l)laCheck(l)l = lb()if reverse(l) != l:raise ValueError(123)if reverse(None) != None:raise ValueError(111)print("ok")if __name__ == "__main__":main()
// rust
fn main() {let l = la();let r = reverse(l);la_check(r).expect("la_check");let l = lb();let r = reverse(l);lb_check(r).expect("lb_check");let l = lnone();let r = reverse(l);if r.is_some() {panic!("lnone");}println!("ok")
}#[derive(Debug)]
struct Node {val: i32,next: Option<Box<Node>>,
}impl Node {fn new(val: i32, next: Option<Box<Node>>) -> Self {Self { val, next }}
}fn la() -> Option<Box<Node>> {let c = Some(Box::new(Node::new(2, None)));let b = Some(Box::new(Node::new(1, c)));let a = Some(Box::new(Node::new(0, b)));a
}fn la_check(head: Option<Box<Node>>) -> Result<(), String> {let mut ans = vec![];let mut iter = head;while let Some(node) = iter {ans.push(node.val);iter = node.next;}if ans.len() != 3 {return Err("len".to_string());}if ans[0] != 2 {return Err("0".to_string());}if ans[1] != 1 {return Err("1".to_string());}if ans[2] != 0 {return Err("2".to_string());}Ok(())
}fn lb() -> Option<Box<Node>> {Some(Box::new(Node::new(5, None)))
}fn lb_check(head: Option<Box<Node>>) -> Result<(), String> {let mut ans = vec![];let mut head = head;while let Some(node) = head {ans.push(node.val);head = node.next;}if ans.len() != 1 {return Err("len".to_string());}if ans[0] != 5 {return Err("5".to_string());}Ok(())
}fn lnone() -> Option<Box<Node>> {None
}fn reverse(head: Option<Box<Node>>) -> Option<Box<Node>> {let mut head = head;let mut pre: Option<Box<Node>> = None;while let Some(mut node) = head {let next = node.next.take();node.next = pre;pre = Some(node);head = next;}pre
}
// js
// ts
function main() {let l = la();let r = reverse(l);laCheck(r);l = lb();r = reverse(l);lbCheck(r);l = lnone();r = reverse(l);if (r) {throw new Error("lnone");}console.log("ok");
}class ListNode {val: number;next: ListNode | null;constructor(val: number, next: ListNode | null) {this.val = val;this.next = next;}
}function la(): ListNode | null {const c = new ListNode(2, null);const b = new ListNode(1, c);const a = new ListNode(0, b);return a;
}function laCheck(head: ListNode | null) {const ans: number[] = [];let iter: ListNode | null = head;while (iter) {ans.push(iter.val);iter = iter.next;}if (ans.length !== 3) {throw new Error("length");}if (ans[0] !== 2) {throw new Error("0")}if (ans[1] !== 1) {throw new Error("1");}if (ans[2] !== 0) {throw new Error("2");}
}function lb(): ListNode {return new ListNode(5, null);
}function lbCheck(head: ListNode | null) {const ans: number[] = [];let iter: ListNode | null = head;while (iter) {ans.push(iter.val);iter = iter.next;}if (ans.length !== 1) {throw new Error("length");}if (ans[0] !== 5) {throw new Error("5");}
}function lnone(): ListNode | null {return null;
}function reverse(head: ListNode | null): ListNode | null {let pre: ListNode | null = null;while (head) {const next = head.next;head.next = pre;pre = head;head = next;}return pre;
}main();
二、双链表反转
2.1 实现思路
和 单链表反转 相同,每次反转两个指针即可,即 head.next = pre 和 head.pre = next。
package mainfunc main() {l := la()r := reverse(l)laCheck(r)l = lb()r = reverse(l)lbCheck(r)r = reverse(nil)if r != nil {panic("lnil")}println("ok")
}type Node struct {val intpre *Nodenext *Node
}func la() *Node {c := &Node{2, nil, nil}b := &Node{1, nil, c}a := &Node{0, nil, b}c.pre = bb.pre = areturn a
}func laCheck(h *Node) {ans := []int{}iter := hfor iter != nil {ans = append(ans, iter.val)iter = iter.next}if len(ans) != 3 {panic("length is not 3")}if ans[0] != 2 {panic("0 is not the first element")}if ans[1] != 1 {panic("1 is not the second element")}if ans[2] != 0 {panic("2 is not the third element")}
}
func lbCheck(h *Node) {ans := []int{}iter := hfor iter != nil {ans = append(ans, iter.val)iter = iter.next}if len(ans) != 1 {panic("length is not 3")}if ans[0] != 5 {panic("0 is not the first element")}
}func lb() *Node {return &Node{5, nil, nil}
}func reverse(h *Node) *Node {var pre *Node = niliter := hfor iter != nil {next := iter.nextiter.next = preiter.pre = nextpre = iteriter = next}return pre
}
2.2 多语言解法
C p p / G o / P y t h o n / R u s t / J s / T s Cpp/Go/Python/Rust/Js/Ts Cpp/Go/Python/Rust/Js/Ts
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;class Node
{
public:int val;Node *pre;Node *next;Node() : val(0), pre(nullptr), next(nullptr) {}Node(int val) : val(val), pre(nullptr), next(nullptr) {}Node(int val, Node *pre, Node *next) : val(val), pre(pre), next(next) {}
};Node *la()
{Node *c = new Node(2);Node *b = new Node(1);Node *a = new Node(0);a->next = b;b->next = c;c->pre = b;b->pre = a;return a;
}void la_check(Node *h)
{vector<int> ans;Node *iter = h;while (iter){ans.push_back(iter->val);iter = iter->next;}if (ans.size() != 3){throw new runtime_error("size");}if (ans[0] != 2){throw new runtime_error("0");}if (ans[1] != 1){throw new runtime_error("1");}if (ans[2] != 0){throw new runtime_error("2");}
}Node *lb()
{return new Node(5);
}void lb_check(Node *h)
{if (h == nullptr){throw new runtime_error("h null");}if (h->val != 5){throw new runtime_error("val");}
}Node *reverse(Node *h)
{Node *pre = nullptr;Node *iter = h;while (iter){Node *next = iter->next;iter->next = pre;iter->pre = next;pre = iter;iter = next;}return pre;
}int main()
{Node *l = la();Node *r = reverse(l);la_check(r);Node *l2 = lb();Node *rb = reverse(l2);lb_check(rb);Node *lnull = nullptr;if (reverse(nullptr)){throw new runtime_error("lnull");}cout << "ok" << endl;
}
# python
def main():l = la()r = reverse(l)la_check(r)l = lb()r = reverse(l)lb_check(r)l = Noner = reverse(l)if r is not None:raise Exception("error")print("ok")class Node(object):def __init__(self, val):self.val = valself.pre = Noneself.next = Nonedef la():c=Node(2)b=Node(1)a=Node(0)a.next = bb.next = cc.pre = bb.pre = areturn adef la_check(h):ans = []cur = hwhile cur:ans.append(cur.val)cur = cur.nextif ans != [2,1,0]:raise Exception("error")def lb():return Node(5)def lb_check(h):if h.val != 5:raise Exception("error")if h.next is not None:raise Exception("error")if h.pre != None:raise Exception("error")def reverse(h):pre = Nonecur = hwhile cur:next = cur.nextcur.next = precur.pre = nextpre = curcur = nextreturn preif __name__ == "__main__":main()
// rust
use std::cell::RefCell;
use std::rc::Rc;#[derive(Debug)]
struct Node {val: i32,prev: Option<Rc<RefCell<Node>>>,next: Option<Rc<RefCell<Node>>>,
}impl Node {fn new(val: i32) -> Self {Node {val,prev: None,next: None,}}
}fn la() -> Option<Rc<RefCell<Node>>> {let c = Rc::new(RefCell::new(Node::new(2)));let b = Rc::new(RefCell::new(Node::new(1)));let a = Rc::new(RefCell::new(Node::new(0)));a.borrow_mut().next = Some(b.clone());b.borrow_mut().next = Some(c.clone());c.borrow_mut().prev = Some(b.clone());b.borrow_mut().prev = Some(a.clone());Some(a)
}fn la_check(h: Option<Rc<RefCell<Node>>>) {let mut iter = h;let mut ans = Vec::new();while let Some(node) = iter {ans.push(node.borrow().val);iter = node.borrow().next.clone();}if ans.len() != 3 {panic!("length is not 3");}if ans[0] != 2 {panic!("0 error");}if ans[1] != 1 {panic!("1 error");}if ans[2] != 0 {panic!("2 error");}
}fn lb() -> Option<Rc<RefCell<Node>>> {Some(Rc::new(RefCell::new(Node::new(5))))
}fn lb_check(h: Option<Rc<RefCell<Node>>>) {let mut iter = h;let mut ans = Vec::new();while let Some(node) = iter {ans.push(node.borrow().val);iter = node.borrow().next.clone();}if ans.len() != 1 {panic!("length is not 1");}if ans[0] != 5 {panic!("0 error");}
}fn reverse(h: Option<Rc<RefCell<Node>>>) -> Option<Rc<RefCell<Node>>> {let mut cur = h;let mut pre: Option<Rc<RefCell<Node>>> = None;while let Some(node) = cur {let next = node.borrow_mut().next.take();node.borrow_mut().next = pre;node.borrow_mut().prev = next.clone();pre = Some(node);cur = next}pre
}fn main() {let l = la();let r = reverse(l);la_check(r);let l = lb();let r = reverse(l);lb_check(r);let l: Option<Rc<RefCell<Node>>> = None;let r = reverse(l);if r.is_some() {panic!("r is not None");}println!("ok");
}
function main() {let l = la();let r = reverse(l);la_check(r);l = lb();r = reverse(l);lb_check(r);r = reverse(null);if (r) {throw new Error("lnull error")}console.log("ok")
}class ListNode {val: number;prev: ListNode | null;next: ListNode | null;constructor(val: number) {this.val = val;this.prev = null;this.next = null;}
}function la(): ListNode | null {const c = new ListNode(2);const b = new ListNode(1);const a = new ListNode(0);a.next = b;b.next = c;c.prev = b;b.prev = a;return a;
}function la_check(h: ListNode | null) {let ans: number[] = [];let iter: ListNode | null = hwhile (iter) {ans.push(iter.val);iter = iter.next;}if (ans.length != 3) {throw new Error("length error")}if (ans[0] != 2) {throw new Error("0 error")}if (ans[1] != 1) {throw new Error("1 error")}if (ans[2] != 0) {throw new Error("2 error")}
}function lb(): ListNode | null {return new ListNode(5);
}function lb_check(h: ListNode | null) {if (!h) {throw new Error("h null error")}if (h.val != 5) {throw new Error("5 error")}if (h.next) {throw new Error("next error")}if (h.prev) {throw new Error("prev error")}
}function reverse(h: ListNode | null): ListNode | null {let iter: ListNode | null = h;let prev: ListNode | null = null;while (iter) {let next = iter.next;iter.next = prev;iter.prev = next;prev = iteriter = next}return prev
}main();
相关文章:
【算法】009、单双链表反转
【算法】009、单双链表反转 文章目录 一、单链表反转1.1 实现思路1.2 多语言解法 二、双链表反转2.1 实现思路2.2 多语言解法 一、单链表反转 1.1 实现思路 维护 pre 变量。 从前向后遍历 head,首先记录 next head.next,其次反转指针使 head.next pr…...
物联网设备接入系统后如何查看硬件实时数据?
要在软件中实时查看硬件设备的信息,通常需要结合前后端技术来实现。以下是设计思路和实现步骤: 1. 系统架构设计 实时查看硬件设备信息的系统通常采用以下架构: 数据采集层: 硬件设备通过传感器采集数据,发送到InfluxDB。数据存…...
【Linux系统编程】初识系统编程
目录 一、什么是系统编程1. 系统编程的定义2. 系统编程的特点3. 系统编程的应用领域4. 系统编程的核心概念5. 系统编程的工具和技术 二、操作系统四大基本功能1. 进程管理(Process Management)2. 内存管理(Memory Management)3. 文…...
解决stylelint对deep报错
报错如图 在.stylelintrc.json的rules中配置 "selector-pseudo-class-no-unknown": [true,{"ignorePseudoClasses": ["deep"]} ]...
React基础之useInperativehandlle
通过ref调用子组件内部的focus方法来实现聚焦 与forwardRef类似,但是forwardRef是通过暴露整个Ref来实现,而useInperativehandle是通过对外暴露一个方法来实现的 import { forwardRef, useImperativeHandle, useRef, useState } from "react";…...
使用joblib 多线程/多进程
文章目录 1. Joblib 并行计算的两种模式多进程(Multiprocessing,适用于 CPU 密集型任务)多线程(Multithreading,适用于 I/O 密集型任务)2. Joblib 的基本用法3. Joblib 多进程示例(适用于 CPU 密集型任务)示例:计算平方4. Joblib 多线程示例(适用于 I/O 密集型任务)…...
⭐算法OJ⭐N-皇后问题 II【回溯剪枝】(C++实现)N-Queens II
⭐算法OJ⭐N-皇后问题【回溯剪枝】(C实现)N-Queens 问题描述 The n-queens puzzle is the problem of placing n n n queens on an n n n \times n nn chessboard such that no two queens attack each other. Given an integer n, return the num…...
【数据结构初阶】---堆的实现、堆排序以及文件中的TopK问题
1.树的概念及结构 1.1树的概念 树是一种非线性的数据结构,它是由n(n>0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。 有一个特殊的结点&…...
ubuntu20系统下conda虚拟环境下安装文件存储位置
在 Conda 虚拟环境中执行 pip install 安装软件后,安装的文件会存储在该虚拟环境专属的 site-packages 目录中。具体路径取决于你激活的 Conda 环境路径。以下是定位步骤: 1. 确认 Conda 虚拟环境的安装路径 查看所有环境: conda info --env…...
鸿蒙开发:RelativeContainer 相对布局详解【全套华为认证学习资料分享(考试大纲、培训教材、实验手册等等)】
前言 在最新版本的 DevEco Studio 中,官方在创建新项目时,默认使用 RelativeContainer 组件作为根布局。这足以证明 RelativeContainer 的重要性。相比其他容器组件,它极大地简化了复杂 UI 布局中的元素对齐问题。 例如,在没有 R…...
基于SpringBoot实现旅游酒店平台功能一
一、前言介绍: 1.1 项目摘要 随着社会的快速发展和人民生活水平的不断提高,旅游已经成为人们休闲娱乐的重要方式之一。人们越来越注重生活的品质和精神文化的追求,旅游需求呈现出爆发式增长。这种增长不仅体现在旅游人数的增加上࿰…...
HttpServletRequest 和 HttpServletResponse 区别和作用
一、核心作用对比 对象HttpServletRequest(请求对象)HttpServletResponse(响应对象)本质客户端发给服务器的 HTTP 请求信息(输入)服务器返回客户端的 HTTP 响应信息(输出)生命周期一…...
树莓派学习(一)——3B+环境配置与多用户管理及编程实践
树莓派学习(一)——3B环境配置与多用户管理及编程实践 一、实验目的 掌握树莓派3B无显示器安装与配置方法。学习Linux系统下多用户账号的创建与管理。熟悉在树莓派上使用C语言和Python3编写简单程序的方法。 二、实验环境 硬件设备:树莓派…...
Mysql安装方式
方式一:安装包安装 下载安装包 官网直接下载:https://dev.mysql.com/downloads/ 安装配置 2.1、双击刚刚下载好的msi文件,开始安装MySQL。 2.2、选择自定义模式Custom安装 2.3、点击选择自己电脑对应的mysql安装目录 2.5、继续点击下一步&…...
Vue3实战学习(Vue3的基础语法学习与使用(超详细))(3)
目录 (1)Vue3工程环境准备、项目基础脚手架搭建详细教程。(博客链接) (2)Vue3的基础语法学习与使用。 (1)"{{}}"绑定数据。 <1>ref()函数定义变量——绑定数据。 <2>reactive({...})…...
使用websocket,注入依赖service的bean为null
问题:依赖注入失败,service获取不到,提示null 这是参考代码 package com.shier.ws;import cn.hutool.core.date.DateUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.google.gson.Gson; import com.s…...
批量在 Word 的指定位置插入页,如插入封面、末尾插入页面
我们经常会碰到需要在 Word 文档中插入新的页面的需求,比如在 Word 文档末尾插入一个广告页、给 Word 文档插入一个说明封面,在 Word 文档的中间位置插入新的页面等等。相信这个操作对于大部分小伙伴来说都不难,难的是同时给多个 Word 文档插…...
算法系列之滑动窗口
算法系列之滑动窗口 题目 给定一个字符串 s ,请你找出其中不含有重复字符的 最长 子串 的长度。 示例 1:输入: s "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。 示例 2:输入: s "bbbbb"…...
【C#】详解C#中的内存管理机制
文章目录 前言一、C#内存管理的基本机制(1)托管堆(Managed Heap)(2)垃圾回收(Garbage Collection)(3)栈内存 二、 开发者需要主动管理的场景(1&am…...
C/S架构与B/S架构
一、定义与核心区别 C/S架构(Client/Server,客户端/服务器) 客户端需安装专用软件(如QQ、企业ERP系统),直接与服务器通信。服务器端通常包括数据库和业务逻辑处理1。特点:客户端承担部分计算任务…...
IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...
STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...
PostgreSQL——环境搭建
一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在࿰…...
二维FDTD算法仿真
二维FDTD算法仿真,并带完全匹配层,输入波形为高斯波、平面波 FDTD_二维/FDTD.zip , 6075 FDTD_二维/FDTD_31.m , 1029 FDTD_二维/FDTD_32.m , 2806 FDTD_二维/FDTD_33.m , 3782 FDTD_二维/FDTD_34.m , 4182 FDTD_二维/FDTD_35.m , 4793...
