力扣题目 #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) {
// 虚拟的头节点
ListNode dumyhead = new ListNode(-1);
dumyhead.next = head;
// 临时储存值
ListNode temp;
ListNode temp1;
// 临时指针
ListNode currentNode = dumyhead;
// 这里注意空指针异常
//先写current.next.next会报空指针异常
while (currentNode.next != null && currentNode.next.next != null) {
temp = currentNode.next;
temp1 = currentNode.next.next.next;
currentNode.next = currentNode.next.next;
currentNode.next.next = temp;
currentNode.next.next.next = temp1;
currentNode = currentNode.next.next;
}
return dumyhead.next;
}
}
力扣题目 #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) {
//虚拟的头节点
ListNode dumyhead = new ListNode(0); //记得赋值
dumyhead.next = head;
//快慢指针,快指针遍历,慢指针为删除节点的前驱
ListNode fast = dumyhead;
ListNode slow = dumyhead;
//记录的快慢指针的间隔数
int number = 0;
while(fast != null){
//当快慢指针之间相差n个节点就是快慢指针的相对位置
if(number == n+1 )
slow = slow.next;
else
number++;
fast = fast.next;
}
slow.next = slow.next.next;
return dumyhead.next;
}
}
力扣题目 #面试题0207 链表相交
注意:这里警惕的是交点是指针相同而不是单纯数值相同
/**
* 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) {
ListNode curA = headA;
ListNode curB = headB;
int lenA = 0;
int lenB = 0;
//求A,B链表的长度
while(curA != null){
lenA ++;
curA = curA.next;
}
while(curB != null){
lenB ++;
curB = curB.next;
}
curA = headA;
curB = headB;
//这里是为让链表A作为最长的链表,那么下面的gap就不用做判断。
//也可以选择用if-else来做判断也是可以的,但是下面的让A,B链表对齐的步骤也要对齐
if(lenB > lenA){
//交换长度
int tempLen = lenB;
lenB = lenA;
lenA = tempLen;
//交换链表
ListNode tempNode = curA;
curA = curB;
curB = tempNode;
}
int gap = lenA - lenB;
//让链表A,B对齐
while(gap-- > 0){
curA = curA.next;
}
while( curA != null){
if(curA == curB)
return curA;
curA = curA.next;
curB = curB.next;
}
return null;
}
}
力扣题目 #142 环形链表Ⅱ
注意:
1、快指针走2个节点,慢指针走1个节点,那么快指针相对于慢指针就是一个一个节点的在靠近慢指针。
2、有数学证明,头节点到入口处的距离,与相遇处到入口的距离相等
/**
* 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) {
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;
}
return index1;
}
}
return null;
}
}
链表的总结
链表的理论基础
1、链表的种类:单链表、双链表、环形链表
2、链表里的元素是通过指针来连接的
3、Java中LinkedList集合就是基于双链表形成的
链表的基本操作
1、链表的操作最好是设计一个虚拟的头节点来操作 ,不然就要另外考虑头节点是否空指针的异常报错的情况
2、设计链表的操作,熟练之后就可以不用担心链表的增删改查的问题
链表的经典题目
经典题目真的很经典 (-_-)