• 025k个一组翻转链表


      1 #include "000库函数.h"
      2 
      3 
      4 
      5 struct ListNode {
      6     int val;
      7     ListNode *next;
      8     ListNode(int x) : val(x), next(NULL) {}
      9 };
     10 /************************自己解答****************************/
     11  //不含头结点,链表中的数据按照k个k个地翻转,使用栈进栈出原理
     12 class Solution {
     13 public:
     14     ListNode* reverseKGroup(ListNode* head, int k) {
     15         if (k <= 1 || !head || !(head->next))return head;
     16         ListNode* Res = new ListNode(0);
     17         ListNode* r = Res;
     18         ListNode* p = head;
     19         stack<int> S;
     20         while (p) {
     21             S.push(p->val);            
     22             p = p->next;            
     23             if (S.size() == k) {
     24                 while (!S.empty()) { //采用尾插法
     25                     ListNode* q = new ListNode(0);
     26                     q->val = S.top();
     27                     r->next = q;
     28                     r = q;
     29                     S.pop();
     30                 }                
     31             }
     32         }
     33         if (S.size()) {
     34             while (!S.empty()) {            //采用头插法
     35                     ListNode* q = new ListNode(0);
     36                     q->val = S.top();
     37                     q->next = r->next;
     38                     r->next = q;                    
     39                     S.pop();                
     40             }
     41         }
     42         return Res->next;
     43 
     44     }
     45     
     46 };
     47 
     48 
     49 
     50 
     51 /*******************************博客答案***************************/
     52 //这道题让我们以每k个为一组来翻转链表,实际上是把原链表分成若干小段,
     53 //然后分别对其进行翻转,那么肯定总共需要两个函数,一个是用来分段的,
     54 //一个是用来翻转的,我们就以题目中给的例子来看,对于给定链表1->2->3->4->5,
     55 //一般在处理链表问题时,我们大多时候都会在开头再加一个dummy node,因为翻转链表时头结点可能会变化
     56 //为了记录当前最新的头结点的位置而引入的dummy node,那么我们加入dummy node后的链表变为
     57 //- 1->1->2->3->4->5,如果k为3的话,我们的目标是将1, 2, 3翻转一下,那么我们需要一些指针
     58 //,pre和next分别指向要翻转的链表的前后的位置,然后翻转后pre的位置更新到如下新的位置:
     59 
     60 
     61 
     62 //复制代码
     63 //- 1->1->2->3->4->5
     64 //|        |  |
     65 //pre      cur next
     66 //
     67 //- 1->3->2->1->4->5
     68 //|     |  |
     69 //cur   pre next
     70 //复制代码
     71 
     72 
     73 //以此类推,只要cur走过k个节点,那么next就是cur->next,
     74 //就可以调用翻转函数来进行局部翻转了,注意翻转之后新的cur和pre的位置都不同了,
     75 //那么翻转之后,cur应该更新为pre->next,而如果不需要翻转的话,cur更新为cur->next,
     76 
     77 
     78 
     79 //解法一://耗时超过自己的解答
     80 
     81 class Solution {
     82 public:
     83     ListNode* reverseKGroup(ListNode* head, int k) {
     84         if (!head || k == 1) return head;
     85         ListNode *dummy = new ListNode(-1), *pre = dummy, *cur = head;
     86         dummy->next = head;//添加头结点
     87         for (int i = 1; cur; ++i) {
     88             if (i % k == 0) {
     89                 pre = reverseOneGroup(pre, cur->next);
     90                 cur = pre->next;
     91             }
     92             else {
     93                 cur = cur->next;
     94             }
     95         }
     96         return dummy->next;
     97     }
     98     ListNode* reverseOneGroup(ListNode* pre, ListNode* next) {
     99         ListNode *last = pre->next, *cur = last->next;
    100         while (cur != next) {
    101             last->next = cur->next;
    102             cur->next = pre->next;
    103             pre->next = cur;
    104             cur = last->next;
    105         }
    106         return last;
    107     }
    108 };
    109 
    110 
    111 
    112 //我们也可以在一个函数中完成,我们首先遍历整个链表,统计出链表的长度,
    113 //然后如果长度大于等于k,我们开始交换节点,当k = 2时,每段我们只需要交换一次,
    114 //当k = 3时,每段需要交换2此,所以i从1开始循环,注意交换一段后更新pre指针,然后num自减k
    115 //直到num < k时循环结束,参见代码如下:
    116 
    117 
    118 
    119 //解法二:时间更长!!!!
    120 
    121 
    122 class Solution {
    123 public:
    124     ListNode* reverseKGroup(ListNode* head, int k) {
    125         ListNode *dummy = new ListNode(-1), *pre = dummy, *cur = pre;
    126         dummy->next = head;
    127         int num = 0;
    128         while (cur = cur->next) ++num;
    129         while (num >= k) {
    130             cur = pre->next;
    131             for (int i = 1; i < k; ++i) {
    132                 ListNode *t = cur->next;
    133                 cur->next = t->next;
    134                 t->next = pre->next;
    135                 pre->next = t;
    136             }
    137             pre = cur;
    138             num -= k;
    139         }
    140         return dummy->next;
    141     }
    142 };
    143 
    144 
    145 
    146 //我们也可以使用递归来做,我们用head记录每段的开始位置,cur记录结束位置的下一个节点,
    147 //然后我们调用reverse函数来将这段翻转,然后得到一个new_head,原来的head就变成了末尾,
    148 //这时候后面接上递归调用下一段得到的新节点,返回new_head即可,参见代码如下:
    149 
    150 
    151 class Solution {
    152 public:
    153     ListNode* reverseKGroup(ListNode* head, int k) {
    154         ListNode *cur = head;
    155         for (int i = 0; i < k; ++i) {
    156             if (!cur) return head;
    157             cur = cur->next;
    158         }
    159         ListNode *new_head = reverse(head, cur);
    160         head->next = reverseKGroup(cur, k);
    161         return new_head;
    162     }
    163     ListNode* reverse(ListNode* head, ListNode* tail) {
    164         ListNode *pre = tail;
    165         while (head != tail) {
    166             ListNode *t = head->next;
    167             head->next = pre;
    168             pre = head;
    169             head = t;
    170         }
    171         return pre;
    172     }
    173 };
    174         
    175 
    176 void T025() {
    177     ListNode* N = new ListNode(0);
    178     ListNode* p = N;
    179     for (int i = 0; i < 5; ++i) {
    180         ListNode* q = new ListNode(0);
    181         q->val = i + 1;
    182         p->next = q;
    183         p = q;
    184     }
    185     p = N->next;
    186     cout << "原:";
    187     while (p) {
    188         cout << p->val << '	';
    189         p = p->next;
    190     }
    191     cout << endl;
    192     Solution S;
    193     p = S.reverseKGroup(N->next,3);
    194     cout << "转:";
    195     while (p) {
    196         cout << p->val << '	';
    197         p = p->next;
    198     }
    199     cout << endl;
    200     
    201 
    202 }
  • 相关阅读:
    A. Generous Kefa
    1031 骨牌覆盖
    1074 约瑟夫环 V2
    1073 约瑟夫环
    1562 玻璃切割
    Ants
    1024 矩阵中不重复的元素
    1014 X^2 Mod P
    1135 原根
    1010 只包含因子2 3 5的数
  • 原文地址:https://www.cnblogs.com/zzw1024/p/10525118.html
Copyright © 2020-2023  润新知