Java-链表2

本文深入探讨了链表数据结构的多种高级操作,包括寻找相交链表的起始节点、判断链表是否存在环、定位链表入环的第一个节点、链表分割以及链表数值求和等核心算法。通过具体的代码实现,读者可以全面掌握链表处理的技巧。

一、相交链表的起始节点
在这里插入图片描述

public class Solution {
   //找两个链表的公共节点
    public  ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if (headA == null || headB == null) {
            return null;
        }
        int lenA = 0;
        int lenB = 0;
        ListNode PL = headA;//长
        ListNode PS = headB;//短
        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;
        }
        //PL指向长的,PS指向短的
        //PL走了差值步
        while (len > 0) {
            PL = PL.next;
            len--;
        }
        while (PL != null && PS != null && PL != PS) {
            PL = PL.next;
            PS = PS.next;
        }
        if (PL != null && PS != null && PL == PS) {
            return PS;
        }
        return null;
    }
}

二、判断链表是否有环
在这里插入图片描述

    //这里需要注意的是,上面的whlie循环跳出来有三种情况
    //1、fast指向null
    //2、slow指向null
    //3、相遇了
    //所以再这里要处理一下这样的情况
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){
             break;
            }
        }
        if(fast==null||fast.next==null){
            return false;
        }
        return true;
    }
}

三、链表入环的第一个节点
在这里插入图片描述

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(fast==slow){
                break;
            }
        }
        if(fast==null||fast.next==null){
            return null;
        }
        slow=head;
        while(fast!=slow){
            fast=fast.next;
            slow=slow.next;
        }
        return fast;
    }
}

四、链表分割:给定一个基准值x,把小于x的节点排在等于或者大于x的节点之前
在这里插入图片描述

public class Partition {
    public ListNode partition(ListNode pHead, int x) {
        // write code here
        ListNode cur=pHead;
        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=bs;
                }else{
                   ///已经有
                    be.next=cur;
                    be=be.next;
                }
            }else{
                if(as==null){
                    as=cur;
                    ae=as;
                }else{
                    ae.next=cur;
                    ae=ae.next;
                }
            }
            cur=cur.next;
        }
        if(bs==null){
            return as;
        }
        //bs!=null
        be.next=as;
        if(as!=null){
            ae.next=null;
        }
        return bs;
    }
}

五、有两个用链表表示的整数,每个结点包含一个数位。这些数位是反向存放的,也就是个位排在链表的首部。编写函数对这两个整数求和,并用链表形式返回结果。
给定两个链表ListNode* A,ListNode* B,请返回A+B的结果(ListNode*)
在这里插入图片描述

public class TestLinkedList {
        public ListNode plusAB(ListNode A, ListNode B) {

            //传入两个链表
            //先把链表转成整数进行计算
            Integer a = listNodeInvertIntValue(A);
            Integer b = listNodeInvertIntValue(B);

            //然后相加
            Integer ret = a + b;
            //最后再把结果反序插入到链表中
            return intValueRevertListNode(ret);


        }

        private ListNode intValueRevertListNode(Integer value) {
            char[] charArray = String.valueOf(value).toCharArray();
            ListNode node = new ListNode(Integer.parseInt(String.valueOf(charArray[charArray.length - 1])));
            ListNode cur = node;
          //整数反转存储到链表中
            for (int i = charArray.length - 2; i >= 0; i--) {
                ListNode newNode = new ListNode(Integer.parseInt(String.valueOf(charArray[i])));
                cur.next = newNode;
                cur = newNode;
            }
            return node;
        }


        private Integer listNodeInvertIntValue(ListNode P) {
            StringBuilder stringBuilder = new StringBuilder();
            ListNode cur = P;
            while (cur != null) {
                stringBuilder.append(cur.val);
                cur = cur.next;

            }
            return Integer.parseInt(stringBuilder.reverse().toString());
        }
    }
class Node {
    int val;
    Node next;

    public Node(int val) {
        this.val = val;
    }

}
### Java 数据结构 链表 实现教程 #### 单链表的定义与基本实现 在 Java 中,单链表可以通过自定义类来实现。以下是基于引用的内容构建的一个完整的单链表实现方案。 ```java public class LinkedList { // 定义内部节点类 public static class Node { public int data; // 假设节点存储的数据类型为 int public Node next; public Node(int data) { this.data = data; this.next = null; } } private Node head = null; // 初始化头节点为空 // 添加节点的方法 public void addNode(int data) { Node newNode = new Node(data); if (head == null) { // 如果链表为空,则新节点作为头节点 head = newNode; } else { Node temp = head; while (temp.next != null) { // 找到最后一个节点 temp = temp.next; } temp.next = newNode; // 将新节点连接到最后一个节点之后 } } // 获取链表长度(不统计头节点) public int getLength() { if (head == null) { // 空链表返回 0 return 0; } int length = 0; Node current = head; while (current != null) { // 遍历整个链表 length++; current = current.next; } return length; } // 输出链表内容 public void displayList() { Node node = head; while (node != null) { System.out.print(node.data + " -> "); node = node.next; } System.out.println("null"); } } ``` 上述代码实现了单链表的基本功能,包括添加节点、计算链表长度以及打印链表内容的功能[^1]。 --- #### 链表的特点及其存储方式 链表是一种物理存储单元上非连续、非顺序的存储结构。它的特点是数据元素之间的逻辑顺序通过链表中的指针链接次序实现。具体来说,链表由一系列结点组成,每个结点包含两部分:一部分用于存储数据元素(即数据域),另一部分用于存储下一个结点地址(即指针域)。这种特性使得链表能够在运行时动态生成新的结点[^2]。 --- #### 计算链表的有效节点数量 为了获取单链表中有效节点的数量,可以采用以下方法: ```java public static int countNodes(Node head) { if (head == null || head.next == null) { // 判断是否为空链表或者只有一个头节点 return 0; } int count = 0; Node currentNode = head.next; // 不统计头节点本身 while (currentNode != null) { count++; currentNode = currentNode.next; } return count; } ``` 此函数能够有效地忽略头节点并仅统计实际有效的数据节点[^3]。 --- #### 遍历环形链表 如果需要处理的是环形链表,则其遍历方式略有不同。通常情况下,会利用辅助指针 `cur` 来完成这一操作。例如,在环形链表中找到某个特定条件下的节点或执行其他复杂操作时,可按照如下方式进行: ```java // 创建环形链表 public static void createCircularLinkedList(Node[] nodes) { for (int i = 0; i < nodes.length - 1; i++) { nodes[i].next = nodes[i + 1]; } nodes[nodes.length - 1].next = nodes[0]; // 形成闭环 } // 遍历环形链表 public static void traverseCircularList(Node first) { if (first == null) { return; } Node cur = first; do { System.out.print(cur.id + " -> "); cur = cur.next; } while (cur != first); // 当回到起点时停止 System.out.println(first.id); // 补充最后一个节点输出 } ``` 这段代码展示了如何创建和遍历环形链表的过程[^4]。 --- #### 总结 以上介绍了单链表的基础概念及其实现细节,并进一步探讨了如何计算链表长度以及遍历环形链表的具体方法。这些知识点构成了理解 Java 数据结构中链表的核心基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值