分享
  1. 首页
  2. 文章

面试:从尾到头打印链表

若鱼治水 · · 1235 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

题目:从尾到头打印链表

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

示例:

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

限制:

0 <= 链表长度 <= 10000

题解1:递归法

因为是从尾到头返回每一个节点的值,所以很容易想到如果从最后的节点将值放入数组中,然后再往前逐步将数据放入数组,最后回到头节点返回即可,可以想到递归就能轻松做到,只要注意递归函数的结束条件即可。

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 * Val int
 * Next *ListNode
 * }
 */
func reversePrint(head *ListNode) []int {
 if head == nil {
 return nil
 }
 return appendData(head)
}
func appendData(head *ListNode) []int {
 if head.Next != nil{
 list := appendData(head.Next)
 list = append(list, head.Val)
 return list
 }
 return []int{head.Val}
}

自然而然,效率不会很高~

file

反思了一下,其实递归还可以再简短一点

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 * Val int
 * Next *ListNode
 * }
 */
func reversePrint(head *ListNode) []int {
 if head == nil {
 return []int{}
 }
 return append(reversePrint(head.Next), head.Val)
}

结果如下:

file

题解2:反转链表

想了一下,这样不行啊,耗时这么长,试试不用递归吧~

然后就想,如果我反转链表呢,再生成数组返回,这样也可以实现吧?

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 * Val int
 * Next *ListNode
 * }
 */
func reversePrint(head *ListNode) []int {
 if head == nil {
 return nil
 }
 var newHead *ListNode
 res := []int{}
 for head != nil {
 node := head.Next
 head.Next = newHead
 newHead = head
 head = node
 }
 for newHead != nil {
 res = append(res, newHead.Val)
 newHead = newHead.Next
 }
 return res
}

结果如下:

file

解法3:反转数组

反转链表再获取数值,可以是可以,会不会有点多余?还不如直接顺序获取值放到数组,再反转结果呢~

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 * Val int
 * Next *ListNode
 * }
 */
func reversePrint(head *ListNode) []int {
 if head == nil {
 return nil
 }
 res := []int{}
 for head != nil {
 res = append(res, head.Val)
 head = head.Next
 }
 for i, j := 0, len(res)-1; i < j; {
 res[i], res[j] = res[j], res[i]
 i++
 j--
 }
 return res
}

至此,结果有了很大的提升:

file

解法4:栈

这个反转数组还是感觉好奇怪,有没有更好的方法呢?把先读到的放最后,最后的在最前面,栈不就是这样的数据结构吗?

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 * Val int
 * Next *ListNode
 * }
 */
import "container/list"
func reversePrint(head *ListNode) []int {
 if head == nil {
 return nil
 }
 res := list.New()
 for head != nil {
 res.PushFront(head.Val)
 head = head.Next
 }
 ret := []int{}
 for e := res.Front(); e != nil; e = e.Next() {
 ret = append(ret, e.Value.(int))
 }
 return ret
}

三下五除二,搞定!来看看成果:

file

解法5:遍历两次

其实到栈,我以为这题就这样了,然而......

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 * Val int
 * Next *ListNode
 * }
 */
func reversePrint(head *ListNode) []int {
 if head == nil {
 return nil
 }
 count := 0
 newHead := head
 for head != nil {
 count++
 head = head.Next
 }
 res := make([]int, count)
 i := 0
 for newHead != nil {
 res[count-i-1] = newHead.Val
 i++
 newHead = newHead.Next 
 }
 return res
}

卧槽!!!质的提升,既省去自动扩容的性能,也能提高处理速度:

file

欢迎关注公众号:若鱼治水,文章会首发在公众号,也可备注加我备注进群进技术交流群~

有疑问加站长微信联系(非本文作者)

本文来自:Segmentfault

感谢作者:若鱼治水

查看原文:面试:从尾到头打印链表

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
1235 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏