代码随想录训练营第四天
今日任务
● 24. 两两交换链表中的节点
● 19.删除链表的倒数第N个节点
● 面试题 02.07. 链表相交
● 142.环形链表II
● 总结
1.LeetCode 24. 两两交换链表中的节点
题目链接:24. 两两交换链表中的节点
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode swapPairs(ListNode head) {
//交换两两相邻的节点,并返回交换后的链表头节点
//交换节点
//我的思路是一个指针用来遍历(每次跳2),一个指针用来交换
//看完代码随想录之后
//直到了第一个亮亮交换的指针就像是插入新节点那样去操作,注意顺序
//一定要直到插入位置的前一个节点
//所以我们就创建虚拟头节点,利于操作
ListNode dumyNode=new ListNode();
dumyNode.next=head;
//实例1:1的地方就是dumyNode.next
//2的地方就是dumyNode.next.next
//因为最终要返回头节点,所以我们用一个遍历的指针
ListNode curNode=dumyNode;
//临时指针,保存要交换的
ListNode temp1;
//还需要保存节点3的只知道你
ListNode temp3;
while(curNode.next!=null&&curNode.next.next!=null){
temp1=curNode.next;
temp3=curNode.next.next.next;
//交换第一次节点
curNode.next=curNode.next.next;
curNode.next.next=temp1;
//让节点1指向节点3(忘记了)
temp1.next=temp3;
//跳动遍历位置
curNode=curNode.next.next;
}
return dumyNode.next;
}
}
2.LeetCode 19.删除链表的倒数第N个节点
题目链接:19. 删除链表的倒数第 N 个结点
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
// //之前学过对链表的操作,删除过指定位置的节点,所以这道题不在话下
// //要删除,就要找到被删除位置的前一个节点
// //创建虚拟头节点,并让它指向head
// ListNode dumyNode=new ListNode();
// dumyNode.next=head;
// //虚拟头节点的下一个节点下标才是0
// //因为要返回链表的头节点
// //创建遍历的指针
// ListNode curNode=dumyNode;
// while(n>0){
// curNode=curNode.next;
// //极端判断,当腰找下标为0这个被删除节点的前一个节点,那么这个循环不会进入
// //那么curNode就是dumyNode//在前一个,证明正确
// }
// //现在指针已经指向了要被删除的前一个节点了
// //开始删除
// curNode.next=curNode.next.next;
// return dumyNode.next;
//也不是,我们我们可以选择先将链表反转,删除后,我们再一次反转
//看完代码随想录之后思路:
//定义两个指针
//快指针先走n步,然后让快慢指针同时移动,直到快指针指向为null,那么就找到了要被删除的位置
//那想找到被删除的前一个节点,应该是让快指针走n+1步,然后让慢指针和快指针同时移动
//创建虚拟头节点,并让它指向head
ListNode dumyNode=new ListNode();
dumyNode.next=head;
//定义快慢指针
ListNode fast=dumyNode;
ListNode slow=dumyNode;
// if(fast.next==null){
// return head;
// }
//先让快指针走n+1步
while(n>-1&&fast!=null){
//需要加上fast!=null,不是fast.next!=null
fast=fast.next;
//忘记减减了
n--;
}
//再让快慢指针同时走
while(fast!=null){
slow=slow.next;
fast=fast.next;
}
//此时慢指针已经走到了被删除的前一个位置
//进行删除
slow.next=slow.next.next;
return dumyNode.next;
}
}
3.LeetCode 160.相交链表
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
//import java.lang.Math;
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
//就是求两个链表交点节点的指针。
//交点不是数值相等,而是指针相等
//思路:看实例,相交后的两个链表后面都是相同的,相交前是不一样的
//我们求出两个链表的长度,并求出两个链表长度的差值,然后让curA移动到,和curB 末尾对齐的位置(这样确保相交后面一样,用这样来推处相交的节点)
//此时我们就可以比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到交点。
//否则循环退出返回空指针
//一个链表一个指针
ListNode curNodeA=headA;
ListNode curNodeB=headB;
//求出两个链表的长度
int lenA=0;
int lenB=0;
while(curNodeA!=null){
curNodeA=curNodeA.next;
lenA++;
}
while(curNodeB!=null){
curNodeB=curNodeB.next;
lenB++;
}
curNodeA = headA;
curNodeB = headB;
// 让curA为最长链表的头,lenA为其长度
if (lenB > lenA) {
//1. swap (lenA, lenB);
int tmpLen = lenA;
lenA = lenB;
lenB = tmpLen;
//2. swap (curA, curB);
ListNode tmpNode = curNodeA;
curNodeA = curNodeB;
curNodeB = tmpNode;
}
//求长度差
int gap=lenA-lenB;
//让curA移动到,和curB 末尾对齐的位置(也就是在同一起点上,末尾位置对齐)
while(gap-->0){
curNodeA=curNodeA.next;
}
//遍历curA和curB,遇到相同就返回,没有就返回null
while(curNodeA!=null){
if(curNodeA==curNodeB){
return curNodeA;
}
//没有就遍历下一个
curNodeA=curNodeA.next;
curNodeB=curNodeB.next;
}
//遍历完了没找到
return null;
//差值,得是绝对值,平方之后再开方 Math.
//int changelen=(int)(Math.sqrt(Math.pow(lenB-lenA),2));
}
}
4.LeetCode 142.环形链表II
题目链接:142. 环形链表 II
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
//思路:我们定义两个指针
//一个快指针每次走两个节点
//一个慢指针每次走一个节点
//当快指针和慢指针相遇的时候,证明有环
//此时记录快指针或者慢指针的位置,再记录head头部的位置,让这两个位置去往下移动,直到相等,那么就找到了入环的位置
//创建快慢指针
ListNode fast=head;
ListNode slow=head;
while(fast!=null&&fast.next!=null){
fast=fast.next.next;
slow=slow.next;
if(fast==slow){//证明有环
ListNode index1=fast;//慢指针的也行
ListNode index2=head;
while(index1!=index2){//找入口
index1=index1.next;
index2=index2.next;
}
//那么找到了返回的是index1或者index2
return index1;
}
}
//空指针,返回null
return null;
}
}