LeetCode.24 两两交换链表中的节点
题目链接 两两交换链表中的节点
题解一、递归法
class Solution {
public ListNode swapPairs(ListNode head) {
if(head == null || head.next == null){
return head;
}
ListNode nextNode = head.next;
ListNode newNode = swapPairs(nextNode.next);
nextNode.next = head;
head.next = newNode;
return nextNode;
}
}
解题思路
newNode可以视为后面以及排序好后的链表的头节点,即样例1->2->3->4,newNode是节点2后面的链表的头节点,然后对head(1),nextNode(2),newNode(2后面的链表头节点),对这三个节点进行重新排序。
题解二、循环迭代法
class Solution {
public ListNode swapPairs(ListNode head) {
if(head == null || head.next == null){
return head;
}
ListNode dummyNode = new ListNode(0);
dummyNode.next = head;
ListNode curNode = dummyNode;
while(curNode.next != null && curNode.next.next != null){
ListNode tmpNode = curNode.next.next;
curNode.next.next = tmpNode.next;
tmpNode.next = curNode.next;
curNode.next = tmpNode;
curNode = curNode.next.next;
}
return dummyNode.next;
}
}
解题思路
由于可能会操作到头节点,即头节点也可能被交换顺序,这里使用虚拟头节点。首先头节点以及头节点的下一个指针进行特判,然后进行循环遍历,每次循环两个节点就对这两个节点进行交换处理,交换之后将指针向右移动两个位置。如果最后长度小于2,直接返回当前指针,此时循环也到此结束。
LeetCode.19 删除链表的倒数第K个节点
题目链接 删除链表的倒数第K个节点
题解一、快慢指针法
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummyNode = new ListNode(0);
dummyNode.next = head;
ListNode firstIndex = dummyNode;
ListNode secondIndex = dummyNode;
for(int i = 0;i<=n;i++){
firstIndex = firstIndex.next;
}
while(firstIndex != null){
firstIndex = firstIndex.next;
secondIndex = secondIndex.next;
}
if(secondIndex.next!=null){
secondIndex.next = secondIndex.next.next;
}
return dummyNode.next;
}
}
解题思路
快慢指针法,让快指针先走n + 1步,然后慢指针再开始走,快慢指针始终相差n + 1个节点,当快指针到链表底部,对慢指针的下一个节点进行删除操作,即slowIndex.next = slowIndex.next.next;
题解二、递归法
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
// 由于可能头节点也可能是被删除的对象,所以设置一个虚拟头节点
ListNode dummyNode = new ListNode(0);
dummyNode.next = head;
removeN(dummyNode,n);
return dummyNode.next;
}
public int removeN(ListNode head,int n){
// n 是计数器,代表倒数第几个节点
if(head == null){
// 链表到底了,返回0
return 0;
}
int curN = removeN(head.next,n);
if(curN == n){
// 进行删除操作
head.next = head.next.next;
}
return curN + 1;
}
}
递归实现,利用递归的回溯来计算这是倒数第几个节点,详情可以看代码的注解。
LeetCode 面试题02.07.链表相交
题目链接 面试题02.07.链表相交
题解
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode p1 = headA;
ListNode p2 = headB;
while(p1 != p2){
if(p1 != null){
p1 = p1.next;
}else {
p1 = headB;
}
if(p2 != null){
p2 = p2.next;
}else {
p2 = headA;
}
}
return p1;
}
}
解题思路
假设A链表和B链表不相交,那么两个下标p1,p2必定是分别从自己链表到对方链表各移动一遍,移动的长度是m + n,然后同时到达对方的尾节点,同时为null ,这个时候退出循环,返回p1 为 null符合题意,否则必定会在移动长度小于 m + n之内相遇。
LeetCode.142 环形链表Ⅱ
题目链接 环形链表Ⅱ
题解
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head == null || head.next == null){
return null;
}
ListNode fastIndex = head;
ListNode slowIndex = head;
while(fastIndex!= null && fastIndex.next != null){
fastIndex = fastIndex.next.next;
slowIndex = slowIndex.next;
if(slowIndex == fastIndex){
ListNode a = fastIndex;
ListNode b = head;
while(a != b){
a = a.next;
b = b.next;
}
return a;
}
}
return null;
}
}
解题思路
快慢指针,如果有环的话,可以视为快指针绕了一圈环,然后快指针追着慢指针,最终在环中相遇,找环的出口可以看一下卡尔的解题思路与证明
收获与总结
收获了链表快慢指针的写法,递归的写法,对这些写法掌握得更深,比如想获得链表的中间,可以快慢指针从头开始同时进行遍历,快指针移动两位,慢指针移动一位,当快指针到终点时,慢指针就刚好到中间位置等等用法,后续继续加油。