2024.1.26力扣每日一题——边权重均等查询

news2024/10/7 20:36:42

2024.1.26

      • 题目来源
      • 我的题解
        • 方法一 使用dfs对每一组查询都求最近公共祖先(会超时,通不过)
        • 方法二 不需要构建图,直接在原始数组上进行求最大公共祖先的操作。

题目来源

力扣每日一题;题序:2846

我的题解

方法一 使用dfs对每一组查询都求最近公共祖先(会超时,通不过)

使用dfs对每一组查询都去找最近公共祖先,并在这个过程中统计边的权重,最后通过TreeMap计算出边权重集合中元素重复的最大次数,贪心策略可知,结果为:查询路径上总共的边-最大次数。

时间复杂度:O( n 2 n^2 n2)
空间复杂度:O( m × n m\times n m×n)

 List<Integer> list;
 public int[] minOperationsQueries(int n, int[][] edges, int[][] queries) {
     Map<Integer,Integer>[] graph=createGraph(n,edges);
     int qn=queries.length;
     int[] res=new int[qn];
     for(int i=0;i<qn;i++){
         int from=queries[i][0];
         int to=queries[i][1];
         if(from==to)
             continue;
         list=new ArrayList<>();
         boolean[] visited=new boolean[n];
         dfs(graph,from,to,visited,new ArrayList<>());
         res[i]=needChange(list);
     }
     return res;
 }
 public int needChange(List<Integer> l){
     TreeMap<Integer, Long> frequencyMap = new TreeMap<>(l.stream()
         .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())));
     TreeMap<Integer, Long> frequencySortMap=new TreeMap<>(Comparator.comparing(frequencyMap::get));
     frequencySortMap.putAll(frequencyMap);
     return l.size()-Integer.parseInt(frequencySortMap.get(frequencySortMap.lastKey()).toString());
     
}
 public Map<Integer,Integer>[] createGraph(int n,int[][] edges){
     Map<Integer,Integer>[] graph=new HashMap[n];
     for(int i=0;i<n;i++)
         graph[i]=new HashMap<>();
     for(int[] e:edges){
         int from =e[0];
         int to=e[1];
         int val=e[2];
         graph[from].put(to,val);
         graph[to].put(from,val);
     }
     return graph;
 }
 public void dfs(Map<Integer,Integer>[] graph,int from,int to,boolean[] visited,List<Integer> path){
     if(from==to){
         list=new ArrayList(path);
         return ;
     }
     visited[from]=true;
     for(int next:graph[from].keySet()){
         if(!visited[next]){
             path.add(graph[from].get(next));
             dfs(graph,next,to,visited,path);
             path.remove(path.size()-1);
         }
     }
     visited[from]=false;
 }
方法二 不需要构建图,直接在原始数组上进行求最大公共祖先的操作。

参考:官方题解

以节点 0 为根节点,使用数组 count[i]记录节点 i到根节点 0 的路径上边权重的数量,即 count[i][j] 表示节点 i到根节点 0 的路径上权重为 j的边数量。对于查询 queries[i]=[ a i a_i ai, b i b_i bi],记节点 l c a i lca_i lcai为节点 a i a_i ai b i b_i bi的最近公共祖先,那么从节点 a i a_i ai到节点 b i b_i bi的路径上,权重为 j 的边数量 t j t_j tj的计算如下:

t j = count [ a i ] [ j ] + count [ b i ] [ j ] − 2 × count [ lca i ] [ j ] t_j = \textit{count}[a_i][j] + \textit{count}[b_i][j] - 2 \times \textit{count}[\textit{lca}_i][j] tj=count[ai][j]+count[bi][j]2×count[lcai][j]
为了让节点 a i a_i ai到节点 b i b_i bi路径上每条边的权重都相等,贪心地将路径上所有的边都更改为边数量最多的权重即可,即从节点 a i a_i ai到节点 b i b_i bi路径上每条边的权重都相等所需的最小操作次数 r e s i ​ res_i​ resi的计算如下: res i = ∑ j = 1 W t j − max ⁡ 1 ≤ j ≤ W t j \textit{res}_i = \sum_{j=1}^{W}t_j - \max_{1 \le j \le W}t_j resi=j=1Wtjmax1jWtj
其中 W=26W = 26W=26 表示权重的最大值。

时间复杂度:O((m+n)×W+m×logn),其中 n 是节点数目,m 是查询数目,W 是权重的可能取值数目。
空间复杂度:O(n×W+m)

class Solution {
    static final int W = 26;

    public int[] minOperationsQueries(int n, int[][] edges, int[][] queries) {
        int m = queries.length;
        Map<Integer, Integer>[] neighbors = new Map[n];
        for (int i = 0; i < n; i++) {
            neighbors[i] = new HashMap<Integer, Integer>();
        }
        for (int[] edge : edges) {
            neighbors[edge[0]].put(edge[1], edge[2]);
            neighbors[edge[1]].put(edge[0], edge[2]);
        }
        List<int[]>[] queryArr = new List[n];
        for (int i = 0; i < n; i++) {
            queryArr[i] = new ArrayList<int[]>();
        }
        for (int i = 0; i < m; i++) {
            queryArr[queries[i][0]].add(new int[]{queries[i][1], i});
            queryArr[queries[i][1]].add(new int[]{queries[i][0], i});
        }

        int[][] count = new int[n][W + 1];
        boolean[] visited = new boolean[n];
        int[] uf = new int[n];
        int[] lca = new int[m];
        tarjan(0, -1, neighbors, queryArr, count, visited, uf, lca);
        int[] res = new int[m];
        for (int i = 0; i < m; i++) {
            int totalCount = 0, maxCount = 0;
            for (int j = 1; j <= W; j++) {
                int t = count[queries[i][0]][j] + count[queries[i][1]][j] - 2 * count[lca[i]][j];
                maxCount = Math.max(maxCount, t);
                totalCount += t;
            }
            res[i] = totalCount - maxCount;
        }
        return res;
    }

    public void tarjan(int node, int parent, Map<Integer, Integer>[] neighbors, List<int[]>[] queryArr, int[][] count, boolean[] visited, int[] uf, int[] lca) {
        if (parent != -1) {
            System.arraycopy(count[parent], 0, count[node], 0, W + 1);
            count[node][neighbors[node].get(parent)]++;
        }
        uf[node] = node;
        for (int child : neighbors[node].keySet()) {
            if (child == parent) {
                continue;
            }
            tarjan(child, node, neighbors, queryArr, count, visited, uf, lca);
            uf[child] = node;
        }
        for (int[] pair : queryArr[node]) {
            int node1 = pair[0], index = pair[1];
            if (node != node1 && !visited[node1]) {
                continue;
            }
            lca[index] = find(uf, node1);
        }
        visited[node] = true;
    }

    public int find(int[] uf, int i) {
        if (uf[i] == i) {
            return i;
        }
        uf[i] = find(uf, uf[i]);
        return uf[i];
    }
}

困难题果然不是我会做的,做做搬运工得了在这里插入图片描述

有任何问题,欢迎评论区交流,欢迎评论区提供其它解题思路(代码),也可以点个赞支持一下作者哈😄~

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

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

相关文章

[C++] opencv + qt 创建带滚动条的图像显示窗口代替imshow

在OpenCV中&#xff0c;imshow函数默认情况下是不支持滚动条的。如果想要显示滚动条&#xff0c;可以考虑使用其他库或方法来进行实现。 一种方法是使用Qt库&#xff0c;使用该库可以创建一个带有滚动条的窗口&#xff0c;并在其中显示图像。具体步骤如下&#xff1a; 1&…

《汇编语言》- 读书笔记 - 各章检测点归档

《汇编语言》- 读书笔记 - 各章检测点归档 检测点 1.1检测点 2.1检测点 2.2检测点 2.3检测点 3.1检测点 3.2检测点 6.1检测点 9.1 检测点 1.1 1个CPU 的寻址能力为8KB&#xff0c;那么它的地址总线的宽度为 13 。 解&#xff1a;8KB 8192B 213 1KB的存储器有 10…

###C语言程序设计-----C语言学习(9)#函数基础

前言&#xff1a;感谢您的关注哦&#xff0c;我会持续更新编程相关知识&#xff0c;愿您在这里有所收获。如果有任何问题&#xff0c;欢迎沟通交流&#xff01;期待与您在学习编程的道路上共同进步。 一. 基础知识的学习 1.函数的定义 函数是一个完成特定工作的独立程序模块&…

酷开系统 | 拓展内容营销边界,酷开科技大屏价值全面升维

丰富的内容是智能大屏吸引消费者的关键。随着智能大屏各类垂直应用的增多&#xff0c;和长、短视频等多元内容的加入&#xff0c;使消费者的使用需求进一步激发和释放&#xff0c;这些流量的加入&#xff0c;也使大屏成为了营销的天然宝藏。酷开科技一直致力于OTT大屏营销&…

这个人脸考勤技术,拿走直接套用!请收藏!

随着科技的不断发展&#xff0c;人脸识别技术在各个领域得到了广泛应用&#xff0c;其中之一就是人脸考勤系统。 三维人脸考勤系统作为现代智能考勤的代表&#xff0c;通过先进的人脸识别技术&#xff0c;为组织提供了一种高效、准确、安全的考勤解决方案。 客户案例 制造企业…

【XR806开发板试用】TCP通信测试 Ping 命令测试

1.工程准备 由于要使用wifi功能&#xff0c;直接从wlan_demo复制一份出来&#xff0c;然后修改。 源文件只留下 main.c 就可以了。 BUILD.gn文件 import("//device/xradio/xr806/liteos_m/config.gni")static_library("app_mying") {configs []sources…

【C语言】const修饰指针的不同作用

目录 const修饰变量 const修饰指针变量 ①不用const修饰 ②const放在*的左边 ③const放在*的右边 ④*的左右两边都有const 结论 const修饰变量 变量是可以修改的&#xff0c;如果把变量的地址交给⼀个指针变量&#xff0c;通过指针变量的也可以修改这个变量。 但…

vue - 指令(一)

看文章可以得到什么&#xff1f; 1.可以快速的了解并会使用vue的指令 2.可以加深你对vue指令的理解&#xff0c;知道每个指令代表什么功能​​​​​​​ 目录 什么是vue的指令&#xff1f;​​​​​​​ vue常见指令的使用 v-html v-show v-if v-else 和v-else-…

JVM 性能调优 - Java 中的四种引用(4)

为什么会有四种引用 我们先回顾下在 Java 虚拟机内存体系(1) 中提到了的垃圾回收算法 1、引用计数法 原理:给对象添加一个引用计数器,每当有一个地方引用它,计数器的值就加一。每当有一个引用失效,计数器的值就减一。当计数器值为零时,这个对象被认为没有其他对象引用,…

解决ssh: connect to host 192.168.x.x port 22: Connection refused

我在使用scp命令向另一目标主机传输文件时提示ssh: connect to host 192.168.x.x port 22: Connection refused错误&#xff0c;总结出现的原因&#xff0c;及解决办法。 查看目标主机的ssh服务是否启动 service ssh status 如下图显示则启动状态 如果提示Unit ssh.service co…

python制作恶意软件删除工具

今天&#xff0c;来教大家用python制作一个恶意软件删除工具 查杀流程图 对&#xff0c;就这些&#xff0c;已经具备了杀毒软件的功能 判断文件是否为病毒 要查杀病毒&#xff0c;先要判断文件是不是病毒&#xff08;不然删错了咋办&#xff09;&#xff0c;这里我们用获取文…

『运维备忘录』之 Vim 命令详解

运维人员不仅要熟悉操作系统、服务器、网络等只是&#xff0c;甚至对于开发相关的也要有所了解。很多运维工作者可能一时半会记不住那么多命令、代码、方法、原理或者用法等等。这里我将结合自身工作&#xff0c;持续给大家更新运维工作所需要接触到的知识点&#xff0c;希望大…

多彩贵州人文山水展风采,微环境监测智能调控护古韵

一、人文山水时光峰峦——多彩贵州历史文化展 2月3日&#xff0c;贵州省博物馆向公众开放《人文山水时光峰峦——多彩贵州历史文化展》。6000平方米展厅里&#xff0c;从石器时期开始&#xff0c;通过六个篇章&#xff0c;用3503件文物的回忆链&#xff0c;系统化的向观众揭开…

我要成为嵌入式高手之2月4、5日Linux高编第二天!!

读写函数接口 1、fgetc 语法&#xff1a; 功能&#xff1a;从流中获取一个字符 练习1&#xff1a;编写程序统计文件的行数 #include <stdio.h>int main(void) {FILE *fp NULL;char ch 0;int row 0;fp fopen("file.txt","r");if (NULL fp){pe…

C#验证字符串的长度,用正则表达式 vs 字符数组长度或字符串的长度

目录 一、使用的方法 1.使用正则表达式 2.通过计算字符串的长度验证 二、实例 1.源码 2.生成效果 一、使用的方法 1.使用正则表达式 使用正则表达式可以判断和限制用户输入的字符串长度。 比如验证用户密码不得少于8为&#xff0c;匹配的正则表达式"^.{8,}$"…

ShardingSphere 5.x 系列【5】Spring Boot 3 集成并实现读写分离

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Spring Boot 版本 3.1.0 本系列ShardingSphere 版本 5.4.0 源码地址&#xff1a;https://gitee.com/pearl-organization/study-sharding-sphere-demo 文章目录 1. 概述2. 使用限制3. 案例演示3.…

空气质量预测 | Matlab实现基于SVR支持向量机回归的空气质量预测模型

文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 政府机构使用空气质量指数 (AQI) 向公众传达当前空气污染程度或预测空气污染程度。 随着 AQI 的上升,公共卫生风险也会增加。 不同国家有自己的空气质量指数,对应不同国家的空气质量标准。 基于支持向量机(Su…

高速接口PCB布局指南(一)高速信号接口概述

高速接口PCB布局指南&#xff08;一&#xff09;高速信号接口概述 1.什么是高速信号接口&#xff1f;2.高速信号PCB设计概述2.1 概述2.2 关键信号 tips&#xff1a;资料主要来自网络&#xff0c;仅供学习使用。 1.什么是高速信号接口&#xff1f; 高速信号接口是指用于传输高…

jmeter-04创建请求

文章目录 一、发送请求-查看响应流程二、新建请求三、选择请求方式&#xff0c;填写url1.发送get请求当只有请求方式不一样的时候&#xff0c;参数都填写在参数栏里面&#xff0c;GET请求与POST请求的区别&#xff1f; 2.发送post请求2.1 application/x-www-form-urlencoded2.2…

二叉搜索树题目:二叉搜索树的最近公共祖先

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法一思路和算法代码复杂度分析 解法二思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;二叉搜索树的最近公共祖先 出处&#xff1a;235. 二叉搜索树的最近公共祖先 难度 3 级 题目描述 要求 给定一个…