题目1:给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
示例:
输入:head = [1,2,3,4] 输出:[2,1,4,3]
错误:秒过!!!没错嘿嘿~
修正:
核心:
虚拟头节点+搞清楚逻辑关系不要把连接关系覆盖了.
找到循环规律+找到循环停止条件
答案:
/**
* 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) {
//1.利用虚拟头节点+临时存储节点
ListNode dummy=new ListNode(){};
dummy.next=head;
ListNode cur =dummy;
while(cur.next!=null&&cur.next.next!=null){//考虑循环停止条件
ListNode temp1=cur.next;
ListNode temp2 = cur.next.next;
cur.next=temp2; //cur指向2
temp1.next=temp2.next;//1指向3
temp2.next=temp1;//2指向1
cur=temp1;//cur移动2位
}
return dummy.next;
}
}
题目2:给你一个链表,删除链表的倒数第 n
个结点,并且返回链表的头结点。
输入:head = [1,2,3,4,5], n = 2 输出:[1,2,3,5]
错误:
修正:
核心:第一考虑极端情况 删除的是头节点和尾节-虚拟头节点,//采用办法为求size+遍历
方法二 快慢指针-办法是两个指针相差n个然后一起遍历直到fast到最后一个,此时slow指针就是要处理的值前一个
答案:
/**
* 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) {
//1.考虑极端情况 删除的是头节点和尾节点,
//采用办法为求size+遍历
ListNode dummy= new ListNode(){};
dummy.next=head;
ListNode cur=dummy;
int size=0;
while(cur.next!=null){
cur=cur.next;
size++;
}
cur=dummy;
for(int i=0; i<size-n;i++){
cur=cur.next;
}
ListNode temp=cur.next.next;
cur.next=temp;
return dummy.next;
}
//方法二 快慢指针-办法是两个指针相差n个然后一起遍历直到fast到最后一个,此时slow指针就是要处理的值前一个
}
题目3:
给你两个单链表的头节点 headA
和 headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null
。
图示两个链表在节点 c1
开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
输入headA headB 输出c1
错误:
修正:
核心:
/*1.找规律 快慢指针,fast比slow快size差步
2.找出停止条件 快慢指针指向的是同一个
3.找出极端情况
--不相交 从来没有相等输出null
--完全相交 正常输出
--全部为空值*/
答案:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
/*1.找规律 快慢指针,fast比slow快size差步
2.找出停止条件 快慢指针指向的是同一个
3.找出极端情况
--不相交 从来没有相等输出null
--完全相交 正常输出 */
if(headA==null||headB==null){
return null;
}//考虑空值极端情况
int sizeA=0;
ListNode curA=headA;
while(curA.next!=null){
curA=curA.next;
sizeA++;
}
int sizeB=0;
ListNode curB=headB;
while(curB.next!=null){
curB=curB.next;
sizeB++;
}
//!让curA成为最长链表的头
curA=sizeA>=sizeB?headA:headB;
curB=sizeA<sizeB?headA:headB;
int sizeCha=(sizeA-sizeB)>=0?(sizeA-sizeB):(sizeB-sizeA);
//长链表先走sizaCha
for(int i=0; i<sizeCha;i++){
curA=curA.next;
}
while(curA!=curB){
if(curA.next==null||curB.next==null){
return null;
}
curA=curA.next;
curB=curB.next;
}
return curA;
}
}
题目4:
给定一个链表的头节点 head
,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos
是 -1
,则在该链表中没有环。注意:pos
不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
输入:head = [3,2,0,-4], pos = 1 输出:返回索引为 1 的链表节点 解释:链表中有一个环,其尾部连接到第二个节点。
错误:
修正:
核心: 一个指针从头节点走,一个从相遇位置走,每次一步,第一个相遇的就是入口节点(因为刚好差环这么多步)
答案:
public class Solution {
public ListNode detectCycle(ListNode head) {
//1.找规律--快慢指针
//快慢指针步数 差环的长度/环长度的倍数 时候一定会指向同一个节点
//环的长度从1-2-3-~
//每次差1或者2或者3或者````->快指针走2步,慢指针走1步
//2.找停止条件
//指向同一个节点,停止输出
//3.找极端情况
//空值
//没有环
if(head==null||head.next==null){
return null;
}
ListNode curFast=head;
ListNode curSlow=head;
curFast=curFast.next.next;
curSlow=curSlow.next;
while(curFast!=curSlow){
if(curFast==null||curFast.next==null||curSlow==null){
return null;
}
curFast=curFast.next.next;
curSlow=curSlow.next;
}
//一个指针从头节点走,一个从相遇位置走,每次一步,第一个相遇的就是入口节点(因为刚好差环这么多步)
curSlow=head;
while(curFast!=curSlow){
curSlow=curSlow.next;
curFast=curFast.next;
}
return curSlow;
}
}