版本说明
当前版本号[20230903]。
版本 | 修改说明 |
---|---|
20230903 | 初版 |
24. 两两交换链表中的节点
力扣题目链接
更多内容可点击此处跳转到代码随想录,看原版文件
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
思路
这道题目正常模拟就可以了。
建议使用虚拟头结点,这样会方便很多,要不然每次针对头结点(没有前一个指针指向头结点),还要单独处理。
对虚拟头结点的操作,还不熟悉的话,可以看这篇代码随想录—力扣算法题:203移除链表元素.Java版(示例代码与导图详解)。
接下来就是交换相邻两个元素了,此时一定要画图,不画图,操作多个指针很容易乱,而且要操作的先后顺序
初始时,cur指向虚拟头结点,然后进行如下三步:
操作之后,链表如下:
看这个可能就更直观一些了:
对应代码:
/**
* swapPairs - 链表两两交换
* head - 链表的头结点
* return - 交换后的链表头结点
*/
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode dumyhead = new ListNode(-1); // 设置一个虚拟头结点
dumyhead.next = head; // 将虚拟头结点指向head,这样方便后面做删除操作
ListNode cur = dumyhead;
ListNode temp; // 临时节点,保存两个节点后面的节点
ListNode firstnode; // 临时节点,保存两个节点之中的第一个节点
ListNode secondnode; // 临时节点,保存两个节点之中的第二个节点
// 当前节点和下一个节点都存在时进行交换
while (cur.next != null && cur.next.next != null) {
temp = cur.next.next.next; // 保存当前节点后面的节点
firstnode = cur.next; // 保存当前节点
secondnode = cur.next.next; // 保存下一个节点
cur.next = secondnode; // 步骤一: 将当前节点指向下一个节点
secondnode.next = firstnode; // 步骤二: 将下一个节点指向当前节点
firstnode.next = temp; // 步骤三: 将当前节点指向原来的后续节点
cur = firstnode; // cur移动到当前已经交换完的节点,准备进行下一轮交换
}
return dumyhead.next;
}
}
递归方法
解释:
- 首先,判断链表的为空或者只有一个节点,如果满足条件,则无需交换,直接返回头结点。
- 否则,我们需要交换两个相邻节点。这里我们可以使用递归的方法,先把第一个节点的下一个节点保存为
nextNode
。 - 然后,我们对剩余部分进行递归调用
swapPairs(nextNode.next)
,得到交换后的链表头结点。 - 接着,我们将原来的第二个节点的
next
指针指向原来的第一个节点(即使交换之后的链表的头结点)。 - 最后,我们将交换后的第二个节点返回作为新链表的头结点。
通过递归的方式,反复调用swapPairs
方法,直到链表的最后一个节点或只剩一个节点时终止递归。最终返回交换后的链表头结点。
请注意,以上代码是基于对问题的理解和分析,但可能不是完整的、可执行的代码。你可以结合实际需求进行代码的调整和完善。
参考代码:
// 递归版本
class Solution {
/**
* swapPairs - 链表两两交换节点(递归版本)
* head - 链表的头结点
* return - 交换后的链表头结点
*/
public ListNode swapPairs(ListNode head) {
// base case 退出提交
// 如果链表为空或只有一个节点,直接返回头结点
if(head == null || head.next == null) return head;
// 获取当前节点的下一个节点
ListNode next = head.next;
// 进行递归
// 递归调用swapPairs方法,传入next.next作为新的头结点
ListNode newNode = swapPairs(next.next);
// 这里进行交换
// 将next节点的next指针指向head,实现两节点交换
next.next = head;
// 将head节点的next指针指向递归得到的新头结点newNode
head.next = newNode;
// 返回交换后的头结点(原来的第二个节点)
return next;
}
}
总结
定义一个Solution类,其中包含了一个swapPairs方法,该方法用于交换给定链表中的每两个相邻节点。代码通过引入一个虚拟头结点dummyhead来简化操作。
在方法体内,建立了一些临时节点,用于保存当前节点、下一个节点和后续节点。然后,通过三个步骤实现交换节点的操作:步骤一将当前节点指向下一个节点,步骤二将下一个节点指向当前节点,步骤三将当前节点指向原来的后续节点。循环遍历链表直到当前节点或下一个节点为空。
ead来简化操作。
在方法体内,建立了一些临时节点,用于保存当前节点、下一个节点和后续节点。然后,通过三个步骤实现交换节点的操作:步骤一将当前节点指向下一个节点,步骤二将下一个节点指向当前节点,步骤三将当前节点指向原来的后续节点。循环遍历链表直到当前节点或下一个节点为空。
最后,返回虚拟头结点的下一个节点作为交换后的链表头结点。