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) {
if(head==null||head.next==null)
{
return head;
}
ListNode vhead=new ListNode(0);//创建虚拟头结点
vhead.next=head;
ListNode r=vhead;
while(r.next!=null&&r.next.next!=null)
{
ListNode tmp=r.next;//将后面的节点保存
ListNode tmps=r.next.next.next;//将前面的节点保存
r.next=r.next.next;
r.next.next=tmp;
tmp.next=tmps;
r=r.next.next;//虚拟头结点要在交换的两个节点的前面一个
}
return vhead.next;
}
}
19.删除链表的倒数第N个节点
题目链接:删除链表的倒数第N个节点
这道题考的是快慢指针在链表上的运用,快指针与慢指针的距离始终为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) {
if(head==null||head.next==null)
{
return null;
}
ListNode vhead=new ListNode(0);//创建虚拟头结点
vhead.next=head;
ListNode p=vhead;
ListNode q=vhead;
for(int i=0;i<n;i++)//快指针移动n步
{
q=q.next;
}
while(q.next!=null)
{
p=p.next;
q=q.next;
}
p.next=p.next.next;
return vhead.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) {
if(headA==null||headB==null)
{
return null;
}
if(headA.next==null&&headB.next==null&&headA==headB)//只有一个节点,且节点相同
{
return headA;
}
ListNode p=headA;
ListNode q=headB;
int count1=0;
int count2=0;
//求两个链表的长度
while(p.next!=null)
{
p=p.next;
count1++;
}
while(q.next!=null)
{
q=q.next;
count2++;
}
ListNode d1=headA;
ListNode d2=headB;
//是两个链表在同一起点开始遍历
if(count1>count2)
{
count1=count1-count2;
for(int i=1;i<=count1;i++)
{
d1=d1.next;
}
}
else if(count1<count2)
{
count2=count2-count1;
for(int j=1;j<=count2;j++)
{
d2=d2.next;
}
}
//判断链表是否存在相同节点
while(d1!=null&&d2!=null)//使其能遍历到链表的最后一个节点,
{
if(d1==d2)
{
return d1;
}
d1=d1.next;
d2=d2.next;
}
return null;
}
}
142.环形链表II
题目链接:环形链表II
这道题考的是环形链表,主要看的是两个点:1.判断链表是否为环形链表;2.找出进入环形链表的首节点。这道题可以用快慢指针来判断是否存在环形链表,如果环形链表存在,快慢指针会在环形链表的某处重合
由上图可知快指针在环形链表内走的长度为:n(y+z)
慢指针走到相遇点的长度为x+y
故:x+y=n(y+z) 可得: x=(n-1)(y+z)+z
所以快指针在环形链表内走了(n-1)圈后到快慢指针相遇点,再走长度z可与从开始走长度为x的指针相遇
/**
* 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) {
if(head==null||head.next==null)
{
return null;
}
ListNode p=head;//slow
ListNode q=head; //fast
ListNode cur=head;
//判断是否为环形链表
while(q!=null&&q.next!=null)
{
p=p.next;
q=q.next.next;
if(p==q)
{
break;
}
}
if(q==null||q.next==null)
{
return null;
}
//判断是否相遇,相遇的点就为换开始的第1个节点
ListNode idx=q;
while(idx!=cur)
{
cur=cur.next;
idx=idx.next;
}
return cur;
}
}
总结:对于今天的题目,主要是考验我对于链表的掌握,虽然被空指针搞爆了心态,今后对于链表还是要理清是否会产生空指针。