【Java--数据结构】链表经典OJ题详解(下)

前言

上一篇

欢迎关注个人主页:逸狼


创造不易,可以点点赞吗~

如有错误,欢迎指出~



目录

前言

链表分割 

链表的回文结构

 相交链表

环形链表


链表分割 

编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前 。OJ链接

1.定义一个节点cur遍历原链表,创建两个新链表B和A,用于放小于x和大于x的,最后将这两个链表连接构成一个新链表。这两个链表分别创建两个节点bs be和as ae,bs作为B链表的头节点,be用于添加节点,as和ae同理

2.比较每个节点的val与x的大小

若val<x,则该节点放在新链表B中

  • be.next=cur;
  • be=be.next;

其中要注意第一次插入be=bs=cur;

若val>x,则该节点放在新链表A中

  • ae.next=cur;
  • ae=ae.next;

其中要注意第一次插入ae=as=cur;

3.注意:

最后一个节点的next,没有null

要判断全部小于x,或全部大于等于x的情况(即遍历完原链表发现B链表为空或者A链表为空)

发现B链表为空 直接返回A链表 return as;

4.拼接

将B和A链表拼接,return bs;

public class Partition {
    public ListNode partition(ListNode pHead, int x) {
        if(pHead==null){
            return null;
        }
        // write code here
        ListNode bs=null;
        ListNode be=null;
        ListNode as=null;
        ListNode ae=null;

        ListNode cur=pHead;
        while(cur!=null){
            if(cur.val<x){
                if(bs==null){
                    be=bs=cur;//第一次插入
                }else{
                    be.next=cur;
                    be=be.next;
                }
                cur=cur.next;
            }else{
                if(as==null){
                    as=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;
    }
}

链表的回文结构

OJ链接

对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构,给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。

 1.找中间节点

快慢指针法(在上一篇有详细讲到),此时fast在走完了链表,slow在中间

2.反转中间节点以后的部分 (在上一篇也有详细讲到)

  • cur=slow.next;
  • while(cur!=null){
  • curN=cur.next;
  • cur.next=slow;
  • slow=cur;
  • cur=curN;}

反转链表后slow一定是尾节点

3.对比前后的val值

cur=slow.next

不能使用fast遍历(fast不一定是尾节点,当链表个数为偶数时,fast为空),所以用slow

注意:

偶数节点时,head和slow没有办法相遇

            //判断偶数情况
            if(head.next==slow){
                return true;
            }

 

public class PalindromeList {
    public boolean chkPalindrome(ListNode head) {
        // write code here
        //空链表也是回文的
        if(head==null){
            return true;
        }
        //1.找中间节点
        ListNode fast=head;
        ListNode slow=head;
        while(fast!=null&&fast.next!=null){
            fast=fast.next.next;
            slow=slow.next;
        }
        //2.反转中间节点之后的链表
        ListNode cur=slow.next;
        while(cur!=null){
        ListNode curN=cur.next;
        cur.next=slow;
        slow=cur;
        cur=curN;
        }
        //3.对比head和slow的val值
        while(head!=slow){
            if(head.val!=slow.val){
                return false;
            }
            //判断偶数情况
            if(head.next==slow){
                return true;
            }
                head=head.next;
                slow=slow.next;
        }
            return true;
    }
}

 相交链表

输入两个链表,找出它们的第一个公共结点。OJ链接

 

链表相交后,形成Y结构链表,如图题目要求是找出值为60的节点

1.分别求2个链表的长度,求出差值x

2.让长的先走x步

3.然后一起走,直到相遇

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        //假设p1是长链表
        ListNode p1=headA;
        ListNode p2=headB;
        int lenA=0;
        int lenB=0;
        while(p1!=null){
            p1=p1.next;
            lenA++;
        }
        while(p2!=null){
            p2=p2.next;
            lenB++;
        }
        //要重新让p1和p2指向头节点
        p1=headA;
        p2=headB;
        int len =lenA-lenB;
        if(len<0){
            p1=headB;
            p2=headA;
            len=lenB-lenA;
        }
        //走完上面代码后p1一定是最长的链表
        //让长链表先走len步
        for(int i=0;i<len;i++){
            p1=p1.next;
        }
        //一起走
        while(p1!=p2){
            p1=p1.next;
            p2=p2.next;
        }
        if(p1==null){
            //如果两个引用都为空,证明不相交,返回null  不写也不会报错
            return null;
        }
        return p1;
    }
}

环形链表

给定一个链表,判断链表中是否有环。 OJ链接

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false 。

fast走一步,slow走两步,若相遇,则有环

public class Solution {
    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;
    }
}

  • 55
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 26
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值