链表k个节点反向

时间:2021-02-03 10:03:47

问题:

以k个元素为一组,反转单向链表。比如:

输入: 1->2->3->4->5->6->7->8->null and k = 3

输出:3->2->1->6->5->4->8->7->null.

分析:

我们可以把整个链表分成多个长度为 k  的子链表, 然后,我们再反转每一个子链表(递归)。问题的关键是我们需要把每个子链表再连接起来。所以,对每一个子链表操作以后,我们需要返回该子链表的头(head),然后,我们设置前一个子链表的最后一个node,把它的next 设置成下一个链表返回的头(head),这样,所有的子链表就连接起来了。

  1. public static Node reverse (Node head, int k) {
  2. Node current = head;
  3. Node next = null;
  4. Node prev = null;
  5. int count = 0;
  6. /*reverse first k nodes of the linked list */
  7. while (current != null && count < k) {
  8. next  = current.next;
  9. current.next = prev;
  10. prev = current;
  11. current = next;
  12. count++;
  13. }
  14. /* next is now a pointer to (k+1)th node
  15. Recursively call for the list starting from current.
  16. And make rest of the list as next of first node */
  17. if(next !=  null) {
  18. head.next = reverse(next, k);
  19. }
  20. /* prev is new head of the input list */
  21. return prev;
  22. }
public static Node reverse (Node head, int k) {
Node current = head;
Node next = null;
Node prev = null;
int count = 0; /*reverse first k nodes of the linked list */
while (current != null && count < k) {
next = current.next;
current.next = prev;
prev = current;
current = next;
count++;
} /* next is now a pointer to (k+1)th node
Recursively call for the list starting from current.
And make rest of the list as next of first node */
if(next != null) {
head.next = reverse(next, k);
} /* prev is new head of the input list */
return prev;
}

这个问题也可以使用非递归的方法,基本上问题的处理方式和递归是一样的,但是,非递归的方式要稍微复杂一点,因为每次对子链表反转以后,我们需要更新前一个子链表最后一个node 的next 值。代码如下:

  1. class Node {
  2. int val;
  3. Node next;
  4. Node(int x) {
  5. val = x;
  6. next = null;
  7. }
  8. }
  9. public class Solution {
  10. public static void main(String[] args) {
  11. Solution s = new Solution();
  12. Node n1 = new Node(1);
  13. Node n2 = new Node(2);
  14. Node n3 = new Node(3);
  15. Node n4 = new Node(4);
  16. Node n5 = new Node(5);
  17. n1.next = n2;
  18. n2.next = n3;
  19. n3.next = n4;
  20. n4.next = n5;
  21. Node head = s.ReverseInGroups(n1, 2);
  22. while (head != null) {
  23. System.out.println(head.val);
  24. head = head.next;
  25. }
  26. }
  27. public Node ReverseInGroups(Node current, int k) {
  28. if (current == null || current.next == null ) return current;
  29. //store the new head of the list
  30. Node newHead = null;
  31. //store the last node in the sub-list,
  32. //we will update its next value when finishing
  33. //reversing the next sub-list
  34. Node previousGroupTail = null;
  35. int count = 1; //used to track the first sub-list
  36. while (current != null) {
  37. // the actual tail in the sub-list
  38. Node groupTail = current;
  39. //reverse
  40. Node prev = null;
  41. Node next = null;
  42. for (int i = 1; i <= k && current != null; i++) {
  43. next = current.next;
  44. current.next = prev;
  45. prev = current;
  46. current = next;
  47. }
  48. // get the new head of the whole list
  49. if (count == 1) {
  50. newHead = prev;
  51. count++;
  52. }
  53. // update the next value of the last node in
  54. // each sub-list
  55. if (previousGroupTail != null) {
  56. previousGroupTail.next = prev;
  57. }
  58. previousGroupTail = groupTail;
  59. }
  60. return newHead;
  61. }
  62. }