文章目录
前言
继续分享有关无头单向非循环链表的面试题。
一、给定 x, 把一个链表整理成前半部分小于 x, 后半部分大于等于 x 的形式
牛客链接:link
1.实现思路
1.定义5个变量
ListNode cur=head用cur遍历整个链表
ListNode bs=null bs始终指向小于x值链表的头部
ListNode be=null be始终指向小于x值链表的尾部
ListNode as=null bs始终指向大于x值链表的头部
ListNode ae=null be始终指向大于x值链表的尾部
2.进行比较排序
3.合并链表
这里有两个细节:一个是bs为空直接返回as就行了
另一个是as的尾部ae不为空,我们要手动置为空,否则就会找不到链表的尾而出错
2.具体实现
public class Partition {
public ListNode partition(ListNode head, int x) {
// write code here
ListNode cur=head;
ListNode bs=null;
ListNode be=null;
ListNode as=null;
ListNode ae=null;
while(cur!=null){
if(cur.val<x){
if(bs==null){
bs=cur;
be=cur;
}else{
be.next=cur;
be=be.next;
}
}else{
if(as==null){
as=cur;
ae=cur;
}else{
ae.next=cur;
ae=ae.next;
}
}
cur=cur.next;
}
if(bs==null){
return as;
}
be.next=as;
if(as!=null){
ae.next=null;
}
return bs;
}
}
二、判定链表是否是回文
牛客链接:link
2.1实现思路
1.定义两个指针fast和slow,fast走两步,slow走一步,找到链表的中间位置即slow位置
2.翻转slow后面的的链表
3.head从头往后走,slow从后往前走进行判断
2.2具体实现
public class PalindromeList {
public boolean chkPalindrome(ListNode head) {
ListNode fast=head;
ListNode slow=head;
if(head==null){
return true;
}
while(fast!=null&&fast.next!=null){
fast=fast.next.next;
slow=slow.next;
}
ListNode cur=slow.next;
while(cur!=null){
ListNode curNext=cur.next;
cur.next=slow;
slow=cur;
cur=curNext;
}
while(head!=slow){
if(head.val!=slow.val){
return false;
}//偶数链表情况的判断
if(head.next==slow){
return true;
}
head=head.next;
slow=slow.next;
}
return true;
}
}
三、判定链表相交
力扣链接: link
3.1实现思路
1.分别求headA和headB的长度lenA,lenB,求他们之间的差值len
2.定义两个指针变量pl和ps,
pl 指向长链表的头部
ps 指向短链表的头部
让pl先走len步
3.pl和ps一起走,相遇点即是相交点
3.2具体实现
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode pl=headA;
ListNode ps=headB;
int lenA=0;
int lenB=0;
while(pl!=null){
lenA++;
pl=pl.next;
}
while(ps!=null){
lenB++;
ps=ps.next;
}
pl=headA;
ps=headB;
int len=lenA-lenB;
if(len<0){
pl=headB;
ps=headA;
len=lenB-lenA;
}
while(len!=0){
pl=pl.next;
len--;
}
while(pl!=null&&ps!=null&&pl!=ps){
pl=pl.next;
ps=ps.next;
}
if(pl==ps&&pl==null){
return null;
}
return pl;
}
四、判断链表是否有环
力扣链接:link
4.1实现思路
1.快指针fast走两步,慢指针slow走一步
2.如果链表带环,两个最终肯定会在环内相遇
2.如果链表不带环,快指针肯定会走到链表的末尾
4.2具体实现
public boolean hasCycle(ListNode head) {
ListNode fast=head;
ListNode slow=head;
while(fast!=null&&fast.next!=null){
fast=fast.next.next;
slow=slow.next;
if(fast==slow){
return true;
}
}
return false;
}
五、判断环的入口点
力扣链接: link
4.1实现思路
1.先检测链表是否带环,如果带环则slow和fast当前所在的位置即是相遇点
2. 求交点: 让一个引用slow从链表起始位置开始,一个引用fast从相遇点位置开始,两个引用每次都走一步,最终相遇时的节点即为交点
4.2具体实现
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(slow==fast){
break;
}
}//判断链表是否有环
if(fast==null||fast.next==null){
return null;
}
slow=head;
while(slow!=fast){
fast=fast.next;
slow=slow.next;
}
return slow;
}
}