LeetCode系列记录我学习算法的过程。
持续创作,加速成长!这是我参与「掘金日新计划 6 月更文挑战」的第 23 天,点击查看活动详情
题目
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
示例:
输入: head = [1,2,3,4]
输出: [2,1,4,3]
提示
- 链表中节点的数目在范围
[0, 100]内 0 <= Node.val <= 100
思路
这题又是每两项进行重复的操作,那便可以用递归的方法来实现,首先是找到递归结束的条件
即当结点只剩一个,或没有结点时,递归结束,返回自身
定义变量 res 获取当前结点的下一结点
然后当前结点的下一项由递归调用自身函数传入 res.next 获取
再将处理好的当前结点作为 res 的下一结点
最后将 res 返回即可
代码实现
/**
* 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
// 变量res获取下一结点
let res = head.next
// 当前结点的下一结点由递归调用自身函数获取
head.next = swapPairs(res.next)
// res 下一结点为当前结点
res.next = head
// 返回 res
return res
};
优化
既然可以用递归,那同样也可以使用循环来处理
- 如果链表只有一项或一项都没有,直接返回自身
- 定义一个虚拟头结点,让其下一项指向
head - 定义
prev节点指向虚拟头结点,用来链接每次交互后的链表 - 循环,先对当前项及下一项进行交换
- 然后通过
prev将交换后的链表与前面处理好的链表连接起来 - 移动
head及prev,以便进行下一次交换
/**
* 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
// 虚拟头节点,初始的时候让虚拟头节点下一项指向head
const res = new ListNode(0, head)
// prev指针
let prev = res
while (head && head.next) {
const next = head.next // 保存head的下一项
// 两两交换
head.next = next.next
next.next = head
// 将交换后的链表与前面的链表链接起来
prev.next = next
// 移动 prev 及 head 以便进行下一次交换
prev = head
head = head.next
}
return res.next
};