算法-约瑟夫环问题

题目: 给定两个可能有环也可能无环的单链表,头结点 head1 和 head2。 请实现一个函数,如果两个链表相交,请返回相交的 第一个节点 。如果不相交,返回 null 【要求】 如果两个链表的长度之和为 N ,时间复杂度请达到 O(N) , 额外空间复杂度请达到 O(1) 。

使用容器定位

  • 思路一 (空间复杂度无法达到要求)使用容器完成约瑟夫环:

    比如无环链表: head->A->B->C->D->E->null 与 有环链表: head->A->B->C->D->B->E->null 可以使用 hash 表进行存储,当因为 hash 表中存储的元素都是唯一的,也就是说当我们在遍历链表的过程当中, 将元素置入 hash 表当中,如果链表遍历但最后一个 null 都没有出现重复的元素,则表示该链表不存在环。 如果在遍历的过程当中,一但出现重复的元素,则表示该链表已经形成了一个环。

kotlin 复制代码
    /**
     * 利用容器实现环的查找
     *
     * @param elements
     * @param <E>
     * @return
     */
    public static <E> E vesselScreen(LinkedList<E> elements) {
        HashSet<E> screen = new HashSet<E>();
        for (int i = 0; i < elements.getSize(); i++) {
            E data = elements.get(i);
            if (screen.contains(data))
                return data;
            screen.add(data);
        }
        return null;
    }

通过快慢指针定位

  • 思路二 (空间复杂度 O(1))使用快慢指针:

    通过快慢两个指针的移动,完成对该链表的遍历。如果慢指针最终指向空,则表示该链表是不存在环的,如果慢指针最终追上了快指针,则表示必定有环,因为当没有环的时候,本身快指针就比慢指针走的快,是不可能相遇的。

虽然是相遇,但是却无法定位到入环节点。当两个指针相遇的时候,快指针回到开头节点,快指针走一步,而慢指针走两步,而当快慢指针再次相遇的时候,便是入环的节点。

附录-代码

  • 节点元素

    kotlin 复制代码
    package com.peppa.common;
    ​
    /**
     * 自定义对的节点元素
     * @param <T>
     */
    public class Node<T> {
        T data;
        Node<T> next;
        public Node(T data){
            this.data=data;
            this.next=null;
        }
    }
  • 链表结构

    ini 复制代码
    package com.peppa.common;
    ​
    /**
     * 自定义链表结构
     */
    public class LinkedList<T> {
        private Node<T> head; // 头结点
        private int length; // 链表长度
    ​
        // 添加元素到尾巴节点
        public void append(Node<T> data) {
            if (head == null) {
                head = data;
                length = 1;
                return;
            }
            Node<T> current = head;
            while (current.next != null) { // 定位到最后的一个元素
                current = current.next;
            }
            current.next = data;// 追加到尾部
            length++;
        }
    ​
        //打印链表元素
        public void printList() {
            Node<T> current = head;
            int coutn = 0;
            while (current != null && coutn < length) {
                System.out.print(current.data + " ");
                current = current.next;
                coutn++;
            }
            System.out.println();
        }
    ​
        //根据元素下标获取元素数据
        public T get(int index) {
            Node<T> current = head;
            if (index > length << 1) {
                return current.data;
            }
            for (int i = 0; i < index; i++) {
                current = current.next;
            }
            return current.data;
        }
    ​
        public int getSize() {
            return length;
        }
    ​
    }
  • main

    ini 复制代码
    /**
         * 运行程序
         *
         * @param args
         */
        public static void main(String[] args) {
            LinkedList<Integer> linkedList = new LinkedList();
            Node<Integer> integerNode_1 = new Node<Integer>(1);
            Node<Integer> integerNode_2 = new Node<Integer>(2);
            Node<Integer> integerNode_3 = new Node<Integer>(3);
            Node<Integer> integerNode_4 = new Node<Integer>(4);
            Node<Integer> integerNode_5 = new Node<Integer>(5);
            Node<Integer> integerNode_6 = new Node<Integer>(6);
            Node<Integer> integerNode_7 = new Node<Integer>(7);
            linkedList.append(integerNode_1);
            linkedList.append(integerNode_2);
            linkedList.append(integerNode_3);
            linkedList.append(integerNode_4);
            linkedList.append(integerNode_5);
            linkedList.append(integerNode_6);
            linkedList.append(integerNode_7);
            linkedList.append(integerNode_3);
            linkedList.printList();
    ​
            Integer data = vesselScreen(linkedList);
            if (data != null)
                System.out.println("有环-相交元素为: " + data);
            else
                System.out.println("无环-无相交元素");
        }

    算法文件地址

    约瑟夫环

相关推荐
Fine姐9 分钟前
数据挖掘3.6~3.10 支持向量机—— 核化SVM
算法·支持向量机·数据挖掘
野渡拾光2 小时前
【考研408数据结构-05】 串与KMP算法:模式匹配的艺术
数据结构·考研·算法
tainshuai4 小时前
用 KNN 算法解锁分类的奥秘:从电影类型到鸢尾花开
算法·分类·数据挖掘
Coovally AI模型快速验证9 小时前
农田扫描提速37%!基于检测置信度的无人机“智能抽查”路径规划,Coovally一键加速模型落地
深度学习·算法·yolo·计算机视觉·transformer·无人机
pusue_the_sun9 小时前
数据结构:二叉树oj练习
c语言·数据结构·算法·二叉树
RaymondZhao3410 小时前
【全面推导】策略梯度算法:公式、偏差方差与进化
人工智能·深度学习·算法·机器学习·chatgpt
zhangfeng113310 小时前
DBSCAN算法详解和参数优化,基于密度的空间聚类算法,特别擅长处理不规则形状的聚类和噪声数据
算法·机器学习·聚类
啊阿狸不会拉杆11 小时前
《算法导论》第 32 章 - 字符串匹配
开发语言·c++·算法
小学生的信奥之路11 小时前
洛谷P3817题解:贪心算法解决糖果分配问题
c++·算法·贪心算法
你知道网上冲浪吗12 小时前
【原创理论】Stochastic Coupled Dyadic System (SCDS):一个用于两性关系动力学建模的随机耦合系统框架
python·算法·数学建模·数值分析