1. 题目描述
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.
交换一个单项链表中相邻的元素,且不使用多余的空间,只操作单向链表中的节点指针。
2. 解题思路
一般链表操作我首先先考虑链表为空和只有一个节点的情况,一般这种情况都直接返回,这个题也如是,一个节点不用交换了,直接返回head就好。之后就要开始仔细考虑在操作链表指针的过程中,断开一个指针的时候有没有其他指针指向他后面的元素,如果没有很有可能会发生丢失,还有就是如果我想操作这个节点的前一个或前几个节点的时候,必须也要存下来,因为他是一个单向链表,过去了就找不回来啦。下面我们再画一个图,来看看这个题应该如何对指针进行操作。
既然是要进行交换操作,那么至少就需要两个指针p, q。所谓交换两个节点,就是原本q的next要指向p,原本p的next要指向q的next,这就完成了两个节点的交换。过程如图12,3为完成一次交换后的结果。之后我们将p、q后移对下一组进行操作,这时就发现了一个问题,如果3、4进行交换了,1还是指向3的,这样4就丢了,所以1应该修改next指向4才对。这种问题发生在后面有偶数个元素的情况,即如果后面没有4,到3就结束了,那么1指向3是对的。所以就发现了跟之前重合的部分,因为q如果为空的时候即最后只有一个节点了,压根就不用交换了,也就直接结束了操作。所以当q不为空时,我们需要修改1的next指针,指向交换后在前面的元素。所以我们定义一个r,保存住原来1的位置,进入下一轮操作时,将r的next修改为q,其他的过程还保持不变。宗旨看图应该就可以看明白啦XD
3. Code
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public class Solution {
public ListNode swapPairs(ListNode head) {
// 链表只有一个节点或没有节点直接返回
if (head == null || head.next == null)
{
return head;
}
// 创建两个暂存指针,指向head和head的下一个元素
ListNode p = head;
ListNode q = head.next;
// 因为交换改变了head,所以head需要移动到下一个元素
head = head.next;
ListNode r = null;
// q等于空时,只有一个元素,不用进行交换
while(q != null)
{
if(r != null)
{
r.next = q; // ③
}
p.next = q.next; // ①
q.next = p; // ②
r = p;
p = p.next; // p向后移动到p’
// 当p为空时,后面就没有节点了,证明操作已经完成
if(p == null) break;
q = p.next; // q向后移动到q’
}
return head;
}
}