题目描述
输入一个链表,按链表从尾到头的顺序返回一个ArrayList。
示例1
- 输入: {67,0,24,58}
- 返回值: [58,24,0,67]
难度:简单
题解
方法一:List.Reverse 方法
- Reverse():将整个 List 中元素的顺序反转。此方法是 O (n) 操作,其中 n 是 List 中包含的元素数Count.
- Reverse(int index, int count):将指定范围中元素的顺序反转。
index:要反转的范围的从零开始的起始索引。
count:要反转的范围内的元素数。
Sample:csharplist.Reverse(1, 4) //使用方法重载反转列表中间,从元素1开始,包含四个元素
C#:
using System.Collections.Generic;
/*
public class ListNode
{
public int val;
public ListNode next;
public ListNode (int x)
{
val = x;
}
}*/
class Solution
{
// 返回从尾到头的列表值序列
public List<int> printListFromTailToHead(ListNode listNode)
{
List<int> resList = new List<int>();
while(listNode != null)
{
resList.Add(listNode.val);
listNode = listNode.next;
}
resList.Reverse();
return resList;
}
}
方法二:递归
C#:
using System.Collections.Generic;
/*
public class ListNode
{
public int val;
public ListNode next;
public ListNode (int x)
{
val = x;
}
}*/
class Solution
{
List<int> resList = new List<int>(); // 递归,必须定义在方法外。
public List<int> printListFromTailToHead(ListNode listNode)
{
if(listNode!=null)
{
if(listNode.next !=null)
{
printListFromTailToHead(listNode.next);
}
resList.Add(listNode.val);
}
return resList;
}
}
方法三:反转链表
最后在准备一个temp,表示还未反转的第一个结点。
- 初始化三个指针: pre结点初始指向nullptr,current 为head,next为NULL。
- 通过链表迭代。在循环中,执行以下操作。
//在更改当前节点的下一个节点之前,
//存储下一个节点
next = curr-> next
//现在改变当前节点的下一节点
//这是实际逆转发生的地方
curr-> next = prev
//将prev和curr向前移动一步
prev = curr
curr = next
- 总结:先存储当前节点的下一节点,再反转当前节点的pnext指针,最后重置head头部。
- 注意:若head指向Null而不放数据,则prev、current 、next应相应改变。如果head为空,循环都不会执行。
C#:
using System.Collections;
using System.Collections.Generic;
/*
public class ListNode
{
public int val;
public ListNode next;
public ListNode (int x)
{
val = x;
}
}*/
class Solution
{
public List<int> printListFromTailToHead(ListNode listNode)
{
if (listNode == null)
{
return new List<int>();
}
ListNode current = listNode; //表示当前正在反转的结点,current初始化为head
ListNode next = null; //表示还未反转的第一个结点
ListNode pre = null; //表示正在反转结点的前一个结点
while (current != null)
{
next = current.next;
current.next = pre;
pre = current;
current = next;
}
List<int> ls = new List<int>();
while (pre != null)
{
ls.Add(pre.val);
pre = pre.next;
}
return ls;
}
}
方法四:List.Insert(Int32, T) 方法
List中有个方法是 Insert (index,value),可以指定 index 位置插入 value 值
public void Insert (int index, T item);
参数:
- index:应插入 item 的从零开始的索引。
- item:要插入的对象。 对于引用类型,该值可以为 null。
所以我们在遍历 listNode 的同时将每个遇到的值插入到 list 的 0 位置,最后输出 listNode 即可得到逆序链表.
C#:
using System.Collections.Generic;
/*
public class ListNode
{
public int val;
public ListNode next;
public ListNode (int x)
{
val = x;
}
}*/
class Solution
{
// 返回从尾到头的列表值序列
public List<int> printListFromTailToHead(ListNode listNode)
{
List<int> myList = new List<int>();
while(listNode!=null)
{
myList.Insert(0, listNode.val); //将每个遇到的值插入到 list 的 0 位置
listNode =listNode.next;
}
return myList;
}
}
- 时间复杂度:O(n)
- 空间复杂度:O(n)
方法五:栈
链表只能从头遍历到尾,但是输出却要求从尾到头,是典型的"先进后出",可以用栈实现。
C#:
using System.Collections;
using System.Collections.Generic;
/*
public class ListNode
{
public int val;
public ListNode next;
public ListNode (int x)
{
val = x;
}
}
*/
class Solution
{
public List<int> printListFromTailToHead(ListNode listNode)
{
Stack resStack = new Stack();
List<int> resList = new List<int>();
while(listNode != null)
{
resStack.Push(listNode.val);
listNode = listNode.next;
}
while(resStack.Count>0)
{
resList.Add((int)resStack.Pop());
}
return resList;
}
}