这是我参与11月更文挑战的第15天,活动详情查看:2021最后一次更文挑战」
两两交换链表中的节点(Swap Nodes in Pairs)
今天我们一起看一下这道leetcode题,原题传送门24. 两两交换链表中的节点
题目
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
Given a linked list, swap every two adjacent nodes and return its head. You must solve the problem without modifying the values in the list's nodes (i.e., only nodes themselves may be changed.)
Example
Input: head = [1,2,3,4]
Output: [2,1,4,3]
Input: head = []
Output: []
Input: head = [1]
Output: [1]
思考分割线
解题思路
首先看到这个题我就想到可以把偶数节点和奇数节点分开存放到两个数组中,则奇数数组可能和偶数数组相等或者为偶数数组的长度加 1。
其次当偶数数组和奇数数组都有值的时候,我们进行链表重新排序,把偶数数组中的第一个放到前面,奇数数组中的第一个放到后面。
最后我们再看奇数数组中是否有元素,如果有则加入到链表中,如果没有则链表两两交换完成。
以上思路代码如下:
原始版本
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var swapPairs = function(head) {
if(!head || !head.next) return head;
const oddArr = [];
const evenArr = [];
let list = head;
while(list) {
oddArr.push(list);
list.next && evenArr.push(list.next);
list = list.next?.next ?? null;
}
let dummyHead = new ListNode(0);
let h = dummyHead;
while(evenArr.length && oddArr.length) {
h.next = evenArr.shift();
h.next.next = oddArr.shift();
h = h.next.next;
h.next = null;
}
if(oddArr.length) {
h.next = oddArr.shift();
h.next.next = null
};
return dummyHead.next;
};
上面的算法时间复杂度是O(n), n是链表的节点数。空间复杂度也是:O(n)。
那么我们还有其他方法做这道题吗?答案是肯定的。那么我们先试着用递归调用来实现这个功能。
我们假设我们链表的长度大于2,设原来的头为 head为交换后的第二个元素, 新头部为newHead为 原来头部的 head.next;
然后如果链表有head.next的时候,我们递归调用后面排序完成的结果, 本次交换后的尾部head.next = swapPairs(newHead.next);
实现代码如下
递归版本
var swapPairs = function(head) {
// solution 2 -> recursion
if(!head || !head.next) return head;
let newHead = head.next;
head.next = swapPairs(newHead.next);
newHead.next = head;
return newHead;
};
上面的算法时间复杂度是O(n), n是链表的节点数。空间复杂度也是:O(n)。
既然可以递归实现那么就可以进行迭代实现,我们来实现一遍迭代的版本:
迭代版本
var swapPairs = function(head) {
// solution 3 -> iteration
if(!head || !head.next) return head;
const dummyHead = new ListNode(0);
dummyHead.next = head;
let temp = dummyHead;
while(temp && temp.next && temp.next.next) {
list1 = temp.next;
list2 = temp.next.next;
list1.next = list2.next;
temp.next = list2;
list2.next = list1;
temp = list1
}
return dummyHead.next;
};
此方法时间复杂度是O(n), n是链表的节点数。空间复杂度是:O(1)。【迭代相比于递归是省空间的】
good, 完美完成,以上就是本题的三种解法,你学会了吗?