k个一组翻转链表(迭代法、递归法)

给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。

k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

 

示例 1:

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

示例 2:

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

迭代法解题思路:

创建一个头结点和两个指向头结点的指针pre和end,每次循环都让end相距pre K 个结点,创建start=pre->next, next=end->next。然后让end指向空,切断该子链表,然后把该子链表翻转后重新连接,继续下一循环,直到end->next为空。

// 无注释版

struct ListNode {
      int val;
      ListNode *next;
      ListNode() : val(0), next(nullptr) {}
      ListNode(int x) : val(x), next(nullptr) {}
      ListNode(int x, ListNode *next) : val(x), next(next) {}
  };

class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
  ListNode* dummyHead=new ListNode(0);
  dummyHead->next=head;
  ListNode* pre=dummyHead;
  ListNode* end=dummyHead;
  while(end->next!=NULL){
      for(int i=0;i           end=end->next;
      if(end==NULL)  
          break;
      ListNode* start=pre->next;
      ListNode* next=end->next;
      end->next=NULL;
      pre->next=reverse(start);
      start->next=next;
      pre=start;
      end=pre;
  }
  return dummyHead->next;
    }
private:
ListNode* reverse(ListNode* head)
  {
      ListNode* pre=NULL;
      ListNode* curr=head;
      while(curr!=NULL) {
          ListNode* next=curr->next;
          curr->next=pre;
          pre=curr;
          curr=next;
      }
      return pre;
  }
};

// 注释版

struct ListNode {    // 链表的定义
      int val;
      ListNode *next;
      ListNode() : val(0), next(nullptr) {}
      ListNode(int x) : val(x), next(nullptr) {}
      ListNode(int x, ListNode *next) : val(x), next(next) {}
  };
// 类实现
class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {   

// 创建头结点并连接上链表
  ListNode* dummyHead=new ListNode(0);
  dummyHead->next=head;

// 创建指针pre和end并指向头结点
  ListNode* pre=dummyHead;
  ListNode* end=dummyHead;

// 以k个结点为一组循环
  while(end->next!=NULL){

// 每次都让end相距prek个距离
      for(int i=0;i           end=end->next;

// 如果end为空,结束循环
      if(end==NULL)  
          break;

// 创建start和next指针
      ListNode* start=pre->next;
      ListNode* next=end->next;

// 切断该子链表
      end->next=NULL;

// 让pre指向翻转后的子链表的第一结点

// reverse()实现子链表的翻转并返回第一结点
      pre->next=reverse(start);

// 让翻转后的子链表的最后一结点

// 重新接上链表
      start->next=next;

// 让pre和end指向翻转后的子链表的

// 最后一个结点
      pre=start;
      end=pre;
  }

// 返回链表第一结点
  return dummyHead->next;
    }
private:

// 实现翻转子链表的函数
ListNode* reverse(ListNode* head)
  {  // 传入子链表的第一结点赋给head

// 创建pre指向空和curr指向head
      ListNode* pre=NULL;
      ListNode* curr=head;


      while(curr!=NULL) {

// 创建next指向curr的下一个结点
          ListNode* next=curr->next;

// 让curr指向pre
          curr->next=pre;

// 让pre指向curr,curr指向next
          pre=curr;
          curr=next;
      }   // 建议自己画图理解

// 返回翻转后子链表的第一结点
      return pre;
  }
};

递归法解题思路:

理解递归需要明确三要素:

1.调用递归返回的是什么

2.使用递归返回给谁(哪里使用递归)

3.递归的终止条件

1.改题使用递归应返回交换后的子链表的第一个结点

2.应把返回值(交换后的子链表的第一个结点)给上一级的子链表的第一结点(未翻转的第一结点,也就是翻转后的最后一个结点)的指针域

3.递归的终止条件是最后一个子链表的结点个数小于k。

// 无注释版

struct ListNode {

   int val;

   ListNode *next;

   ListNode() : val(0), next(nullptr) {}

   ListNode(int x) : val(x), next(nullptr) {}

   ListNode(int x, ListNode *next) : val(x), next(next) {}

   };

 

class Solution {

public:

    ListNode* reverseKGroup(ListNode* head, int k) {

   ListNode* pre=head;

   ListNode* end=head;

   for(int i=1;i

        end=end->next;

   if(end==NULL)

      return head;

   ListNode* start=pre->next;

pre->next=reverseKGroup(end->next,k);

   while(pre!=end) {

        ListNode* next=start->next;

        start->next=pre;

        pre=start;

        start=next;

    }

    return end;

    }

};

// 注释版

struct ListNode {    // 链表的定义
      int val;
      ListNode *next;
      ListNode() : val(0), next(nullptr) {}
      ListNode(int x) : val(x), next(nullptr) {}
      ListNode(int x, ListNode *next) : val(x), next(next) {}
  };
// 类实现
class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {

// 定义pre指向第一结点,end指向第k结点
   ListNode* pre=head;    
   ListNode* end=head;
   for(int i=1;i         end=end->next;

// 终止条件:子链表结点个数小于k,不用翻转

// 所以返回子链表的第一结点
   if(end==NULL)
      return head;

// 使用递归把下一级翻转后的子链表的第一

// 结点给上一级未翻转的子链表第一结点的指 //针域
   ListNode* start=pre->next;
pre->next=reverseKGroup(end->next,k);

// 实现翻转
   while(pre!=end) {
        ListNode* next=start->next;
        start->next=pre;
        pre=start;
        start=next;
    }

// 递归的返回值(返回上一级)
    return end;
    }
};

// 建议画图自己一步一步照着推。

 

 

 

 

 

你可能感兴趣的:(算法,链表)