标签:返回 结束 解答 原来 原理 变化 例子 ret next
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 << ‘\t‘; 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 << ‘\t‘; 197 p = p->next; 198 } 199 cout << endl; 200 201 202 }
标签:返回 结束 解答 原来 原理 变化 例子 ret next
原文地址:https://www.cnblogs.com/zzw1024/p/10525118.html