剑指 Offer 06. 从尾到头打印链表(递归、逆置链表、头部动态插入)

本文探讨了三种方法解决链表反转问题:递归、逆置链表和头部动态插入。作者分析了不同解法的时间复杂性和空间占用,并指出头部动态插入在时间和空间效率上优于递归,适合长链表场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。

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

限制:
0 <= 链表长度 <= 10000

解法一:递归(递归本来就是一种栈,所以算做一类)

func reversePrint(head *ListNode) []int {

    if head == nil {
        return []int{}
    }

	if head.Next == nil {
		return []int{head.Val}
	}

	return append(reversePrint(head.Next), head.Val)
}

在这里插入图片描述

解法二:逆置链表

func reversePrint(head *ListNode) []int {

	if head == nil {
		return []int{}
	}
	// 逆置链表
	fistNode, mindNode := head, head.Next
	fistNode.Next = nil
	for {
		if mindNode == nil {
			break
		}

		endNode := mindNode.Next
		mindNode.Next = fistNode
		fistNode = mindNode
		mindNode = endNode

	}
	vals := make([]int,0)
	for {
		if fistNode == nil {
			return vals
		}

		vals = append(vals, fistNode.Val)
		fistNode = fistNode.Next
	}
}

在这里插入图片描述
解法三:头部动态插入(模拟切片动态扩容)

func reversePrint(head *ListNode) []int {

	if head == nil {
		return []int{}
	}
	vals := make([]int, 4)
	endIndex := len(vals)
	for {
		endIndex--
		if head == nil {
			break
		}

		vals[endIndex] = head.Val
		if endIndex == 0 {
			vals, endIndex = dilatation(vals)
		}
		head = head.Next
	}

	return vals[endIndex+1:]
}

func dilatation(arr []int) ([]int, int) {
	lenArr := len(arr)
	restfulSize := lenArr + lenArr/2
	restful := make([]int, restfulSize)
	endIndex := len(restful)
	arrIndex := lenArr - 1
	for {
		if arrIndex < 0 {
			break
		}
		endIndex--
		restful[endIndex] = arr[arrIndex]
		arrIndex--
	}

	return restful, endIndex
}

在这里插入图片描述
总结:可以看出头部动态插入与逆置链表再执行速度相同的情况下占用的空间还是比递归少一些,虽然不是官方解法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值