day4-1 24.两两交换链表中的节点
- 通过花费的时间:00:06:54(两个解法一块)
- 总结整理吃透这道题+博客总共花费的时间: 00:40:42
- 看到题目的第一想法: 指针交换
- 解题过程中遇到的问题: 看完视频后很顺序地写完了
- 此题收获:给自己一个信念,相信坚持的力量,拖了好多天的任务,后面加油赶回来,加油 ,加油
/**
* 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);
// 将虚拟头结点指向head,这样方便后面的做统一的删除操作
dumyhead.next = head;
ListNode cur = dumyhead;
// 临时结点
ListNode temp;// 保存两个节点的后面一个节点
ListNode firstNode; // 保存两个节点中的第一个结点
ListNode secondNode; // 保存两个节点中的第二个节点
while(cur.next != null && cur.next.next != null){ // 注意顺序避免空指针
temp = cur.next.next.next;
firstNode = cur.next;
secondNode = cur.next.next;
// 进行交换
cur.next = secondNode;
secondNode.next = firstNode;
firstNode.next = temp;
// 移动cur,进行下一轮
cur = firstNode;
}
return dumyhead.next;
}
}
day4-2 19.删除链表的倒数第N个结点
- 通过花费的时间:00:10:02(两个解法一块)
- 总结整理吃透这道题+博客总共花费的时间: 00:19:42
- 看到题目的第一想法: 虚拟头结点+快慢指针
- 解题过程中遇到的问题: 移动快指针的时候是移动n+1个位置,因为移除倒数第n个结点需要操作倒数第n+1个结点
- 此题收获:给自己一个信念,相信坚持的力量,拖了好多天的任务,后面加油赶回来,加油 ,加油
/**
* 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 dummyNode = new ListNode(-1);
dummyNode.next = head;
ListNode fastIndex = dummyNode;
ListNode slowIndex = dummyNode;
// 将快指针移动到倒数第 n+1 个节点位置
for(int i = 0; i <= n; i++){
fastIndex = fastIndex.next;
}
while(fastIndex != null){
fastIndex = fastIndex.next;
slowIndex = slowIndex.next;
}
// 删除节点
slowIndex.next = slowIndex.next.next;
// 返回头结点
return dummyNode.next;
}
}
day4-3 面试题02.07.链表相交
- 总结整理吃透这道题+博客总共花费的时间: 00:49:42
- 理解题目的重点:方法一(合并链表—>没懂原理,但是在草稿纸上模拟了一遍可以成),方法二(将两链表末尾对齐还有求的是两个链表交点节点的指针不是数值而是指针)
- 此题收获:给自己一个信念,相信坚持的力量,拖了n多天的任务,后面加油赶回来,加油 ,加油
/**
* 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 p1 = headA;
// ListNode p2 = headB;
// while(p1 != p2){
// // p1走一步,如果走到A链表末尾,转到B链表
// if(p1 == null){
// p1 = headB;
// }else{
// p1 = p1.next;
// }
// // p2走一步,如果走到B链表末尾,转到A链表
// if(p2 == null){
// p2 = headA;
// }else{
// p2 = p2.next;
// }
// }
// return p1;
// }
// 方法二:先移动长链表实现同步移动(求长度->让A为最长的一个链表->让curA和curB在同一起点->开始遍历)
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode curA = headA;
ListNode curB = headB;
int lenA = 0, lenB = 0;
// 求链表的长度
while(curA != null){
lenA++;
curA = curA.next;
}
while(curB != null){
lenB++;
curB = curB.next;
}
// cur指针从新放回各自的头结点
curA = headA;
curB = headB;
// 让A链表成为长度最长的链表,方便后面的操作
if(lenA < lenB){
// 交换长度
int temp = lenA;
lenA = lenB;
lenB = temp;
// 交换指针
ListNode tempNode = curA;
curA = curB;
curB = tempNode;
}
// 把curA和curB放在同一起点(末尾位置对齐)
int gapLen = lenA - lenB;
while(gapLen-- > 0){
curA = curA.next;
}
// 开始遍历
while(curA != null){
if(curA == curB){
return curA;
}
curA = curA.next;
curB = curB.next;
}
return null;
}
}
day4-4 142.环形链表||
- 总结整理吃透这道题+博客总共花费的时间: 00:45:42
- 理解题目的重点:判断是否有环、如果有环如何找到这个入口
- 此题收获:给自己一个信念,相信坚持的力量,拖了n多天的任务,后面加油赶回来,加油 ,加油
/**
* 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){
slow = slow.next;
fast = fast.next;
// 有环
if(fast == slow){
ListNode index1 = fast;
ListNode index2 = head;
// 两个指针,从相遇结点和头结点,各走一步,直到相遇,相遇点则为环的入口
while(index1 != index2){
index1 = index1.next;
index2 = index2.next;
}
return index1;
}
}
return null;
}
}
链表总结
- 双指针