• 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;
        }
    }
    
    
  • 相关阅读:
    clientHeight、offsetHeight和scrollHeight
    关于网页元素的定位问题及offsetParent的讨论
    SQL关闭自增长列标识:SET IDENTITY_INSERT
    动态添加对Web Service的引用
    关于asp.net导出Excel
    scrollTop、scrollLeft、scrollWidth、scrollHeight
    ADO.NET实体数据模型
    不能加断点 单步调试被跳过
    无法启动程序“http://localhost:3303/Default.aspx”
    asp.net本质论学习笔记第一章
  • 原文地址:https://www.cnblogs.com/GardenofEden/p/14658888.html
Copyright © 2020-2023  润新知