数据结构与算法之链表: LeetCode 148. 排序链表 (Ts, Py, Go版)

TS数据结构分析 1.TS包得数据结构 2. // Transport packet header typedef struct TS_packet_header {     unsigned sync_byte                                         :    8;    //同步字节,固定为0x47 ,表示后面的是一个TS分组,当然,后面包中的数 阅读详情

排序链表

  • https://leetcode.cn/problems/sort-list/

描述

  • 给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。

示例 1

输入:head = [4,2,1,3]
输出:[1,2,3,4]

示例 2

输入:head = [-1,5,3,4,0]
输出:[-1,0,3,4,5]

示例 3

输入:head = []
输出:[]

提示

  • 链表中节点的数目在范围 [0, 5 * 10410^4104] 内
  • -10510^5105 <= Node.val <= 10510^5105

进阶

  • 你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?

Typescript 版算法实现

1 )方案 1

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     val: number
 *     next: ListNode | null
 *     constructor(val?: number, next?: ListNode | null) {
 *         this.val = (val===undefined ? 0 : val)
 *         this.next = (next===undefined ? null : next)
 *     }
 * }
 */

function sortList(head: ListNode | null): ListNode | null {
    const map = new Map()
    while(head) {
        map.set(head.val, head) // 存储键值对
        const next = head.next
        if (!next) break
        head = next // 当前指向next
    }
    if (!map.size) return head
    // 基于map来存储
    const sortList:number[] = []
    map.forEach((v, k)=>{
        sortList.push(k)
    })
    // 对sortList进行排序 默认升序
    sortList.sort()
    // 对数组进行处理
    let first:ListNode | null = new ListNode()
    for(let i = 0, len = sortList.length; i < len; i ++) {
        const v = sortList[i]
        const current:ListNode | null = map.get(v) || null
        if (!i) first = current
        if (!current || !sortList.length) break;
        current.next = map.get(sortList[i + 1]) || null;
    }
    return first
};
  • 解题思路
    • 使用map和数组的结构来存储
    • 将链表的val作为map的键,当前节点作为值
    • 将map的所有val存入数组,对数组进行排序
    • 循环读取排序后的数组元素,将元素作为map的key来读取对应节点
    • 逐个将当前节点的next指向到下一个节点
  • 关于时间复杂度
    • 此算法最耗时的应该是 Array.prototype.sort() 这个api了
    • 这个内部实现都是基于浏览器来决定的,一般是 O(nlogn)
    • 所以,这个算法的时间复杂度是 O(nlogn)
  • 这种适应场景有限,针对示例上的用例是可以过的
  • 如果遇到重复的,使用map的数据结构,就会无法处理
  • 所以,此种方案仅适用于开阔下思路,因此不推荐使用
  • 这是反面教材

2 )方案 2

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     val: number
 *     next: ListNode | null
 *     constructor(val?: number, next?: ListNode | null) {
 *         this.val = (val===undefined ? 0 : val)
 *         this.next = (next===undefined ? null : next)
 *     }
 * }
 */

function sortList(head: ListNode | null): ListNode | null {
    let arr: ListNode[] = [];
    let current: ListNode = head;
    while (current) {
        arr.push(current);
        current = current.next;
    }
    arr = arr.sort((a, b) => a.val - b.val);
    if (!arr.length) return head
    head = arr[0];
    let c: ListNode = head;
    for (let i = 1; i < arr.length; i++) {
        c.next = arr[i];
        c = arr[i];
    }
    arr[arr.length - 1].next = null;
    return head;
};
  • 这个示例程序是官方提供的,我这边稍微进行了一下改动优化
  • 这个程序明显比方案1简洁不少,相比方案1而言,方案1处理显得冗余并且出错了
  • 直接使用数组来存储节点,对节点的排序基于val属性进行排序
  • 之后再对排好序的节点进行遍历来寻找后继
  • 此方案推荐,时间复杂度和方案一一致

Python3 版算法实现

1 )方案1

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        if not head or not head.next:  
            return head  
        
        # 使用字典来存储节点值作为键,节点对象作为值  
        node_map = {}  
        current = head  
        while current:  
            node_map[current.val] = current  
            current = current.next  
        
        # 从字典的键中获取一个列表,并对其进行排序  
        sorted_vals = sorted(node_map.keys())  
        
        # 创建一个哑节点作为排序后链表的头部  
        dummy = ListNode(0)  
        prev_node = dummy  # 用来跟踪当前正在处理的节点的前一个节点  
        
        # 根据排序后的值数组来重建链表  
        for val in sorted_vals:  
            prev_node.next = node_map[val]  
            prev_node = prev_node.next  
            prev_node.next = None  # 将当前节点的next指针设置为None,防止循环引用  
        
        # 返回排序后链表的头部(跳过哑节点)  
        return dummy.next 
  • 同ts版本是反面教材
  • 处理不了重复的场景
  • 仅供参考

2 )方案2

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        if not head or not head.next:  
            return head  
        
        # 将链表元素转换为列表  
        arr = []  
        current = head  
        while current:  
            arr.append(current)  
            current = current.next  
        
        # 对列表进行排序  
        arr.sort(key=lambda x: x.val)  
        
        # 将排序后的列表重新构建为链表  
        if not arr:  
            return head  
        head = arr[0]  
        c = head  
        for i in range(1, len(arr)):  
            c.next = arr[i]  
            c = arr[i]  
        
        # 将最后一个节点的next设为None  
        arr[-1].next = None  
        
        return head  

Golang 版算法实现

1 )方案1

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func sortList(head *ListNode) *ListNode { 
	if head == nil || head.Next == nil {  
		return head  
	}  
  
	// Use a map to store the values as keys and node pointers as values.  
	nodeMap := make(map[int]*ListNode)  
	current := head  
	for current != nil {  
		nodeMap[current.Val] = current  
		current = current.Next  
	}  
  
	// Get a slice of the keys and sort them.  
	sortedVals := make([]int, 0, len(nodeMap))  
	for val := range nodeMap {  
		sortedVals = append(sortedVals, val)  
	}  
	sort.Ints(sortedVals)  
  
	// Create a dummy node to be the head of the sorted list.  
	dummy := &ListNode{}  
	prevNode := dummy  
  
	// Rebuild the list based on the sorted values.  
	for _, val := range sortedVals {  
		prevNode.Next = nodeMap[val]  
		prevNode = prevNode.Next  
		prevNode.Next = nil // Set the next pointer to nil to avoid circular references.  
	}  
  
	// Return the head of the sorted list (skipping the dummy node).  
	return dummy.Next  
}  
  • 同ts版本是反面教材
  • 处理不了重复的场景
  • 仅供参考

2 )方案2

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */

func sortList(head *ListNode) *ListNode {  
	if head == nil || head.Next == nil {  
		return head  
	}  
  
	// 链表转换为切片  
	nodes := make([]*ListNode, 0)  
	current := head  
	for current != nil {  
		nodes = append(nodes, current)  
		current = current.Next  
	}  
  
	// 对切片进行排序 这里,leetcode 上不用 import
	sort.Slice(nodes, func(i, j int) bool {  
		return nodes[i].Val < nodes[j].Val  
	})  
  
	// 重新构建链表  
	if len(nodes) == 0 {  
		return nil  
	}  
  
	head = nodes[0]  
	current = head  
	for i := 1; i < len(nodes); i++ {  
		current.Next = nodes[i]  
		current = current.Next  
	}  
	current.Next = nil // 设置最后一个节点的 Next 为 nil  
  
	return head  
}

3 )方案3

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func sortList(head *ListNode) *ListNode { 
	if head == nil || head.Next == nil {  
		return head  
	}  
  
	// 使用切片来存储节点值,并对其进行排序  
	var vals []int  
	current := head  
	for current != nil {  
		vals = append(vals, current.Val)  
		current = current.Next  
	}  
  
	// 对切片进行排序  
	sort.Ints(vals)  
  
	// 创建一个哑节点作为排序后链表的头部  
	dummy := &ListNode{}  
	prevNode := dummy  
  
	// 根据排序后的值切片来重建链表  
	for _, val := range vals {  
		prevNode.Next = &ListNode{Val: val}  
		prevNode = prevNode.Next  
	}  
  
	// 返回排序后链表的头部(跳过哑节点)  
	return dummy.Next  
}
  • 这个是方案2 的优化版本
数据结构和算法TS:以TypeScript(完整)实现的数据结构和算法 TypeScript中的数据结构和算法 主题概述 算法复杂度分析 大O符号 时间复杂度 空间复杂度 数据结构 数组 哈希表 堆栈 s列 链表 树木 图表 演算法 递归 动态编程 比较排序 合并排序 快速排序 正在搜寻 线性搜寻 二元搜寻 BFS和DFS 环境 迪诺1.2.1 V8 8.5.216 打字稿3.9.2 资源资源 策划文章 立即下载

相关推荐

ECC椭圆曲线加解密原理详解(配图)

椭圆曲线加解密原理详解 本文主要参照:ECC椭圆曲线详解(有具体实例)[1] 前言: 椭圆曲线(ECC)加密原理跟RSA加解密原理比起来,可真是晦涩难懂。拜读了大神Kalafinaian文章“ECC椭圆曲线详解(有具体实例)”,终于看到了参透的曙光。 由于原文中有微小的瑕疵,也为了便于阅读起来更加流畅,我重新整理了一下这篇文章。 为什么使用椭圆曲线加密算法? RSA的解决分解整数问题需要亚指数...

Mark的博客 7万+

typescript常见数据结构与算法

吸取了之前刷题的教训,近期系统的学习了下数据结构,并理解性的对常用的数据结构进行封装,颇有收获。

一缕阳光@的博客 1510

阿里云CDN HTTPS 证书配置流程

可以使用HTTPS方式访问资源,如果浏览器中URL旁边出现锁的HTTPS标识,表示HTTPS安全加速已生效。: 证书配置完成后,需要留意证书过期时间并在证书过期前手动配置新的证书。注意 ⚠️ 一定是需要复制 以下标识之间的内容。如果已在阿里云数字证书管理服务中购买了证书,请选择。,该证书将在阿里云数字证书管理服务中保存。如果使用第三方服务商签发的证书,请选择。第四步,在指定域名的左侧导航栏,单击。第二步,在左侧导航栏,单击。开关,并配置证书相关参数。页面,找到目标域名,单击。中选择已购买的证书。

w风雨无阻w的专栏 2212

常见数据结构和算法(Typescript)

线性结构由n个元素组成的。常用的线性结构有:线性表,栈,队列,双队列,数组。数组的内存是连续的,因此在知道下标的情况下,访问效率是很高的。(早起JavaScript的数组内存实现并不是连续的。

m0_62475892的博客 743

555定时器呼吸灯电路制作全攻略:从仿真到实物搭建(附避坑指南)

本文详细介绍了使用555定时器制作呼吸灯电路的完整流程,从基础原理到实物搭建,包括电路设计、元件选择、仿真验证、焊接技巧及调试优化。特别提供了避坑指南,帮助电子爱好者快速掌握这一经典DIY项目,实现美观的呼吸灯效果。

weixin_33734785的博客 403

《网络摄像机实战11:flutter_webrtc支持 AWS Kinesis Video Streams信令服务器》

本文介绍了如何在Flutter项目中集成WebRTC实现网络摄像头的实时视频和音频对讲功能。通过使用flutter_webrtc插件,开发者可以快速构建跨平台的视频通信应用。文章详细说明了集成步骤:1)安装flutter_webrtc插件;2)配置信令服务器和KVS服务;3)初始化本地/远程视频渲染器;4)建立WebRTC连接并进行设备呼叫。最后展示了实际应用效果图,证明该方案能有效实现移动端与摄像头的实时音视频交互。该方案为开发智能家居监控等应用提供了技术参考。

lvj_158的专栏 356

数据结构与算法之链表: LeetCode 141. 环形链表 (Ts, Py, Go版)

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递。仅仅是为了标识链表的实际情况。如果链表中存在环 ,则返回 true。否则,返回 false。给你一个链表的头节点 head ,判断链表中是否有环。

Wang的专栏 682

YOLOv11改进,YOLOv11添加DCNv4可变性卷积(windows系统成功编译),二次创新C3k2结构,全网最详细教程

引入了可变形卷积 v4 (DCNv4),这是一种为广泛视觉应用设计的高效且有效的操作算子。DCNv4通过两项关键增强解决了其前身DCNv3的局限性:1. 移除空间聚合中的softmax归一化,以增强其动态特性和表达能力;2. 优化内存访问以最小化冗余操作,从而加速计算。这些改进使得DCNv4相比DCNv3显著加快了收敛速度,并且处理速度大幅提升,前向传播速度超过三倍。DCNv4在多个任务中表现出色,包括图像分类、实例和语义分割,特别是在图像生成方面表现突出。

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 2667

重读《学习JavaScript数据结构与算法-第三版》-第2章 ECMAScript与TypeScript概述

洛伊安妮·格罗纳女士所著的《学习JavaScript数据结构与算法》第三版于2019年的5月份再次刊印发行,新版内容契合当下,实为JavaScript开发人员的必备之佳作。有幸重读此版,与诸君分享共勉。

胡哥有话说 542

EtherCAT ROS2 入门教程(一)

本文介绍了EtherCAT驱动与ROS2的集成方案,主要包括三部分内容:1)在Ubuntu 22.04上安装IgH EtherCAT主站的详细步骤,包括内核配置、源码编译和网络适配器设置;2)构建ethercat_driver_ros2,通过ros2_control描述文件配置硬件接口和EtherCAT从站模块插件;3)使用方法,包括启动EtherCAT主站和运行配置包。该方案支持通过参数文件定义硬件接口,并提供通用和专用两种EtherCAT模块插件,便于开发基于EtherCAT的工业应用。

机器人控制与仿真应用 1531

Hermes Agent 常见报错排查与问题解决

Hermes Agent 常见报错排查指南 摘要 本文全面梳理了 Hermes Agent 使用过程中的10类常见报错,按阶段划分为安装期、运行期认证类、后端基础设施类和长任务执行类四大类,并提供了系统化的排查流程: 安装期问题:包括命令未找到和Python版本不兼容,主要检查PATH环境和Python版本是否符合要求 认证类问题:涉及API Key认证失败和速率限制,需要验证密钥配置和配额状态 基础设施问题:包含Docker报错、MCP连接失败和OAuth令牌过期,需检查相关服务状态 执行类问题:主要是上

简简单单Onlinezuozuo 1348

TypeScript语言的数据结构与算法

本文介绍了在TypeScript中实现常见的数据结构与算法,包括数组、链表、栈、队列、哈希表、排序算法、查找算法和动态规划等。数据结构与算法是软件开发的基石,掌握它们能够帮助开发者提高解决问题的能力,编写出高效和可维护的代码。希望通过本文的示例,能够激励更多的开发者在TypeScript中深入探索数据结构与算法的奥妙。

2501_91257680的博客 547

3.38 工业缺陷检测实战:物体表面缺陷检测,从图像处理到深度学习

本文介绍了工业缺陷检测的完整流程,从传统图像处理到深度学习方法。首先定义了缺陷检测任务的目标和应用场景,然后详细讲解了传统图像处理方法(边缘检测、阈值分割等)和深度学习方法(分类、检测、分割模型)。文章最后总结了核心要点,提出了思考题和实践建议,建议从简单方法开始逐步优化。下一篇将介绍工业视觉基础技术——相机标定与角点检测。

yonggeit的博客 2890

leetcode | go | 第148题 | 排序链表

【代码】leetcode | go | 第148题 | 排序链表。

iCling的博客 341

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

LeetCode0148.排序链表 Go语言AC笔记

字节面试常考链表题,务必要吃透!go语言实现并附上详细备注的AC代码,效率优于官方题解!

Hexa_H的博客 446

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

排序链表(python实现)

题目描述: 在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。 示例 1: 输入: 4->2->1->3 输出: 1->2->3->4 示例 2: 输入: -1->5->3->4->0 输出: -1->0->3->4->5 来源:力扣(LeetCode) 链接:https://leetcod...

weixin_44512019的博客 941

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

leetcode_148的解题思路

题意:实现一个链表的排序,要求时间复杂度是n*lgn,空间复杂度是常数级 题意分析:该题考点——排序算法之二路归并,即先分割排序,后合并,有两种实现方式:一、递归实现;二、迭代实现。由于要求空间复杂度是常数级,所以是要求用的是迭代去实现。这里两种方式都实现一下(递归代码看起来简单易懂,迭代稍微复杂些,这里就直接粘贴复制了网友的方法) // Definition for singly-linked list. struct ListNode { int val; ListNode *nex...

qq_27763933的博客 277

Go 算法 leetcode 148 排序链表

Go 算法 leetcode 148 排序链表题目链接答案 题目 给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。 链接 leetcode 148 排序链表 答案 /** * Definition for singly-linked list. * type ListNode struct { * Val int * Next *ListNode * } */ func sortList(head *ListNode) *ListNode { i

kucfire 456

Leetcode148. 排序链表

Leetcode148. 排序链表 题目: 在 O(nlogn)O(n log n)O(nlogn) 时间复杂度和常数级空间复杂度下,对链表进行排序。 示例 1: 输入: 4->2->1->3 输出: 1->2->3->4 示例 2: 输入: -1->5->3->4->0 输出: -1->0->3->4->5 题解: 归并排序+递归 java代码: /** * @param head * @ret

会流泪de鱼的博客 300

leetcode 148. 排序链表 golang实现

描述 在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。 示例 1: 输入: 4->2->1->3 输出: 1->2->3->4 示例 2: 输入: -1->5->3->4->0 输出: -1->0->3->4->5 思路 分治思想 1. 将链表切成两份 一直切到无法再切 2. 将切...

tzh_linux的专栏 1126

数据结构与算法笔记:字典序最大问题分析

字典序最大问题 问题描述 给定一个1到n的排列(无序状态的),依次插入到栈中,在每时每刻都可以多次从栈中弹出栈顶 问:应如何使得弹出栈顶的序列的字典序最大,并输出这个序列 问题分析 什么是字典序 比如两个序列:5,4,3,2,1和1,2,3,4,5 这两个中第一个的字典序最大 每个位置上的数字比其他序列上同一位置的数字要大 比如:第一位置中5比1大,第二位置中4比2大这样 即:字典序最大 = 从左向右看这个序列,每个数字都尽量大 题目给定一个1到n的排列,每个数字只出现一次 要使出栈的字典序最大

Wang的专栏 4393

数据结构与算法笔记:农夫过河问题python3实现

问题描述 农夫(Human)过河。一个农夫带着一只狼(Wolf),一只羊(Sheep)和一些菜(Vegetable)过河。河边只有一条船,由于船太小,只能装下农夫和他的一样东西。在无人看管的情况下,狼要吃羊,羊要吃菜,请问农夫如何才能使三样东西平安过河? 要求: 输出一行,为最终的过河方式,方案格式为 过河人员、回来人员、过河人员、回来人员、…、过河人员。 过去和回来的人员之间,用空格隔开。 以四...

Wang的专栏 3374

数据结构与算法笔记:计算思维之经典农夫过河问题C++实现

农夫、羊、狼、菜的过河问题 问题描述 角色:农夫,羊,狼,菜 条件1:船很小,只能装下农夫和其他一个角色 条件2:无人看管,羊吃菜,狼吃羊 问:如何让其他三种角色被农夫平安带着过河? 相关分析 我们可以先用人脑尝试一下相关渡河策略 1 ) 先渡狼,人回来再渡菜,人回来再渡羊 2 ) 先渡菜,人回来再渡狼,人回来再渡羊 以上两种很好想到,而且我们可以知道羊这种角色是不能先渡河过去的,羊需要最后再渡 如果先渡了羊了,之后再渡任何其他角色,都要将羊带回来 可以参考小游戏:http://gameschool

Wang的专栏 3312

数据结构与算法笔记:图搜索之DFS详解

图搜索 Graph Search 图搜索的分类 BFS广度优先(宽搜) DFS深度优先(深搜) !!!本文详解!!! 深度优先搜索DFS 深度优先遍历DFS, 这个策略其实是非常stupid or simple的,比BSF要简单的多 同样,我们可以通过一个故事来开始 在古希腊神话中, Ariadne是Crete的国王Minos的公主,她给忒修斯(Theseus)一个线团 使得忒修斯成功进入迷宫杀死牛头怪兽,但事后忒修斯抛弃了她 这是一个有道德意义的故事又或者存在不同的版本, 但不是我们的研究的对象

Wang的专栏 3119

数据结构与算法笔记:计算思维之人鬼渡河问题

人鬼渡河问题 1 ) 问题描述 目标:将东岸的3人3鬼通过一只小船安全转移到西岸,希望摆渡次数尽可能少 条件 船的容量有限,一次最多只能坐2人(或2鬼或1人1鬼) 无论是在河的东岸还是在河的西岸,一旦鬼数多于人数,则人将被鬼吃掉 怎样渡河的大权掌握在人的手中 说明:划船的时间忽略不计。船一靠岸即将船与岸视为一体,人和鬼即使还没有下 船也视为已上岸 任务:编写程序,求出一种渡河方案 备注:图片托管于github,请确保网络的可访问性 2 ) 分析 目标是找

Wang的专栏 2447

数据结构与算法之二叉树: LeetCode 701. 二叉搜索树中的插入操作 (Ts版)

1 ) 方案1:模拟。2 ) 方案2:递归。

Wang的专栏 2270
上一篇: Vue3源码梳理:watch监听函数的核心实现
下一篇: 数据结构与算法之动态规划: LeetCode 509. 斐波那契数 (Ts, Py, Go版)
Wang's Blog
博客等级 码龄12年 7434粉丝 2421原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值