代码随想录算法Day04-两两交换链表中的节点、删除链表的倒数第N个节点、环形链表II

两两交换链表中的元素

  1. 这个题要求两个一对交换,这个过程主要是:指针指向的变化,操作节点的边界问题
  2. 操作节点:这个节点应该要求是两个交换的节点的前一个节点,假设是0,那么改变的时候就是1->3,2->1,0->2这样的指针变化,既然是前一个节点,为了方便,依旧是设置虚拟头节点
  3. 边界条件:如果是奇数,cur.next.next为空结束,如果是偶数cur.next为空结束(偶数这里因为到不了cur.next.next为空这个条件,但是加上这个条件也没什么影响,所以这里直接用两个条件的&&)
  4. 指针变化的时候注意顺序:将需要指向的元素给存下来
public ListNode swap(ListNode head) {
	ListNode dummy = new ListNode(0,head);
	ListNode cur = dumy;
	while(cur.next != null && cur.next.next != null) {
		ListNode temp = cur.next;
		cur.next = cur.next.next;
		ListNode temp1 = cur.next.next;
		cur.next.next = temp;
		temp.next = temp1;
		cur = cur.next.next;
	}
	return dummy.next;
}

移除链表倒数第N个节点

  1. 快慢指针,需要一个虚拟头节点,因为删除head的时候也需要找到head前面一个元素dummy
  2. 计算从dummy到null,需要整个链表长度size+1步,倒数第n个节点相当于从null向前走n步,相当于从dummy向前走size+1-n步,也就是slow向前走size+1-n步,所以快指针先向前走n步,然后快慢指针再一起向前走size+1-n步(fast == null),就可以到达要删除的元素。但是我们需要的是前一个元素,所以fast应该先向前走n+1步。
public ListNode delete(ListNode head,int n) {
	ListNode dummy = new ListNode (0,head);
	ListNode fast = dummy;
	ListNode slow = dummy;
	for(int i = 0;i < n+1;i++){
		fast = fast.next;
	}
	while(fast != null ){
		fast = fast.next;
		slow = slow.next;
	}
	slow.next = slow.next.next;
	return dummy.next;
}

环形链表II

  1. 快慢指针,fast走两步,slow走一步,如果能相遇,说明有环。
  2. 快指针相对于慢指针的速度是1,所以在环上不停的遍历,快指针肯定能追上慢指针。
  3. 环形的入口:0--入口:x;入口到相遇位置:y;相遇位置到入口:z;
    慢指针走了:x+y
    快指针走了:x+n(y+z)+y
    2(x+y) = x+n(y+z)+y
    x+y = n(y+z)
    x = (n-1)(y+z)+z 也就是x是等于相遇位置到入口加上不定数量的环的长度的,所以如果slow从head开始,fast从相遇位置开始,每人走一步,一定可以在入口处相遇
public ListNode cycle(ListNode head) {
	ListNode fast = head;
	ListNode slow = head;
	while(fast != null && fast.next != null) {
		fast = fast.next.next;
		slow = slow.next;
		if(slow == fast) {
			slow = head;
			while(slow != fast) {
				slow = slow.next;
				fast = fast.next;
			}
			return slow;
		}
	}
	return null;
}
posted @ 2025-07-14 15:28  AAqqs  阅读(20)  评论(0)    收藏  举报