24两两算法交换链表中节点
题目链接
https://leetcode.cn/problems/swap-nodes-in-pairs/
解题思路 在代码中 解释
class Solution {
public ListNode swapPairs(ListNode head) {
//先定义一个虚拟头节点 方便指针的移动还有遍历
ListNode dumyhead = new ListNode(-1);
//让这个虚拟头节点指向 头节点
dumyhead.next = head;
// 定义一个临时指针 指向虚拟头节点 这样做的目的是 便于下一步的移动
ListNode cur = dumyhead;
// cur.next 不等于空要写在前面 才不会出现空指针异常
//终止条件这样的原因是 因为两两相近的元素交换 所以cur指针要指向 两两交换元素的第一个元素 当cur 下一个节点为空的时候 说明已经结束了 后面没有元素了
while(cur.next != null&& cur.next.next!= null){
ListNode temp = cur.next; //再定义一个临时指针 目的是接收 元素的值
//要实现交换 要和第三个元素 第一个元素 关联所以要保存 他们的值
ListNode temp1 = cur.next.next.next;//同理
cur.next = cur.next.next; // 这句代码的意思是 拿cur是虚拟头节点举例,cur.next 也就是头节点 不再是原来的头节点 而是cur.next.next 也就是需要交换成第一个的元素
cur.next.next =temp; //然后再让交换的成第二个的元素变成第二个
temp.next =temp1;//让已经变成第二个元素的元素指向下一个第三个节点
cur = cur.next.next;//让cur指针移动 移动到第三个元素 开始第三个和第四个元素的交换
}
return dumyhead.next; //返回交换完后的头节点
}
}
19删除链表的倒数第n个节点
题目链接
https://leetcode.cn/problems/remove-nth-node-from-end-of-list/
解题思路分析
使用快慢指针! 问题的难点在于怎么找到要删除倒数第n个元素
我们定义快慢指针 同时指向虚拟头节点 快指针先走 先走 n 步 然后快慢指针同时走 直到 快指针指向 null 这样做的原理是 快慢指针始终相隔 n 个节点 就可以找到倒数的第n个节点
public ListNode removeNthFromEnd(ListNode head, int n){
ListNode dummyNode = new ListNode(0);
dummyNode.next = head;
ListNode fastIndex = dummyNode;
ListNode slowIndex = dummyNode;
//只要快慢指针相差 n 个结点即可
for (int i = 0; i < n ; i++){
fastIndex = fastIndex.next;
}
//这里的 .next不等于空的原因是 因为需要慢指针指向 要删除元素的前一个节点! 所以 这里的快指针指向的是倒数第二个元素 这样慢指针就指向了 n+1 元素 这样才能删除第n个元素!
while (fastIndex.next != null){
fastIndex = fastIndex.next;
slowIndex = slowIndex.next;
}
//此时 slowIndex 的位置就是待删除元素的前一个位置。
//具体情况可自己画一个链表长度为 3 的图来模拟代码来理解
slowIndex.next = slowIndex.next.next;
return dummyNode.next;
}
0207 链表相交
题目链接
https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode curA = headA;
ListNode curB = headB;
int lenA = 0, lenB = 0;
while (curA != null) { // 求链表A的长度
lenA++;
curA = curA.next;
}
while (curB != null) { // 求链表B的长度
lenB++;
curB = curB.next;
}
curA = headA; //这里很重要· 我吃了一个大亏 需要重新指定 cur 到头节点 因为已经重新遍历了!
curB = headB;
//始终让cura为最长 这里的意思是 谁长谁就成为cura 和lena 这一步很重要
// 让curA为最长链表的头,lenA为其长度
if (lenB > lenA) {
//1. swap (lenA, lenB);
int tmpLen = lenA;
lenA = lenB;
lenB = tmpLen;
//2. swap (curA, curB);
ListNode tmpNode = curA;
curA = curB;
curB = tmpNode;
}
// 求长度差
int gap = lenA - lenB;
// 让curA和curB在同一起点上(末尾位置对齐)
while (gap> 0) {
curA = curA.next;
gap--;
}
// 遍历curA 和 curB,遇到相同则直接返回
while (curA != null) {
if (curA == curB) {
return curA;
}
curA = curA.next; //向下走 然后是不是相等
curB = curB.next;
}
return null; //没有相等的
}
142环形链表
题目链接
https://leetcode.cn/problems/linked-list-cycle-ii/
因为手打思路分析比较复杂
这里我录了一个视频https://www.bilibili.com/video/BV1qP411m74N/
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {// 有环
ListNode index1 = fast;
ListNode index2 = head;
// 两个指针,从头结点和相遇结点,各走一步,直到相遇,相遇点即为环入口
while (index1 != index2) {
index1 = index1.next;
index2 = index2.next;
}
return index1;
}
}
return null;
}
}```