数据结构与算法——Java实现 7.习题——反转链表

当你穿过了暴风雨,你已不是原来那个人

------ 24.9.21

206. 反转链表

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例 1:

复制代码
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

示例 2:

复制代码
输入:head = [1,2]
输出:[2,1]

示例 3:

复制代码
输入:head = []
输出:[]

提示:

  • 链表中节点的数目范围是 [0, 5000]
  • -5000 <= Node.val <= 5000

方法1

构造一个新链表,从旧链表依次拿到每个结点,创建新节点添加至新链表头部,完成后新链表即是倒序的

java 复制代码
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */ 
   public ListNode reverseList(ListNode head) {
        ListNode prev = null;
        while (head != null) {
            prev = new ListNode(head.val, prev);
            head = head.next;
        }
        return prev;
    }

方法2

与方法1类似,构造一个新链表,从旧链表头部移除节点,添加到新链表头部,完成后新链表即是倒序的,区别在于原题目未提供节点外层的容器类,这里提供一个,另外一个区别是并不去构造新节点

java 复制代码
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        List list1 = new List(head);
        List list2 = new List(null);
        while (head != null) {
            ListNode remove = list1.removeFirst();
            if (remove == null){
                break;
            }
            list2.addFirst(remove);
        }
        return list2.head;
    }
    static class List {
        ListNode head;

        public List(ListNode head) {
            this.head = head;
        }

        public void addFirst(ListNode First){
            First.next = head;
            head = First;
        }

        public ListNode removeFirst(){
            if (head == null){
                return null;
            }
            ListNode thanRemove = head;
            head = head.next;
            return thanRemove;
        }
    }
}

方法3

用递归的方法,直接将链表进行翻转

**注意:**if的判断要左边先进行head是否为空的判断,在进行head.next是否为空的判断,否则力扣判题系统会进行报错,提示程序试图在 null 对象上调用方法或访问字段

java 复制代码
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        if (head == null || head.next == null){
            // 找到了最后一个节点
            return head;
        }
        ListNode last = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return last;
    }
}

方法4

从链表每次拿到第二个节点,将其从链表断开,插入头部,直至它为 null 结束

1.设置指针 old1(旧头)、new1(新头)、old2(旧老二),分别指向第一,第一,第二节点

new1old1(1)--->old2(2)--->3--->4--->5--->null

2.将 old2 节点从链表断开,即 old1 节点指向第三节点

new1old1(1)--->3--->4--->5--->null;old2(2)

3.old2 节点链入链表头部,即

old2(2)--->new1old1(1)->3--->4--->5--->null

4.new1 指向 old2

new1old2(2) --->old1(1) --->3--->4--->5--->null

5.old2 指向 old1 的下一个节点,即

new1(2)--->old1(1)--->old2(3)--->4--->5--->null

6.重复以上 2 ~ 5 步,直到 old2 指向 null

7.还应当考虑边界条件,即链表中不满两个元素时,无需走以上逻辑

java 复制代码
    // 方法4 原始链表设置新旧两个指针进行复制
    public ListNode reverseList4(ListNode old1) {
        if (old1 == null || old1.next == null){
            return old1;
        }
        // 每次把原始链表的第二个结点剪切放到新链表的头部,当旧链表的第二个结点为null时,结束
        ListNode old2 = old1.next;
        ListNode new1 = old1;
        while (old2 != null) {
            old1.next = old2.next;
            old2.next = new1;
            new1 = old2;
            old2 = old1.next;
        }
        return new1;
    }

方法5

要点:把链表分成两部分,思路就是不断从链表2的头,往链表1的头搬移

1.new1 指向 null,代表新链表一开始没有元素,old1 指向原链表的首节点

new1(null),o1(1)--->2--->3--->4--->5--->null

2.开始循环,old2指向原链表次结点

new1(null),old1(1)--->old2(2)--->3--->4--->5--->null

3.挪移

old1(1)--->new1(null),old2(2)--->3--->4--->5--->null

4.指针复位

new(1)--->null,new1 old2(2)--->3--->4--->5--->null

5.重复2~4步

6.当old1 = null时,退出循环

java 复制代码
    // 方法5 面向过程同一链表互换
    public ListNode reverseList5(ListNode old1) {
        if (old1 == null || old1.next == null){
            return old1;
        }
        ListNode new1 = null;
        while (old1 != null) {
            ListNode old2 = old1.next;
            old1.next = new1;
            new1 = old1;
            old1 = old2;
        }
        return new1;
    }
相关推荐
web安全工具库4 分钟前
深入理解Python中的时间表示:Unix时间点、毫秒和微秒,以及time模块
开发语言·python·unix
伯牙碎琴5 分钟前
八、TOGAF(架构治理Architecture Governance)
java·微服务·架构
liuyang-neu11 分钟前
力扣 16.最接近的三数之和
java·数据结构·算法·leetcode
艾伦~耶格尔13 分钟前
Java API 之集合框架进阶
java·开发语言·学习
韩子谦14 分钟前
Java迭代器Iterator和Iterable有什么区别?
java·windows·python
Satan71216 分钟前
【Java】全面理解Java8特性
java·开发语言
至简行远17 分钟前
路由器接口配置DHCP实验简述
java·服务器·网络·数据结构·python·算法·智能路由器
c1tenj218 分钟前
SpringCloud Feign 以及 一个标准的微服务的制作
java·spring cloud·微服务
hakesashou22 分钟前
python有main函数吗
开发语言·python
Zach_yuan23 分钟前
C++重生之我是001
开发语言·c++