代码随想录算法训练营Day04

两两交换链表中的节点

注意循环控制条件以及cur的位置
交换的是cur后面的两个节点的位置

class Solution {
	public ListNode swapPairs(ListNode head) {
		ListNode dummyHeadNode = new ListNode(0);
		dummyHeadNode.next = head;
		ListNode current = dummyHeadNode;
		while(current.next!=null&&current.next.next!=null){
			ListNode temp = current.next;
			ListNode temp1 = temp.next.next;
			current.next = temp.next;
			temp.next.next = temp;
			temp.next = temp1;
			current = temp;
		}
		return dummyHeadNode.next;
	}
}

删除链表倒数第n个节点

双指针是最优解法,也可以用笨方法,倒数第n个是正数第size-n个,再用deleteAtIndex删除即可

class Solution {
	public ListNode removeNthFromEnd(ListNode head, int n) {
		//用到了双指针的思想,一个快指针一个慢指针,快指针先往后移动,然后同时向后移动,当快指针移动到末尾时,慢指针移动到要删除元素的位置
		ListNode dummyHeadNode = new ListNode(0,head);
		ListNode slow = dummyHeadNode;
		ListNode fast = dummyHeadNode;
		for(int i = 0;i<n+1;i++){
			fast = fast.next;
		}
		while(fast!=null){
			slow = slow.next;
			fast = fast.next;
		}
		slow.next = slow.next.next;
		return dummyHeadNode.next;
	}
}

链表相交

双指针,保证链表的current指针齐头并进,直至遇到交点

public class Solution {
	public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
		ListNode dummyHeadNodeA = new ListNode(0,headA);
		ListNode dummyHeadNodeB = new ListNode(0,headB);
		ListNode currentA = dummyHeadNodeA;
		ListNode currentB = dummyHeadNodeB;
		int sizeA = 0;
		int sizeB = 0;
		sizeA = getSize(currentA);
		sizeB = getSize(currentB);
		int dif = 0;
		if(sizeA>sizeB){
			dif = sizeA-sizeB;
			for(int i = 0;i<dif;i++){
				currentA = currentA.next;
			}
		}else{
				dif = sizeB-sizeA;
				for(int i = 0;i<dif;i++){
					currentB = currentB.next;
				}
		}
		while(currentA!=currentB){
			currentA = currentA.next;
			currentB = currentB.next;
		}
		return currentA;
	}
	public int getSize(ListNode current){
		int size = 0;
		while(current!=null){
			current = current.next;
			size++;
		}
		return size;
	}
}

环形链表

这里不用dummy Head Node了

成环的条件

  1. 定义两个指针

    • 慢指针(slow):每次移动一个节点。

    • 快指针(fast):每次移动两个节点。

  2. 操作步骤

    • 两个指针从链表头节点同时开始移动。

    • 如果链表中存在环,快指针和慢指针最终会在环内相遇。

    • 如果链表没有环,快指针会先到达链表末尾(即指向 null)。

  3. 原理

    • 在环内,快指针的速度比慢指针快,因此它会不断追赶慢指针并最终相遇。

    • 时间复杂度为𝑂(𝑛),空间复杂度为 𝑂(1)。

找到环的入口

  1. 当快慢指针在环内相遇后,将其中一个指针(如 slow)重新放回链表头。

  2. 两个指针以相同速度(每次移动一个节点)继续移动。

  3. 它们再次相遇时,相遇的节点即为环的入口。

public class Solution {
	public ListNode detectCycle(ListNode head) {
		if (head == null || head.next == null) {
			return null; // 链表为空或只有一个节点时,不可能有环
		}
		ListNode slow = head;
		ListNode fast = head;
		do {
			if (fast == null || fast.next == null) {
				return null; // 快指针先到末尾,这里考虑了奇偶数的问题,说明没有环
			}
			slow = slow.next; // 慢指针移动一步
			fast = fast.next.next; // 快指针移动两步
		} while (slow != fast);//为什么do-while?因为一开始将slow和fast都赋值为head,根本不进循环啊!!
		slow = head;
		while(slow!=fast){
			slow = slow.next;
			fast = fast.next;
		}
		return slow;
	}
}
posted @ 2025-03-30 09:41  Anson_502  阅读(48)  评论(0)    收藏  举报