代码随想录算法训练营第42期 第四天|24.两两交换链表中的节点 、 19.删除链表的倒数第N个节点 、 160.链表相交 、142.环形链表II

一、24.两两交换链表中的节点

学习链接:两两交换链表中的节点

状态:做出来了

细节之处:1 2 3(代码里面)

思路:使用虚拟头节点,找到要交换的俩个链表节点前一个位置记为cur,使用temp保存cur,temp1保存下一个cur即cur.next.next.next.然后执行三个步骤如代码所示。

class Solution {
    public ListNode swapPairs(ListNode head) {
		ListNode dummy=new ListNode();
		dummy.next=head;
		ListNode cur=dummy;
		while(cur.next!=null&&cur.next.next!=null) //1 必须先写cur.next,如果先cur.next.next,cur.next为空的话,会造成空指针异常
		{
			ListNode temp=cur.next;
			ListNode temp1=cur.next.next.next;
			cur.next=cur.next.next;   //2 顺序很重要,这个在这代码必须在第一个,因为cur.next.next没保存
			cur.next.next=temp;
			temp.next=temp1;
			cur=cur.next.next; //3 移动到下一个cur
		}
		return dummy.next;
    }
}

二、19.删除链表的倒数第N个节点

学习链接:删除链表的倒数第N个节点

状态:做出来了

细节之处:1 2 3(代码里面)

思路:只需让慢指针和快指针一直保持n+1的距离,这样快指针到到达终点后,慢指针恰好在删除元素的前一个节点。

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
		ListNode dummy=new ListNode();
		dummy.next=head;
		ListNode cur=dummy.next;
		int stride=0;  //1 快慢节点的距离

		ListNode slow=dummy;
		while(cur!=null)
		{
			cur=cur.next;
			stride++;
			if(stride>=n+1){slow=slow.next;}  //2 保持快慢节点的距离在n+1,使得slow为要删除的前一个节点
		}
		if(slow.next!=null)  //3 防止链表只有一个元素来报出空指针异常
		{slow.next=slow.next.next;}
		return dummy.next;
    }
}

三、160.链表相交

学习链接:链表相交

状态:做出来了

细节之处:1 2 3(代码里面)

 思路:因为这道题是链表,由于相交的部分肯定是在尾部往前,并且如果相交,俩链表的尾部一定是相同的,所以不需要俩层循环,直接对其尾部一个一个比较即可。

public class Solution {
	public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
		ListNode curA = headA;
		ListNode curB = headB;
		int lenA = 0;
		int lenB = 0;
		while (curA != null) {
			lenA++;
			curA = curA.next;
		}
		while (curB != null) {
			lenB++;
			curB = curB.next;
		}
		curA = headA;  //1 算出长度之后一定要回到原来状态
		curB = headB;
		if (lenA < lenB) {     //2 使得A一直是俩链表中最长的一个,减少后面代码的冗余
			int templen = lenB;
			lenB = lenA;
			lenA = templen;
			ListNode temp = curB;
			curB = curA;
			curA = temp;
		}
		int gap = lenA - lenB;
		while (gap-- > 0) {
			curA = curA.next;
		}
		while (curB != null) {    //3 因为这道题目的特殊性,公共部分一定在末尾
			if (curA == curB) return curA;
			curA = curA.next;
			curB = curB.next;
		}
		return null;


	}
}

四、142.环形链表II 

学习链接:环形链表II

状态:没做出来

细节之处:1 2 3(代码里面)

思路:这道题需要数学证明,所以放截图了(代码随想录里面的)。

证明有环:

证明环的入口:

public class Solution {
	public ListNode detectCycle(ListNode head) {
		ListNode slow = head;
		ListNode fast = head;
		while (fast != null && fast.next != null) {  //1 只需要防止fast空指针异常,因为fast比slow快
			slow=slow.next;
			fast=fast.next.next;
			while(slow==fast)   //2 已经判断出来有环了
			{
				ListNode first=head;
				ListNode second=slow;
				while(second!=first)  //3 相遇的地方就是入口处,上面有证明
				{
				first=first.next;
				second=second.next;
				    }
				return  first;
			}
		}
		return null;
	}
}

五、 总结

学了虚拟头节点(在增删改的时候,不需要特殊处理头节点),也懂得了链表的基本操作和利用链表解决算法问题。本人经常出错的点在空指针异常(首节点为空造成的),还有一些cur(当前节点)为了一些目的进行的操作,最后cur没有回到之前的位置,造出错误,这些需要特别注意。

  • 12
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值