Description Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.
k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.
Example:
Given this linked list: 1->2->3->4->5
For k = 2, you should return: 2->1->4->3->5
For k = 3, you should return: 3->2->1->4->5
Note:
Only constant extra memory is allowed.
You may not alter the values in the list’s nodes, only nodes itself may be changed.
Difficulty: Hard
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 class Solution { public ListNode reverseKGroup (ListNode head, int k) { } }
题意 给定一个链表,将其每k个节点反转,并返回修改后的链表。k是小于等于链表长度的正整数,不足k个时保持原样。不允许修改节点的值,只允许修改整个节点。
Solution 1 把每k个节点为一组进行反转,那样需要两个函数,一个用来分段,一个用来反转。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 class Solution { public ListNode reverseKGroup (ListNode head, int k) { if (head==null ||head.next==null ) return head; ListNode dummy = new ListNode(0 ), curr= head, start = curr , lastDone = dummy; int count = 0 ; while (curr!=null ){ count++; ListNode nextOne = curr.next; if (count==k){ lastDone.next=reverse(start,k); lastDone=start; start=nextOne; count=0 ; } curr=nextOne; } lastDone.next=start; return dummy.next; } public ListNode reverse (ListNode node, int k) { ListNode dummy = new ListNode(0 ), curr = node; for (int i=0 ;i<k;i++){ ListNode tmp = dummy.next; dummy.next = curr; curr = curr.next; dummy.next.next=tmp; } return dummy.next; } }
时间复杂度: O()。
空间复杂度: O()。
Solution 2 上述解法,是以k为步进来生成最终的结果链表,保存了很多状态。也可以很平滑地进行反转,在反转是带上k个节点为一组的前置和后置节点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 class Solution { public ListNode reverseKGroup (ListNode head, int k) { if (head==null ||head.next==null ) return head; ListNode dummy = new ListNode(0 ), pre = dummy, curr = head; dummy.next = head; for (int i=1 ;curr!=null ;i++){ if (i%k==0 ){ pre = reverse(pre,curr.next); curr = pre.next; }else { curr = curr.next; } } return dummy.next; } public ListNode reverse (ListNode pre, ListNode next) { ListNode last = pre.next, curr = last.next; while (curr!=next){ last.next = curr.next; curr.next = pre.next; pre.next = curr; curr = last.next; } return last; } }
时间复杂度: O()。
空间复杂度: O()。
Solution 3 上述过程也可以在一个方法中完成,先遍历整个链表计算出链表长度,然后每次对k个节点进行反转。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class Solution { public ListNode reverseKGroup (ListNode head, int k) { if (head==null ||head.next==null ) return head; ListNode dummy = new ListNode(0 ), pre = dummy, curr = head; dummy.next = head; int num = 0 ; while (curr!=null ){ num++; curr = curr.next; } while (num>k){ curr = pre.next; for (int i=1 ;i<k;i++){ ListNode tmp = curr.next; curr.next=tmp.next; tmp.next=pre.next; pre.next=tmp; } pre = curr; num -= k; } return dummy.next; } }
时间复杂度: O()。
空间复杂度: O()。
Solution 4 递归调用,我们用pre记录每段的开始位置的前一个节点,cur记录结束位置的下一个节点,然后我们调用reverse函数来将这段翻转,然后得到一个new_head,原来的head就变成了末尾,这时候后面接上递归调用下一段得到的新节点,返回new_head即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class Solution { public ListNode reverseKGroup (ListNode head, int k) { if (head==null ||head.next==null ) return head; ListNode dummy = new ListNode(0 ), pre = dummy, curr = head; dummy.next = head; for (int i=0 ;i<k;i++){ if (curr==null ) return head; curr = curr.next; } ListNode newHead = reverse(pre,curr); head.next = reverseKGroup(curr,k); return newHead; } public ListNode reverse (ListNode pre, ListNode next) { ListNode last = pre.next, curr = last.next; while (curr!=next){ last.next = curr.next; curr.next = pre.next; pre.next = curr; curr = last.next; } return pre.next; } }
时间复杂度: O()。
空间复杂度: O()。