LeetCode 从头到尾打印链表

LeetCode 从头到尾打印链表

题目描述

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

示例 1:

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

一得之见(Java/Python)

使用 list 顺序存放 head 的每个元素,然后创建一个 int 数组 result,长度为 list.size(),然后通过遍历将 list 的尾部元素即 list.get(size - i - 1)赋值给 result[i],直至循环结束。

时间复杂度:O(n),反向遍历一遍 list
空间复杂度:O(n),使用一个 list 存储链表中的每个节点。

    /**
     * 输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
     *
     * @param head 链表头结点
     * @return 从尾到头反过来返回每个节点的值(用数组返回)
     */
    public static int[] reversePrint(ListNode head) {
        List<ListNode> list = new ArrayList<ListNode>();
        ListNode temp = head;
        while (temp != null) {
            list.add(temp);
            temp = temp.next;
        }
        int size = list.size();
        int[] result = new int[size];
        for (int i = 0; i < size; i++) {
            result[i] = list.get(size - i - 1).val;
        }
        return result;
    }
def reverse_print(head: ListNode) -> List[int]:
    """
    输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
    :param head: 链表头结点
    :return: 从尾到头反过来返回每个节点的值(用数组返回)
    """
    head_list = []
    temp = head
    while temp is not None:
        head_list.append(temp)
        temp = temp.next
    list_len = len(head_list)
    result = [0 for i in range(list_len)]
    for i in range(list_len):
        result[i] = head_list[list_len - i - 1].val
    return result

他山之石(Java/Python)

辅助栈法

栈的特点是后进先出,即最后压入栈的元素最先弹出。考虑到栈的这一特点,使用栈将链表元素顺序导致。从链表的头节点开始,依次将每个节点压入栈内,然后依次弹出栈内的元素并存储到数组中。

  • 创建一个栈,用于存储链表的节点
  • 创建一个指针,初始时指向链表的头节点
  • 当指针指向的元素非空时,重复下列操作:
    • 将指针指向的节点压入栈内
    • 将指针移到当前节点的下一个节点
  • 获得栈的大小 size,创建一个数组 print,其大小为 size
  • 创建下标并初始化 index = 0
  • 重复 size 次下列操作
    • 从栈内弹出一个节点,将该节点的值存到 print[index]
    • 将 index 的值加
  • 返回 print

时间复杂度:O(n),空间复杂度:O(n)

    /**
     * 输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
     *
     * @param head 链表头结点
     * @return 从尾到头反过来返回每个节点的值(用数组返回)
     */
    public static int[] reversePrintTwo(ListNode head) {
        Stack<ListNode> stack = new Stack<ListNode>();
        ListNode temp = head;
        while (temp != null) {
            stack.push(temp);
            temp = temp.next;
        }
        int size = stack.size();
        int[] print = new int[size];
        for (int i = 0; i < size; i++) {
            print[i] = stack.pop().val;
        }
        return print;
    }
}
def reverse_print_three(head: ListNode) -> List[int]:
    """
    输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
    :param head: 链表头结点
    :return: 从尾到头反过来返回每个节点的值(用数组返回)
    """
    stack = []
    while head:
        stack.append(head.val)
        head = head.next
    return stack[::-1]

递归法

  • 递推阶段:每次传入 head.next,以 head == None(即走过链表尾部节点)为递归终止条件,此时返回空列表[]
  • 回溯阶段:利用 Python 语言特性,递归回溯时每次返回当前list + 当前节点值[head.val],即可实现节点的倒序输出。

时间复杂度:O(n),空间复杂度:O(n)

def reverse_print_two(head: ListNode) -> List[int]:
    """
    输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
    :param head: 链表头结点
    :return: 从尾到头反过来返回每个节点的值(用数组返回)
    """
    return reverse_print_two(head.next) + [head.val] if head else []

效率对比(Java)

输入:[0,1,3,2]
方法一:78800ns
方法二:111900ns

效率对比(Python)

输入:[0,1,3,2]
方法一:13200ns
方法二:24300ns
方法三:6300ns

其他知识点

[::-1]和[-1]用法

[::-1]顺序相反操作
[-1]读取倒数第一个元素
[3::-1]从下标为 3(到下标为 0 结束) 的元素开始翻转读取

链表

链表(Linked List)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。
由于不必须按顺序存储,链表在插入的时候可以达到 O(1)的复杂度,比另一种线性表——顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要 O(n)的时间,而顺序表相应的时间复杂度为 O(log n) 和 O(1)。

基本机构
/**
 * @author zhkai
 */
public class ListNode {
    public int val;
    public ListNode next;

    public ListNode(int x) {
        val = x;
    }
}
创建链表
/**
 * @author zhkai
 */
public class CreateListNode {
    public static ListNode createListNode(int[] nums) {
        int len = nums.length;
        if (len < 1) {
            return null;
        }
        // 创建首节点
        ListNode nodeSta = new ListNode(nums[0]);
        // 声明一个变量用来在移动过程中
        ListNode nextNode;
        // 指向首节点
        nextNode = nodeSta;
        // 创建链表
        for (int i = 1; i < len; i++) {
            // 生成新的节点
            ListNode node = new ListNode(nums[i]);
            // 把新的节点连接起来
            nextNode.next = node;
            // 当前节点往后移动
            nextNode = nextNode.next;
        }
        // 当for循环完成之后,nextNode指向最后一个节点
        nextNode = nodeSta;
        return nextNode;
    }
}

posted @ 2021-04-14 17:10  于北往南  阅读(61)  评论(0编辑  收藏  举报