##LeetCode—24. Swap Nodes in Pairs
####题目
https://leetcode.com/problems/swap-nodes-in-pairs/description/
将链表中两两相邻的节点交换,返回头结点。
####思路及解法
首先需要确定需要几个指针,head的前驱指针dummy,指向两个交换节点的指针left和right,另外还要有一个指针beforeLeft指向left的前驱用于交换。注意题目并没有说链表的节点数是双数,所以单双数的情况都要想到。
对于一个以上节点的情况,初始left和right分别为head和head的后驱,交换,然后将beforeLeft指向交换后的后一个节点,这时候我们需要去判断是不是还需要进行交换,也就是后面的链表还有几个节点,如果后面只有一个以下的节点,那么直接返回dummy的后驱。如果有两个以上的节点,则将left和right指向相应的节点,继续交换。循环上面的过程。不过,第一次做这道题的时候,我没有想好怎么设计循环条件的判断,用了beforeLeft的后驱不为空作为条件,测试了一下通过了,就直接用了,但感觉逻辑上不太正确。。。可以看一下代码,感觉每一次应该是在第一个return跳出去的,而不是经过了最后的return
然后去看看了别人写的代码,附在后面。不同之处做法是这样的:在判断有两个以上节点的情况下,永远将最后要交换的两个节点放在循环之外,在最后进行交换,这样循环的判断条件就可以用
right.next != null && right.next.next != nul
判断了
这道题最关键的问题是想清楚由于单双数造成的最后是否剩下单独数字的问题。很容易知道有两种情况,比如[2,1,4,3,5]和[2,1,4,3],但实际上这两种情况实际操作是一样的,就是最后只对34做了交换,有没有5这个这个数字只是在判断条件上有区别。我们回退一步来看,[2,1,3,4,5]和[2,1,3,4],此时左右指针分别指向3和4,对于两种情况要做的操作是一样的,因此我们将这个操作放到最后,也就是不管怎么样都要进行的操作。那么那么判断条件是什么呢?当右指针的next为空或者右指针的next的next为空。此时我们跳出常规的while循环,进行我们上面说到的最后一部操作就行了。
####代码
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode swapPairs(ListNode head) {
if(head == null || head.next == null) return head;
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode beforeLeft = dummy;
ListNode left = head;
ListNode right = head.next;
do{
left.next = right.next;
right.next = left;
beforeLeft.next = right;
beforeLeft = left;
if(beforeLeft.next == null || beforeLeft.next.next == null){
return dummy.next;
}else{
left = beforeLeft.next;
right = left.next;
}
}while(beforeLeft.next != null);
return dummy.next; // 似乎都没有走这里
}
}
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode swapPairs(ListNode head) {
if(head == null || head.next == null) return head;
ListNode fakeHead = new ListNode(0);
fakeHead.next = head;
ListNode pre = fakeHead;
ListNode left = head;
ListNode right = head.next;
while(right.next != null && right.next.next != null){
left.next = right.next;
right.next = left;
pre.next = right;
left = left.next;
right = right.next.next.next;
pre = pre.next.next;
}
left.next = right.next;
right.next = left;
pre.next = right;
return fakeHead.next;
}
}