Given a linked list, swap every two adjacent nodes and return its head.
Example:
Given 1->2->3->4, you should return the list as 2->1->4->3.
Note:
- Your algorithm should use only constant extra space.
- You may not modify the values in the list's nodes, only nodes itself may be changed.
本题是两个一组翻转链表,类似LeetCode 206. Reverse Linked List —— 反转链表又略有不同。思路其实是一样的,还是想两种方法来做,迭代和递归。
解法一,迭代:
遍历链表,一个一个的去交换前驱和后继节点。类似206,本题也要建立一个假节点去链接链表头,因为除非是单节点链表,否则原链表头一定不会是结果的链表头。用假节点去链接结果会更容易操作和理解。建立指针pre指向将要翻转的两个节点的前驱,如果pre.next和pre.next.next同时存在,那么就翻转对应节点。翻转的时候建立一些临时节点存储数据会使整个过程很清晰,详见代码。
解法二,迭代:
思路和206几乎一样。输入规模最小的问题即空链表和单节点链表,直接返回表头即可。当我们要处理k个节点的链表的时候,可以先处理k-2节点的子问题。之所以是k-2是因为每次都要处理成对的两个节点,所以递归要从成对后的第三个节点开始。递归返回的结果是已经翻转完成后的链表的首节点,那么如果把这个首节点的两个前驱对换,再把递归返回来的结果连在第一个前驱后面,即可完成整个k节点的翻转。详见代码注释。
解法一(Java)
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public ListNode swapPairs(ListNode head) { ListNode preHead = new ListNode(0); preHead.next = head; ListNode pre = preHead; while (pre.next != null && pre.next.next != null) { ListNode first = pre.next; ListNode second = first.next; ListNode third= second.next; pre.next = second; second.next = first; first.next = third; pre = pre.next.next; } return preHead.next; } }
解法二(Java)
/** * 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 second = head.next; //存储第二个节点在second中 head.next = swapPairs(second.next); //要递归处理second节点后的那个节点,并将翻转好的结果链接到second的前驱后,即head second.next = head; //再将second的前驱连在second后,完成翻转 return second; //翻转后,second永远是结果的首节点 } }