剑指Offer题目笔记33(并查集)

news2024/11/16 16:39:47

面试题116:

面试题116

解决方案:

​ 一个班级可以包含一个或多个朋友圈,对应的图中可能包含一个或多个子图,每个朋友圈对应一个子图。因此,这个问题可以转化为如何求图中子图的数目。图的搜索算法可以用来计算图中子图的数目。扫描图中所有的节点。如果某个节点v之前没有访问过,就搜索它所在的子图。当所有节点都访问完之后,就可以知道图中有多少个子图。

源代码(使用图的搜索):
class Solution {
    public int findCircleNum(int[][] isConnected) {
        boolean[] visited = new boolean[isConnected.length];
        int result = 0;
        for(int i = 0;i < isConnected.length;i++){
            if(!visited[i]){
                findCircle(isConnected,visited,i);
                result++;
            }  
        }

        return result;
    }

	//遍历同学i的朋友
    private void findCircle(int[][] isConnected,boolean[] visited,int i){
        Queue<Integer> queue = new LinkedList<>();
        queue.add(i);
        visited[i] = true;
        while(!queue.isEmpty()){
            int t = queue.remove();
            for(int friend = 0;friend < isConnected.length;friend++){
                if(isConnected[t][friend] == 1 && !visited[friend]){
                    queue.add(friend);
                    visited[friend] = true;
                }
            }
        }
    }
}
源代码(并查集):
class Solution {
    public int findCircleNum(int[][] isConnected) {
        int[] fathers = new int[isConnected.length];
        for(int i = 0;i < fathers.length;i++){
            fathers[i] = i;
        }

        int count = fathers.length;
        for(int i = 0;i < isConnected.length;i++){
            for(int j = i+1;j < isConnected.length;j++){
                if(isConnected[i][j] == 1 && union(fathers,i,j)){
                    count--;
                }
            }
        }

        return count;
    }
    
	//如果它们的根节点不相同,那么合并他们的朋友圈,如果相同,那么直接返回false
    private boolean union(int[] fathers,int i,int j){
        int fatherOfI = findFather(fathers,i);
        int fatherOfJ = findFather(fathers,j);
        if(fatherOfI != fatherOfJ){
            fathers[fatherOfI] = fatherOfJ;
            return true;
        }

        return false;
    }
    
	//压缩路径,使fathers[i]保存的是子集的根节点
    private int findFather(int[] fathers,int i){
        if(fathers[i] != i){
            fathers[i] = findFather(fathers,fathers[i]);
        }

        return fathers[i];
    }
}

面试题117:

面试题117

解决方案:

​ 把输入数组中的每个字符串看成图中的一个节点。如果两个字符串相似,那么它们对应的节点之间有一条边相连,也就属于同一个子图。例如,字符串[“tars”,“rats”,“arts”,“star”]根据相似性分别属于两个子图。

源代码:
class Solution {
    public int numSimilarGroups(String[] strs) {
        int[] fathers = new int[strs.length];
        for(int i = 0;i < fathers.length;i++){
            fathers[i] = i;
        }

        int groups = strs.length;
        for(int i = 0;i < strs.length;i++){
            for(int j = i + 1;j < strs.length;j++){
                if(similar(strs[i],strs[j]) && union(fathers,i,j)){
                    groups--;
                }
            }
        }

        return groups;
    }

    private boolean similar(String str1,String str2){
        int diffCount = 0;
        for(int i = 0;i < str1.length();i++){
            if(str1.charAt(i) != str2.charAt(i)){
                diffCount++;
            }
        }

        return diffCount <= 2;
    }

    //如果它们的根节点不相同,那么合并子集,如果相同,那么直接返回false
    private boolean union(int[] fathers,int i,int j){
        int fatherOfI = findFather(fathers,i);
        int fatherOfJ = findFather(fathers,j);
        if(fatherOfI != fatherOfJ){
            fathers[fatherOfI] = fatherOfJ;
            return true;
        }

        return false;
    }
    
    //压缩路径,使fathers[i]保存的是子集的根节点
    private int findFather(int[] fathers,int i){
        if(fathers[i] != i){
            fathers[i] = findFather(fathers,fathers[i]);
        }

        return fathers[i];
    }
}

面试题118:

面试题118

解决方案:
  1. 逐步在图中添加5条边以便找出形成环的条件。最开始的时候图中的5个节点是离散的,任意两个节点都没有边相连。也就是说,图被分割成5个子图,每个子图只有一个节点。
  2. 通过一步步在图中添加边可以发现判断一条边会不会导致环的规律。如果两个节点分别属于两个不同的子图,添加一条边连接这两个节点,会将它们所在的子图连在一起,但不会形成环。如果两个节点属于同一个子图,添加一条边连接这两个节点就会形成一个环。
源代码:
class Solution {
    public int[] findRedundantConnection(int[][] edges) {
        int maxVertex = 0;
        //找出节点个数
        for(int[] edge:edges){
            maxVertex = Math.max(maxVertex,edge[0]);
            maxVertex = Math.max(maxVertex,edge[1]);
        }
        
        int[] fathers = new int[maxVertex+1];
        //将n个节点初始化为n个子集,每个节点的根节点都指向它自己
        for(int i = 1;i <= maxVertex;i++){
            fathers[i] = i;
        }

        for(int[] edge:edges){
            if(!union(fathers,edge[0],edge[1])){
                return edge;
            }
        }

        return new int[2];
    }
    
	//合并子集
    private boolean union(int[] fathers,int i,int j){
        int fatherOfI = findFather(fathers,i);
        int fatherOfJ = findFather(fathers,j);
        if(fatherOfI != fatherOfJ){
            fathers[fatherOfI] = fatherOfJ;
            return true;
        }

        return false;
    }

    //压缩路径,使fathers[i]保存的是子集的根节点
    private int findFather(int[] fathers,int i){
        if(fathers[i] != i){
            fathers[i] = findFather(fathers,fathers[i]);
        }

        return fathers[i];
    }
}

面试题119:

面试题119

解决方案:

​ 这个题目是关于整数的连续性的。如果将每个整数看成图中的一个节点,相邻的(数值大小相差1)两个整数有一条边相连,那么这些整数将形成若干子图,每个连续数值序列对应一个子图。计算最长连续序列的长度就转变成求最大子图的大小。

源代码(使用广度优先搜索):
class Solution {
    public int longestConsecutive(int[] nums) {
        Set<Integer> set = new HashSet<>();
        for(int num:nums){
            set.add(num);
        }

        int longest = 0;
        while(!set.isEmpty()){
            Iterator<Integer> iter = set.iterator();
            longest = Math.max(longest,bfs(set,iter.next()));
        }

        return longest;
    }
    
	//搜索最长数字连续的最长序列
    private int bfs(Set<Integer> set,int num){
        Queue<Integer> queue = new LinkedList<>();
        queue.offer(num);
        set.remove(num);
        int length = 1;
        while(!queue.isEmpty()){
            int i = queue.poll();
            int[] neighbors = new int[]{i-1,i+1};
            for(int neighbor:neighbors){
                if(set.contains(neighbor)){
                    queue.offer(neighbor);
                    set.remove(neighbor);
                    length++;
                }
            }
        }

        return length;
    }
}
源代码(使用并查集):
class Solution {
    public int longestConsecutive(int[] nums) {
        Map<Integer,Integer> fathers = new HashMap<>();
        //保存每个数字的最长数字序列
        Map<Integer,Integer> counts = new HashMap<>();
        Set<Integer> all = new HashSet<>();
        for(int num:nums){
            fathers.put(num,num);
            counts.put(num,1);
            all.add(num);
        }

        for(int num:nums){
            //如果数组中存在num + 1的数字,那就两个子集合并
            if(all.contains(num + 1)){
                union(fathers,counts,num,num+1);
            }
			//如果数组中存在num - 1的数字,那就两个子集合并
            if(all.contains(num-1)){
                union(fathers,counts,num,num-1);
            }
        }

        int longest = 0;
        for(int length:counts.values()){
            longest = Math.max(longest,length);
        }

        return longest;
    }

    private int findFather(Map<Integer,Integer> fathers,int i){
        if(fathers.get(i) != i){
            fathers.put(i,findFather(fathers,fathers.get(i)));
        }

        return fathers.get(i);
    }

    private void union(Map<Integer,Integer> fathers,Map<Integer,Integer> counts,int i,int j){
        int fatherOfI = findFather(fathers,i);
        int fatherOfJ = findFather(fathers,j);
        if(fatherOfI != fatherOfJ){
            fathers.put(fatherOfI,fatherOfJ);
            int countOfI = counts.get(fatherOfI);
            int countOfJ = counts.get(fatherOfJ);
            //合并后,长度也叠加
            counts.put(fatherOfJ,countOfI + countOfJ);
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1605563.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

3D模型处理的多进程并行【Python】

今天我们将讨论如何使用 Python 多进程来处理大量3D数据。 我将讲述一些可能在手册中找到的一般信息&#xff0c;并分享我发现的一些小技巧&#xff0c;例如将 tqdm 与多处理 imap 结合使用以及并行处理存档。 NSDT工具推荐&#xff1a; Three.js AI纹理开发包 - YOLO合成数据生…

PLC工业网关,实现PLC联网

在当今工业自动化领域&#xff0c;PLC&#xff08;可编程逻辑控制器&#xff09;作为控制系统的核心&#xff0c;其稳定性和可靠性至关重要。然而&#xff0c;随着工业互联网和智能制造的快速发展&#xff0c;如何实现PLC的联网通信&#xff0c;提高数据传输效率&#xff0c;成…

URL的绝对路径/相对路

一、URL 浏览器要想发起请求,必须是一个完整的url地址. URL是一个固定格式的字符串 它表达了&#xff1a; 从网络中 哪台计算机&#xff08;domain&#xff09; 中的 哪个程序&#xff08;port&#xff09; 寻找 哪个服务&#xff08;path&#xff09;&#xff0c;并注明了…

数据治理中心DataArts Studio学习

一、什么是DataArts Studio&#xff1f; 数据治理中心DataArts Studio是为了应对上述挑战&#xff0c;针对企业数字化运营诉求提供的具有数据全生命周期管理和智能数据管理能力的一站式治理运营平台&#xff0c;包含数据集成、数据开发、数据架构、数据质量监控、数据资产管理…

使用vue2-ace-editor实现可选择的代码编辑器

最近在琢磨前端&#xff0c;因项目中需要在页面上编辑代码&#xff0c;所以需要写一个代码编辑器供用户使用。找了几个编辑器相关的组件&#xff0c;对比了下感觉还是vue2-ace-editor用着舒服&#xff0c;写了demo供大家参考。 由于我的项目使用的是vue2&#xff0c;二开鹅厂的…

MySQL高负载排查方法最佳实践(15/16)

高负载排查方法 CPU占用率过高问题排查 使用mpstat查看cpu使用情况。 # mpstat 是一款 CPU 性能指标实时展示工具 # 能展示每个 CPU 核的资源视情况&#xff0c;同时还能将资源使用情况进行汇总展示 # 如果CPU0 的 %idle 已经为 0 &#xff0c;说明此核已经非常繁忙# 打印所…

算法训练营第25天回溯(分割)

回溯算法&#xff08;分割&#xff09; 131.分割回文串 力扣题目链接(opens new window) 题目 给定一个字符串 s&#xff0c;将 s 分割成一些子串&#xff0c;使每个子串都是回文串。 返回 s 所有可能的分割方案。 示例: 输入: “aab” 输出: [ [“aa”,“b”], [“a”,“…

Redis中的Lua脚本(二)

Lua脚本 创建排序辅助函数 为了防止带有副作用的函数令脚本产生不一致的数据&#xff0c;Redis对math库的math.random函数和math.randomseed函数进行了替换。对于Lua脚本来说&#xff0c;另一个可能产生不一致数据的地方是哪些带有不确定性质的命令&#xff0c;比如对于一个集…

Linux中如何安装ImageMagick及其常规使用命令

在Linux中安装ImageMagick可以通过包管理工具进行安装。具体步骤如下&#xff1a; 打开终端&#xff08;Terminal&#xff09;。 使用以下命令更新系统软件包列表&#xff1a; sudo apt update使用以下命令安装ImageMagick&#xff1a; sudo apt install imagemagick安装完…

大型网站系统架构演化实例_2.使用缓存改善网站性能

1.使用缓存改善网站性能 网站访问的特点和现实世界的财富分配一样遵循二八定律&#xff1a;80%的业务访问集中在20%的数据上。既然大部分业务访问集中在一小部分数据上&#xff0c;那么如果把这一小部分数据缓存在内存中&#xff0c;就可以减少数据库的访问压力&#xf…

在Linux系统中,禁止有线以太网使用NTP服务器进行时间校准的几种方法

目录标题 方法 1&#xff1a;修改NTP配置以禁止所有同步方法 2&#xff1a;通过网络配置禁用NTP同步方法 3&#xff1a;禁用NTP服务 在Linux系统中&#xff0c;如果想要禁止有线以太网使用NTP服务器进行时间校准&#xff0c;可以通过以下几种方法之一来实现&#xff1a; 方法 …

LDF、DBC、BIN、HEX、S19、BLF、asc、csv、ARXML、slx等(未完待续)

文章目录 如题如题 LDF是LIN报文格式文件,把这个直接拖到软件里面,可以发报文和接收报文 DBC是CAN报文格式文件,把这个直接拖到软件里面,可以发报文和接收报文 BIN文件烧录在BOOT里面(stm32),有人喜欢叫固件,这个固件就是bin文件,bin文件比hex文件体积小 其实BOOT也…

探索AI提示词网站:助力内容创作与AI对话

嗨&#xff0c;大家好&#xff01;在这个充满创意的时代里&#xff0c;AI技术为我们带来了许多惊喜和便利。如果你是一个内容创作者&#xff0c;无论是在撰写博客还是进行科技对话&#xff0c;今天我将向大家介绍几个能够提升与AI对话效率的神奇网站。 1. FlowGPT 首先&#xf…

PhotoShop2024安装包(亲测可用)

目录 一、软件简介 二、软件下载 一、软件简介 Adobe Photoshop是一款由Adobe Systems开发的图像编辑软件。它被广泛用于图像处理和数字艺术创作&#xff0c;是设计师、摄影师和艺术家们的首选工具之一。 主要功能&#xff1a; 图像编辑&#xff1a; Photoshop提供了丰富的编辑…

点云的投影------PCL

点云的投影 /// <summary> /// 参数化模型投影点云 /// </summary> /// <param name"cloud">点云</param> /// <param name"x">投影平面x面的系数</param> /// <param name"y"></param> /// &…

M系Mac关闭SIP

文章目录 M系Mac关闭SIP一&#xff1a;查看SIP状态二&#xff1a;关闭SIP步骤 M系Mac关闭SIP 一&#xff1a;查看SIP状态 1、使用终端 打开终端 输入csrutil status&#xff0c;回车 你会看到以下信息中的一个&#xff0c;指示SIP状态 已打开 System Integrity Protection s…

制作一个RISC-V的操作系统十一-外部设备中断

文章目录 中断分类mie mip中断处理流程外部中断中断源PLICPriorityPendingEnableThresholdClaim/CompletePLIC工作流程设置uart寄存器IER设置uart寄存器LSRasm volatile("mv %0, tp" : "r" (x) );头文件不能定义函数&#xff0c;不然每次导入都会定义一次s…

C++修炼之路之list--C++中的双向循环链表

目录 前言 一&#xff1a;正式之前先回顾数据结构中的双向循环链表 二&#xff1a;list的简介 三&#xff1a;STL中list常用接口函数的介绍及使用 1.构造函数接口 2.list迭代器 范围for 3.数据的修改接口函数 4.list容量操作函数 5.list的迭代器失效 6.演示代码和测…

RAG学习笔记系列(一)

RAG 介绍 RAG 全称为 Retrieval Augmented Generation&#xff08;检索增强生成&#xff09;。是基于LLM构建系统的一种架构。 RAG 基本上可以理解为&#xff1a;搜索 LLM prompting。根据用户的查询语句&#xff0c;系统会先使用搜索算法获取到相关内容作为上下文&#xff0…

最大公约数和最小公倍数(C语言)

一、N-S流程图&#xff1b; 二、运行结果&#xff1b; 三、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>//实现最大公约数函数&#xff1b; int max(int x, int y) {//初始化变量值&#xff1b;int judge 1;//运算&#xff1b;judge x %…