这两天遇到几个反转链表的题目,觉得比较有意思,这里分享一下:
1 给出一个链表,同时给出索引m和n,要求将位于m和n之间的节点反转,然后返回结果。
1 < m < n < lengthof(LinkList)
eg: 1->2->3->4->5 m =2, n = 4 输出:1 -> 4 -> 3 -> 2 ->5
反转链表的时候,有一个比较关键的技巧,比如链表1-2-3-4-5
第一次反转的时候,pre = 1,cur = 2,这时候把2换掉最前面得到2-1-3-4-5
再次反转的时候,pre = 1 cur = 3, 得到3-2-1-4-5,每次都把cur插入到最前面,
最后得到5-4-3-2-1.这里也是采用的同样的方法。
ListNode* reverse(ListNode * head, int m,int n)
{
ListNode dummy(0);
dummy.next = head;
ListNode * pre2, pre1 = &dummy;
for(int i = 1; i < = n; i++)
{
// pre2 stores the node before mth node
if(i == m) pre2 = pre1;
if(i > m && i <= n)
{
// for node between m & n, swap the second node right after pre2. do this repetaly.
pre1 -> next = head -> next;
head -> next = pre2 ->next;
pre2 -> next = head;
head = pre1;
}
pre1 = head;
head = head -> next;
}
return dummy.next;
}
2 反转链表也可以有如下的衍生形式:
比如以k为距离反转长度为n的链表:k = 2, n= 4;
1-2-3-4, 得到2-1 - 4-3,
这个就是多添加了一个遍历的时候对长度的判断,只有在遍历到k的整数倍的时候,才把这k个链表节点拿出来反转,而反转的过程则跟上题一样。
这里给出一份参考代码,来自leetcode @Linfuzki
http://discuss.leetcode.com/questions/206/reverse-nodes-in-k-group
ListNode *reverseKGroup(ListNode *head, int k) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
if (!head || k <= 1) return head;
ListNode dummy(0);
dummy.next = head;
ListNode *pre = &dummy;
int i = 0;
while (head) {
i++;
if (i % k == 0) {
pre = reverse(pre, head->next);
head = pre->next;
} else {
head = head->next;
}
}
return dummy.next;
}
ListNode *reverse(ListNode *pre, ListNode *next) {
ListNode *last = pre->next;
ListNode *cur = last->next;
while (cur != next) {
last->next = cur->next;
cur->next = pre->next;
pre->next = cur;
cur = last->next;
}
return last;
}