1. 程式人生 > 其它 >連結串列內指定區間反轉——牛客網

連結串列內指定區間反轉——牛客網

描述

將一個節點數為 size 連結串列 m 位置到 n 位置之間的區間反轉,要求時間複雜度 O(n),空間複雜度 O(1)。
例如:
給出的連結串列為 1→2→3→4→5→NULL, m=2,n=4,
返回 1→4→3→2→5→NULL.

資料範圍: 連結串列長度 0<size≤1000,0<m≤n≤size,連結串列中每個節點的值滿足 |val| <= 1000
要求:時間複雜度 O(n),空間複雜度 O(n)
進階:時間複雜度 O(n),空間複雜度 O(1)

示例1

輸入:
{1,2,3,4,5},2,4
返回值:
{1,4,3,2,5}

示例2

輸入:
{5},1,1
返回值:
{5}

解題思路

第一次遍歷:首先遍歷節點,用一個變數cnt來維護當前節點的位置,如果已經遍歷到的節點位置在反轉區間左邊界的前一個,即跳出迴圈(也可能反轉就從第一個節點開始,需要用一個p指標去維護)

第二次遍歷,從左邊界的下一個節點開始繼續遍歷,每次遍歷都將當前節點進行反轉作為頭節點,然後指標q向後移動一位,重複上述過程,直到cnt > n(反轉區間右邊界)則跳出迴圈

最後判斷,若p不為空,則將p.next = newHead,並返回原頭節點head,反之,則直接返回反轉後連結串列的頭節點即可)

AC程式碼

import java.util.*;

/* * public class ListNode { * int val; * ListNode next = null; * } */ public class Solution { /** * * @param head ListNode類 * @param m int整型 * @param n int整型 * @return ListNode類 */ public ListNode reverseBetween (ListNode head, int m, int n) {
// write code here if (head == null || head.next == null) { return head; } // 用於記錄當前已經遍歷到的節點位置 int cur = 0; ListNode p = null; if (cur != m - 1) { p = head; // 找到開始位置 while (p != null) { cur++; if (cur == m - 1) { break; } p = p.next; } } cur++; ListNode newHead = p != null ? p.next : head; if (newHead.next == null) { return head; } ListNode tail = newHead; ListNode q = tail.next; while (q != null) { cur++; if (cur > n) { // 後續不用反轉 break; } ListNode tmp = q.next; q.next = newHead; newHead = q; tail.next = tmp; q = tmp; } // 前後銜接 if (p != null) { p.next = newHead; return head; } return newHead; } }

原題連結:https://www.nowcoder.com/practice/b58434e200a648c589ca2063f1faf58c?tpId=295&tqId=654&ru=%2Fpractice%2Fb58434e200a648c589ca2063f1faf58c&qru=%2Fta%2Fformat-top101%2Fquestion-ranking&sourceUrl=%2Fexam%2Foj