[剑指offer] 06.从头到尾打印链表& 24.反转链表

从头到尾打印链表

题目描述:

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

示例一:

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

借助实现,代码如下:

Java实现:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public int[] reversePrint(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[] res = new int[size];
       for(int i = 0;i<size;i++){
           res[i] = stack.pop().val;
       }
       return res;
    }
}

反转链表;同LeeDCode206

题目描述:

定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。

示例一:

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

自己的想法:实现的方式跟上面那道题相似,都是借助栈的先进后出原理来实现

Java实现:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        if(head==null) return head;
        Stack<ListNode> stack = new Stack<ListNode>();
        ListNode temp = head;
        //将链表的结点一个个存入栈中
        while(temp!=null){
            stack.push(temp);
            temp = temp.next;
        } 
     
        ListNode resHead = stack.pop();
        ListNode tailNode = resHead;
        while(!stack.isEmpty()){
            ListNode tt = stack.pop();
            tailNode.next = tt;
            tailNode = tt; //这个地方的tailNode一定要后移,很容易出错
        }
        tailNode.next = null;
        return resHead;
    }
}

官方解法:(源自力扣官方)

图解算法数据结构 - LeetBook - 力扣(LeetCode)全球极客挚爱的技术成长平台

解法一:迭代(双指针)

1. 初始化pre,cur分别指向null和头结点

2. 暂存后继节点,修改引用指向

tmp = cur.next; //暂存后继节点
cur.next = pre; //修改引用指向

3. 暂存当前节点,访问下一节点

pre = cur; //暂存当前节点
cur = tmp; //访问下一节点

4. 这样循环遍历完整个链表之后就能生成以pre作为头结点的反转链表

Java实现:

class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode cur = head, pre = null;
        while(cur != null) {
            ListNode tmp = cur.next; // 暂存后继节点 cur.next
            cur.next = pre;          // 修改 next 引用指向
            pre = cur;               // pre 暂存 cur
            cur = tmp;               // cur 访问下一节点
        }
        return pre;
    }
}

 复杂度分析:

  • 时间复杂度O(N):遍历链表使用线性大小空间
  • 空间复杂度O(1):变量pre和cur使用常数大小额外空间

解法二:递归

1. recur(cur,pre)递归函数

  • 终止条件:当 cur 为空,则返回尾节点 pre (即反转链表的头节点);
  • 递归后继节点,记录返回值(即反转链表的头节点)为 res ;
  • 修改当前节点 cur 引用指向前驱节点 pre ;
  • 返回反转链表的头结点res

2. reverseList(head)函数

  • 调用并返回 recur(head, null) 。传入 null 是因为反转链表后, head 节点指向 null 
class Solution {
    public ListNode reverseList(ListNode head) {
        return recur(head, null);    // 调用递归并返回
    }
    private ListNode recur(ListNode cur, ListNode pre) {
        if (cur == null) return pre; // 终止条件
        ListNode res = recur(cur.next, cur);  // 递归后继节点
        cur.next = pre;              // 修改节点引用指向
        return res;                  // 返回反转链表的头节点
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

clear up

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值