Leecode 24.两两交换链表中的节点

题目链接

原本以为链表是比较容易对付的知识点,但规模比较大的问题很容易在思考完成写代码的时候出现混乱,引发难以debug的问题.用画图这种更形象的方法可以比较有效的解决思路紊乱的问题.

测试用例和示意图
输入:head = [1,2,3,4]
输出:[2,1,4,3]

这道题的操作规模并不算很大,题目要求我们把链表中成对的结点两两交换后输出.很容易想到用迭代或者递归进行next结点的交换就可以解决问题,但在交换的顺序上需要用画图理清逻辑.

链表已经被定义好,val为值,next指向下一个结点的引用.

// 链表结点的定义,不需要写在程序里
public class ListNode {
	int val;
	ListNode next;
	
	ListNode() {}
	
	ListNode(int val) {this.val = val;}
	
	ListNode(int val, ListNode next) {
		this.val = val;
		this.next = next;
	}
}

看着示意图不难理清思路,以新定义的头结点作为起点(nowNode),交换后两个结点(leftNode和rightNode)在链表中的顺序,然后将交换后连接后方结点的结点设置为flag,继续执行交换,直到后方的结点不足两个.

操作前的链表长这样:

在这里插入图片描述
最后要达到的效果:

在这里插入图片描述

用代码实现.首先由于涉及到头结点
的移动,我们设置一个空结点重新作为头结点.交换的起点也是它.

ListNode dummyHead = new ListNode(-1,head);
ListNode nowNode = dummyHead;

对于每一个结点,作出交换操作,如果后面没有结点需要交换就直接退出循环

while (nowNode.next != null && nowNode.next.next != null) {
			ListNode leftNode = nowNode.next;
			ListNode rightNode = nowNode.next.next;
			
			leftNode.next = rightNode.next;
			rightNode.next = leftNode;
			nowNode.next = rightNode;
			nowNode = leftNode;
		}

最后返回虚拟头结点的next,也就是交换后真正的头结点

return dummyHead.next;

主要的难点在于交换的过程怎么实现.在每次交换开始时的情况就和上面的一样.

在这里插入图片描述
声明好临时变量之后,第一个操作用来把rightNode的next结点交给leftNode的next结点.因为前三个结点的next都需要指向新的结点,而已经有临时变量存放它们的引用,所以优先把待会会被覆盖的rightNode,next放到正确的位置.这时候示意图长这样

在这里插入图片描述

其他两个需要更改的next指针指向的引用都已经存放在变量中了,所以顺序不是那么重要.之后变成这样

在这里插入图片描述
但原来的rightNode.next结点引用,现在存放在leftNode.next中.
所以设置leftNode结点作为下一个交换的开始,检测后两个需要交换的结点是否存在.

nowNode后结点不够的情况已经在循环条件中考虑,而nowNode结点永远不会为空,因为初始值为自行创建的虚拟头结点,在满足交换条件并执行交换之后才会更新.

由于每一对结点都需要进行操作,所以时间复杂度为 O ( n ) O(n) O(n).代码使用常数个变量,空间复杂度为 O ( 1 ) O(1) O(1).

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
	public ListNode swapPairs(ListNode head) {
		ListNode dummyHead = new ListNode(-1,head);
		ListNode nowNode = dummyHead;
		while (nowNode.next != null && nowNode.next.next != null) {
			ListNode leftNode = nowNode.next;
			ListNode rightNode = nowNode.next.next;
			
			leftNode.next = rightNode.next;
			rightNode.next = leftNode;
			nowNode.next = rightNode;
			nowNode = leftNode;
		}
		
		return dummyHead.next;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值