果然是昨有点头昏,今天再看链表感觉简单了不少,今天表现还不错题目基本都是先自己想思路再看文章,文章有不少思路都和我想得一样,这应该就是我在进步的证明吧。
● 24. 两两交换链表中的节点
题目链接/文章讲解/视频讲解: 代码随想录
这题目看完我就想到了初学代码的时候的题目交换a,b的值,这种题目需要一个第三方来帮助不能直接交换,这道题目也差不多,需要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) {
ListNode cur=new ListNode(-1,head);//创建虚拟表头
ListNode q=cur;//交换链表初始位置,即从虚拟头部开始
ListNode p;
while(q.next!=null){//原理与交换a,b两个的值相似。
p=head.next;//获取交换的节点
if(p==null)break;//判断是否可以进行交换,不行就直接推出
q.next=p;
head.next=p.next;
p.next=head;//上面三步就是进行交换位置
q=head;
head=head.next;//前往下一个交换位置
}
return cur.next;//返回交换后的链表
}
}
● 19.删除链表的倒数第N个节点
题目链接/文章讲解/视频讲解:代码随想录
这道题看完我就想到了可以用我最近很喜欢的双指针,让两个指针中间相差n(需要删除倒数第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 cur=new ListNode(-1,head);//创建虚拟头部(虚拟头部真的可以简化很多操作);
ListNode fast=head;//创建快指针;
ListNode show=cur;//创建慢指针;
for(int i=0;i<n;i++)//让快指针与慢指针距离相差n;
fast=fast.next;
while(fast!=null){//让快指针到达底部;
fast=fast.next;
show=show.next;
}
show.next=show.next.next;//删除倒数第n个节点;
return cur.next;//返回信链表;
}
}
● 面试题 02.07. 链表相交
题目链接/文章讲解:代码随想录
这道题的思路也比较简单,根据题目可以看出如果两个链表相交,那他们相交的地方一定都是尾部,既然在尾部从尾部开始找是不说很好?我刚开始也这么想但是这两个链表都是单向链表,所以这个方法行不通,我们只能从前往后找,我们可以发想想同部分是一定小于或等于短链表的切一定在两个链表尾部,所以长一点的链表比短链表长的前端一定不是相交的部分所以直接让长链表开始位置和锻链表一样长就很好找了。
具体代码:
/**
* 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 p=headA;
ListNode q=headB;
int lenA=0,lenB=0;
//获取两条链表长度;
while(p!=null){
lenA++;
p=p.next;
}
while(q!=null){
lenB++;
q=q.next;
}
//判断那条链表更长将长链表移动到和短链表相同长度位置 ;
if(lenA>lenB)
for(;lenA!=lenB;lenA--)
headA=headA.next;
else
for(;lenA!=lenB;lenB--)
headB=headB.next;
//找到相同位置或直到到末尾退出循环;
while(headA!=headB&&headA!=null){
headA=headA.next;
headB=headB.next;
}
return headA; //返回相同链表初始节点或null;
}
}
● 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) {
ListNode fast=head;
ListNode show=head;
if(fast==null||fast.next==null)return null;
do{
fast=fast.next.next;
show=show.next;
}while(fast!=show&&fast!=null&&fast.next!=null);
if(fast!=show)
return null;
ListNode cur=head;
while(cur!=show){
cur=cur.next;
show=show.next;
}
return cur;
}
}
记录
通过昨天对自己的反思我开始在代码之间加上了注释方便看懂代码,也会简单的叙述做题的思路了,虽然非常粗糙但是还是有进步,一点点慢慢来吧,这几天也越来越得心应手了,今天有发现了虚拟头部真的真的超级好用!!!链表头部的处理真的是一个很容易忽略的地方虚拟头部真的很适合新手,答复优化了对头部的处理,虽然才开始第4天当我确实是感受到了自己的变化。
day4打卡!!!!