LeetCode Swap Nodes in Pairs

本文探讨了在单链表中交换相邻节点的有效方法。通过分析不同实现方式,包括使用额外空间、直接交换节点值以及实际节点位置交换,详细解释了每种方法的优势与挑战。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

 

Given a linked list, swap every two adjacent nodes and return its head.

For example,
Given 1->2->3->4, you should return the list as 2->1->4->3.

Your algorithm should use only constant space. You may not modify the values in the list, only nodes itself can be changed.

题意:

就是给定一个单链表,然后交换一对节点的位置,然后再输出。这道题目看似简单,其实对于单链表的操作要非常熟练,一不小心就会出错。一开始LZ采用了一种比较消耗空间的方法,也就是新开一个单链表,将结果保存在这个单链表中,然后依次将这个单链表的节点重新往刚才的那个单链表中传,但是出现了Memory Limit的错误,也就是空间复杂度出现限制。代码如下:

 

public ListNode swapPairs(ListNode head)
	{
		LinkedList<ListNode> list = new LinkedList<ListNode>();
		if(head == null)
			return null;
		ListNode node = head;
		ListNode nodes = head;
		while(node != null && node.next != null)
		{
			ListNode a = node;
			System.out.println(a.val);
			ListNode b = node.next;
			System.out.println(b.val);
			list.add(b);
			list.add(a);
			node = node.next.next;
		}
		if(node != null && node.next == null)
		   list.add(node);
		head = list.get(0); //这里要特别注意,就是在java中,链表保存的是地址,而不是数值,所以这个head一定要重新进行地址的赋值。
		System.out.println(head.val);
		nodes = head;
		int i = 1;  
		while(i < list.size())
		{
		    System.out.println(nodes.val);
			nodes.next = list.get(i);
			nodes = nodes.next;
			i++;
		}
		return head;
	}

那么考虑换方法,后来又想到一种最简单的方法,也就是直接交换值,因为此题没说一定要交换节点,所以我们可以直接交换节点的值即可。省去了交换节点带来的麻烦。

 

 

public ListNode swapPairs(ListNode head)
	{
		if(head == null || head.next == null)
			return head;
		//ListNode node = head;
		int count = 0;
	        ListNode node = head;
		while(node != null && node.next != null)
		{
			int value1 = node.val;
			int value2 = node.next.val;
			node.val = value2;   //交换的是节点的值
			node.next.val = value1;
			if(count == 0)
			   head = node;
			count ++;
			node = node.next.next;
		}
		return head;
	}


可是LZ觉得如果一开始就直接采用交换节点的值,那么也太简单了,所以就考虑采用交换节点来做,但是交换节点出现了很多错误,并不是非常容易,首先是单链表的头结点的指向问题,我采用了一个count来做,一旦这个count为0,那么说明只交换了第一个和第二个节点,那么我们就可以将head重新指向新交换后的节点了,这是其一。其二,首先前两个节点交换之后,第二个节点指向没有交换的第三个节点,而待会儿第三个和第四个节点交换以后,其实刚才,第二个节点还是指向新交换的第四个节点,所以这里会出现断链的情况,所以,我采用了临时保存上一次交换完后的第二个节点,然后再往下做。这样就不会出错了,这两个错误是我这道题遇到的,尤其是第二个,困扰了我一天,以后做单链表的题目,节点与节点之间的指向还是得考虑清楚才行。

 

public static ListNode swapPairs(ListNode head)
	{
		if(head == null || head.next == null)
			return head;
		ListNode p = head;
		ListNode q = head.next;
		ListNode s = null,t = null;
		int count = 0;
		while(p != null && q != null)
		{
			s = q.next;
			p.next = s;
			q.next = p;
			if(count == 0)   //这里判断,如果count为0,那么说明只是经过了第一次的交换,那么这个t先保存刚才的那个交换之后的第二个节点
			{
				t = p;
				head = q;    //这个头结点现在需要重新指向了,因为已经经过交换了,这里要特别当心。
			}
			else if(count != 0)
			{
				t.next = q;   //如果是第二及以后的交换,那么得先考虑保存将上一次交换之后的第二个节点的下一个节点更新成为这一次交换会后的节点
				t = p;   //然后再考虑将这一次交换之后的第二个节点保存给t
			}
			count++;
			p = s;
			if(p != null)
			  q = p.next;
		}
		return head;
	}


做了这题,LZ对于单链表的认识又加深了一些,但是还是需要多做相应的题目来加深印象。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值