剑指 Offer 06. 从尾到头打印链表

一、题目 

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

        示例 1:

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

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

二、思路

1、用栈写入后出的特点实现

2、先链表反转,再遍历链表放进数组

3、遍历连表,逆序存入数组(最优解)

        

三、代码

1、基于栈的特点、先入后出;且栈元素的插入删除【入栈出栈】都发生在栈顶。

        时间和空间复杂度均为O(n)

public int[] reversePrint(ListNode head) {
//  1、  非空校验
        if (head == null) {
            return new int[0];
        }

 // 2、新建一个栈空间、遍历链表,元素依次入栈
        Stack<ListNode> stack = new Stack<>();
        ListNode currNode = head;
        while (currNode != null) {
            stack.push(currNode);
            currNode = currNode.next;
        }
  // 3. 取出栈顶元素、依次存入数组中
        int[] arr = new int[stack.size()];
        int i = 0;
        while (!stack.isEmpty()) {
            arr[i] = stack.pop().val;
            i++;
        }
//4、返回数组
        return arr;
    }

2.反转链表、遍历链表、放入数组

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

       public int[] reversePrint(ListNode head) {
      //  1、  非空校验
        if (head == null) {
            return new int[0];
        }
        // 2、原地反转链表
        ListNode prev = null;
        ListNode cur = head;
        int count =0;
        while (cur != null) {
            ListNode next = cur.next;
            cur.next = prev;
            prev = cur;
            cur = next;
            count ++;
        }

        //遍历链表、元素存入数组
        ListNode curNode = prev;
        int[] arr = new int[count];
        int index = 0;
        while (curNode != null) {
            arr[index] = curNode.val;
            index++;
            curNode = curNode.next;
        }
        return arr;
}

3、遍历链表、逆序放入数组中(最优解)

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

public int[] reversePrint(ListNode head) {
        //  1、  非空校验
        if (head == null) {
            return new int[0];
        }

        // 2. 统计链表的长度
        int count = 0;
        ListNode currNode = head;
        while (currNode != null) {
            count++;
            currNode = currNode.next;
        }

        // 3. 新建一个和链表等长度的数组
        int[] arr = new int[count];

        // 4. 遍历链表、逆序放入数组
        // 定位到数组末尾下标
        int index = count - 1;
        currNode = head;
        while (currNode != null) {
            arr[index] = currNode.val;
            index--;
            currNode = currNode.next;
        }

        return arr;
    }

最终结果:

四、总结

一、数组和链表的区别:

1、数组是相同元素的集合,创建时需指定容量大小,进而分配内存。链表创建时无需指定大小,每添加一个节点就分配一次内存。

2、数组再内存中连续、链表不连续。

3、数组在栈区、链表在堆区。

4、数组通过下标定位元素,查找元素时间复杂度为O(1),链表查找元素时间复杂度O(n).

5、数组插入和删出元素时间复杂度时O(n),链表插入和删除时间复杂度O(1)。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值