无头单向链表链表的具体使用(下)


前言

继续分享有关无头单向非循环链表的面试题。

一、给定 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;       
    }
}
  • 11
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值