算法小练习之翻转链表

91 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第19天,点击查看活动详情

1、前言

每天一个算法小练习,本篇使用Java实现。

2、题目描述

对于一个链表 L: L0→L1→…→Ln-1→Ln,将其翻转成 L0→Ln→L1→Ln-1→L2→Ln-2→…。输入是一串数字,请将其转换成单链表格式之后,再进行操作。

2.1、输入描述

一串用逗号分隔的数字

2.2、输出描述

一串用逗号分隔的数字

2.3、示例

输入:

1,2,3,4,5

输出:

1,5,2,4,3

3、解题思路

将链表分成两半,后半段逆序,然后与前半段进行合并。

image.png

  • 1、利用快慢指针找到链表的中间节点;

  • 2、通过遍历,使后半段链表逆序;

  • 3、合并两个链表。

4、实现代码


public class ReverseListNode {
    static class ListNode {
        int val;
        ListNode next = null;
        ListNode(int val) {
            this.val = val;
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str = sc.nextLine();
        String[] inputStrArr = str.split(",");
        ListNode head = new ListNode(-1);
        ListNode rear = head;
        //将输入数据都插入到链表中
        for(String item : inputStrArr) {
            ListNode newNode = new ListNode(Integer.parseInt(item));
            rear.next = newNode;
            rear = newNode;
        }
        reverseListNode(head.next);
        head = head.next;
        while(head!=null){
            if(head.next==null){
                System.out.print(head.val);
            }else{
                System.out.print(head.val+",");
            }
            head=head.next;
        }

    }

    /**
     * 链表分割成两段,后半段逆序,然后与前半段合并
     * @param head
     */
    public static void reverseListNode(ListNode head) {
        if (head == null || head.next == null) {
            return;
        }
        ListNode left = head;
        ListNode right = head;
        //利用快慢指针,找到链表的中间节点。快指针每次移动2步,慢指针每次1步
        while (right.next != null && right.next.next != null) {
            left = left.next;
            right = right.next.next;
        }
        //将链表分为两段
        right = left.next;
        left.next = null;
        left = head;
        //把后半段链表逆序
        ListNode head2 = right;
        ListNode next2;
        while (right.next != null) {
            next2 = right.next;
            right.next = next2.next;
            next2.next = head2;
            head2 = next2;
        }
        right = head2;
        //合并
        ListNode next1;
        while (right != null) {
            next1 = left.next;
            next2 = right.next;
            left.next = right;
            right.next = next1;
            left = next1;
            right = next2;
        }
    }

}

5、执行结果

与预期一样

image.png

6、算法性能

6.1、时间复杂度

因为只需要从头到尾遍历一遍链表,所以时间复杂度为 O(N)O(N)NN就是需要翻转的链表的长度。

6.2、空间复杂度

实现过程中没有创建使用额外空间,所以为O(1)O(1)

好了、本期就先介绍到这里,有什么需要交流的,大家可以随时私信我。😊