反转链表 II

152 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第19天,点击查看活动详情

前言

笔者除了大学时期选修过《算法设计与分析》和《数据结构》还是浑浑噩噩度过的(当时觉得和编程没多大关系),其他时间对算法接触也比较少,但是随着开发时间变长对一些底层代码/处理机制有所接触越发觉得算法的重要性,所以决定开始系统的学习(主要是刷力扣上的题目)和整理,也希望还没开始学习的人尽早开始。

系列文章收录《算法》专栏中。

力扣题目链接

问题描述

给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表

示例 1

输入:head = [1,2,3,4,5], left = 2, right = 4
输出:[1,4,3,2,5]

示例 2:

输入:head = [5], left = 1, right = 1
输出:[5]

提示:

  • 链表中节点数目为 n
  • 1 <= n <= 500
  • -500 <= Node.val <= 500
  • 1 <= left <= right <= n

进阶: 你可以使用一趟扫描完成反转吗?

剖析

需要把从right开始到left为止的位置的元素进行调换,因为调换的过程中涉及到依次取右边的元素到左边来,但是链表不适合随机定位,所以笔者的想法是先遍历一遍放入数组,放完后再从左边开始进行调换。每次迭代前一个节点nodeBefore,把右边的元素作为nodeBefore的next节点。

其他需要注意的地方就是:left可能为最左边元素,我们可以使用创建一个-1位置的节点hair,最后返回hair的next就是头节点了,最后的nodeBefore节点需要和后面的节点衔接上。

代码

package com.study.algorithm.linklist;

import java.util.ArrayList;
import java.util.List;

/**
 * https://leetcode-cn.com/problems/reverse-linked-list-ii/
 * 反转链表 II
 */
public class ReverseBetween {
    public static 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 static ListNode reverseBetween(ListNode head, int left, int right) {
        if (left == right) {
            return head;
        }

        ListNode hair = new ListNode(-1);
        hair.next = head;

        ListNode current = head;
        List<ListNode> nodeList = new ArrayList<>();
        while (current != null) {
            nodeList.add(current);
            current = current.next;
        }

        ListNode nodeBefore;
        if ((left - 2) < 0) {
            nodeBefore = hair;
        } else {
            nodeBefore = nodeList.get(left - 2);
        }

        int needSwapIndex = right - 1;
        for (int i = (left - 1); i < right; i++) {
            nodeBefore.next = nodeList.get(needSwapIndex);
            nodeBefore = nodeList.get(needSwapIndex);
            needSwapIndex--;
        }

        if (right == nodeList.size()) {
            nodeBefore.next = null;
        } else {
            nodeBefore.next = nodeList.get(right);
        }


        return hair.next;
    }
}