LeetCode 24:24. 两两交换链表中的节点
题目描述:
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
解题思路:
(1)需要创建两个临时节点,一个存储cur.next节点,一个存储cur.next.next.next节点
(2)循环终止条件:
如果节点为奇数:cur.next.next == null
如果节点为偶数:cur.next ==null
(3)交换的操作
public static ListNode swapPairs(ListNode head) {
if (head == null || head.next == null) {
return head;
}
//定义虚拟节点
ListNode dummy = new ListNode(0);
dummy.next = head;
//定义当前节点
ListNode cur = dummy;
//遍历终止条件
//如果链表的长度是奇数,则head的next的next节点是空则终止
//如果链表的长度是偶数,则head的next节点是空则终止
while (cur.next != null && cur.next.next != null) {
//定义临时节点1存放cur的next节点
ListNode temp1 = cur.next;
//定义临时节点2存放cur的next的next的next节点
ListNode temp2 = cur.next.next.next;
//1.将cur的next节点指向cur的next的next节点
cur.next = cur.next.next;
//2.将cur的next的next节点指向temp1
cur.next.next = temp1;
//3.将cur的next的next的next节点指向temp2
cur.next.next.next = temp2;
//cur向右移动两位
cur = cur.next.next;
}
return dummy.next;
}
LeetCode 19:19. 删除链表的倒数第 N 个结点
题目描述:
给你一个链表,删除链表的倒数第 n
个结点,并且返回链表的头结点。
解题思路:
(1)利用快慢指针解决
创建一个虚拟链表,slow指针指向dummy,fast指针指向fast
(2)fast指针先走n步
(3)fast指针与slow指针同时移动,循环终止条件为fast指针移动到最后一个节点
(4)这样移动之后,当fast指针移动到最后时,slow指针指向的节点就是应该删除的节点
public ListNode removeNthFromEnd(ListNode head, int n) {
if(head == null){
return null;
}
ListNode fast = head;
ListNode dum = new ListNode(0, head);
ListNode slow = dum;
//快指针先走K步
for(int i = n; i > 0; i--) {
fast = fast.next;
}
while(fast != null){
slow = slow.next;
fast = fast.next;
}
//将k节点元素删除
slow.next = slow.next.next;
return dum.next;
}
LeetCode 面试题02.07 : 面试题 02.07. 链表相交
题目描述:
给你两个单链表的头节点 headA
和 headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null
。
图示两个链表在节点 c1
开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
解题思路:
(1)创建两个指针l1、l2,分别对应headA、headB
(2)分别遍历两个链表,获取两个链表的长度
(3)对两个长度进行比较,哪个链表的长度比较长,哪个链表先走gap(sizeA-sizeB)步
(4)循环两个链表,终止条件为两个链表相同,此时的链表就是相交的部分
LeetCode 142:19. 删除链表的倒数第 N 个结点
题目描述:
给定一个链表的头节点 head
,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos
是 -1
,则在该链表中没有环。注意:pos
不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
解题思路:
(1)利用快慢指针来解决,fast指针一次走两步,slow指针一次走一步,如果有环则两个指针必会相遇
(2)如何确定这个环的入口:
借用这张图来推导一下过程:
slow指针走的节点数:x+y
fast指针走的节点数: x+y+n(y+z)
经过推导可以得出:
2(x+y)= x+y+n(y+z)
代入n=1可以得出: x=z
所以在相遇之后,一个从相遇位置出发,一个从头结点出发,再次相遇的位置就是环形入口节点位置
public ListNode detectCycle(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while (fast != null && fast.next != null) {
//快指针一次走两步
fast = fast.next.next;
//慢指针一次走一步
slow = slow.next;
//如果fast与slow相等,则说明有环
if (fast == slow) {
//重新定义两个指针
ListNode index1 = fast;
ListNode index2 = head;
//让两个指针一起移动,到相遇的地方就是入环口
while(index1 != index2) {
index1 = index1.next;
index2 = index2.next;
}
return index1;
}
}
return null;
}