【Leetcode】【Medium】Swap Nodes in Pairs

Given a linked list, swap every two adjacent nodes and return its head.

For example,
Given 1->2->3->4, you should return the list as 2->1->4->3.

Your algorithm should use only constant space. You may not modify the values in the list, only nodes itself can be changed.

 

解题思路:

传统的链表操作题,需要注意如果结点不是偶数,最后一个结点不需要交换,放在队尾。

先条件:head不为空;head至少包含两个结点;

后条件:返回指向新链表第一个结点的指针;原链表结点全部加入新链表中,并且偶数对结点两两互换;新旧链表的结点数一致。

不变式:1、新建一个newhead指针,newhead->next永远指向新链表的头部;

    2、新建一个newlist指针,newlist永远指向新链表的最后一个结点;

    3、newlist->next始终为NULL;

    4、head指针永远指向还未被操作的旧链表第一个结点;

    5、新链表上的结点数加上旧链表剩余的结点数之和,应该和原链表结点数一致;

当head为空时,循环结束,每次循环:

    1、将head中的结点按对取出~交换~插入newlist末端

    2、若head只剩一个结点不够一对,则直接插入newlist末端;

 

解题步骤:

1、新建preHead结点,新建newlist指针;

2、按照不定式分析,开始循环,循环结束标志为head为空:

  (1)如果当前head只剩一个结点,则将其插入newlist后,并结束循环;

  (2)取出待操作的两个结点,head后移两位;

  (3)将这两个结点反转插入newlist中

3、释放preHead,返回newlist;

 

代码1:

 1 /**
 2  * Definition for singly-linked list.
 3  * struct ListNode {
 4  *     int val;
 5  *     ListNode *next;
 6  *     ListNode(int x) : val(x), next(NULL) {}
 7  * };
 8  */
 9 class Solution {
10 public:
11     ListNode* swapPairs(ListNode* head) {
12         /*
13         if (head == NULL || head->next == NULL) 
14             return head;
15         */
16         ListNode* newhead = new ListNode(0);
17         ListNode* newlist = newhead;
18         ListNode* preNode = NULL;
19 
20         while (head != NULL) {
21             if (head->next == NULL) {
22                 newlist->next = head;
23                 break;
24             }
25             preNode = head;
26             head = head->next->next;
27             preNode->next->next = preNode;
28             newlist->next = preNode->next;
29             newlist = preNode;
30             newlist->next = NULL;
31         }
32         
33         head = newhead->next;
34         delete newhead;
35         return head;
36     }
37 };

 

代码2,使用二维指针:

基本逻辑实现:

1 ListNode **p = &head;
2 while (*p && (*p)->next) {
3     // n表示待交换的两个结点中,后一个结点
4     ListNode* n = (*p)->next; 
5     (*p)->next = n->next; 
6     n->next = *p;
7     p = &(*p)->next;
8 }

由于二维指针p一直在操作当前需要交换的结点,不断向后迭代,而head指针此时指向的是链表中第二个结点(前两个交换);

因此上述代码唯一的问题是,没有指针指向头结点,无法返回...

所以我们希望在第一轮交换时,将head结点重新指向交换后的第一个结点。观察到第一轮交换时,*p其实就代表head,操作*p的指向,就是操作head的指向。

所以,最终代码为:

 1 /**
 2  * Definition for singly-linked list.
 3  * struct ListNode {
 4  *     int val;
 5  *     ListNode *next;
 6  *     ListNode(int x) : val(x), next(NULL) {}
 7  * };
 8  */
 9 class Solution {
10 public:
11     ListNode* swapPairs(ListNode *head) {
12         ListNode **p = &head;
13 
14         while (*p && (*p)->next) {
15             ListNode* n = (*p)->next;
16             (*p)->next = n->next;
17             n->next = *p;
18             *p = n;
19             p = &(*p)->next->next;
20         }
21 
22         return head;
23     }
24 };

 

posted @ 2015-05-19 02:14  胡潇  阅读(247)  评论(0编辑  收藏  举报