1. 程式人生 > 其它 >牛客刷題——連結串列中的節點每K個一組反轉

牛客刷題——連結串列中的節點每K個一組反轉

技術標籤:牛客刷題

題目:

將給出的連結串列中的節點每 k個一組翻轉,返回翻轉後的連結串列
如果連結串列中的節點數不是 k的倍數,將最後剩下的節點保持原樣
你不能更改節點中的值,只能更改節點本身。
要求空間複雜度O(1)

例如:

給定的連結串列是1->2->3->4->5

對於 k=2, 你應該返回2->1->4->3->5

對於k=3, 你應該返回3->2->1->4->5

首先解決的方法肯定是以連結串列反轉為基礎的,但是這個反轉不是反轉整個連結串列,而是反轉當前結點開始的k個節點,所以在反轉的函式中加一個對於節點的計數count和k的比較即可。

然後分析k個一組反轉的話,首先要滿足有k個,所以需要使用兩個指標left和right,當指標表示的區間長度為k的時候對以left開頭,right結尾的這一組進行反轉,在進行反轉之前要記錄好當前區間的pre節點和next節點,由於上一個連結串列區間反轉後關係變成了right->left,這裡的left節點實際上就是當前結點的pre節點,對於next節點則直接在遍歷的時候記錄即可。連結串列反轉之後,使用pre,left,right和next重新整理好連結串列之間的關係,並且更新這些節點的值,直到整個連結串列遍歷結束。

完整程式碼如下:

public ListNode reverseKGroup (ListNode head,int k) {
        // write code here
		if(head==null||head.next==null) {
			return head;
		}
		int count = 0;
		
		ListNode tempNow = head;   
		ListNode now = head;	//兩個結點相當於左右指標,確定反轉區間
		ListNode res = new ListNode(0);  //頭結點
		res.next = head;
		ListNode next = null;   //tempNow的下一個結點
		ListNode pre = res;    //now的上一個結點
		while(now!=null) {
			count++;
			
			if(count%k==0) {
				next = now.next;
				ListNode temp = reverseK(tempNow, k);
				pre.next = now;
				pre = temp;
				temp.next = next;
				tempNow = next;
				now = next;
			}else {
				now = now.next;
			}
		}
		return res.next;
    }
	
	public ListNode reverseK(ListNode head,int k) {  //反轉從head開始的k個 
        // write code here
		ListNode now = head;
		ListNode next = head.next;
		head.next = null;
		int count = 1;
		while(next!=null&&count<k) {
			ListNode nNext = next.next;
			next.next = now;
			now = next;
			next = nNext;
			count++;
		}
		return head;
    }