loud-and-rich

在一组N个人中,每个人都有不同数目的钱和安静程度。本篇介绍如何使用深度优先遍历算法,找出在所有拥有钱不少于某人的人中,最安静的人。通过优化的深度优先遍历,避免了不必要的比较,提高了算法效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:loud-and-rich

题目描述

在一组 N 个人(编号为 0, 1, 2, …, N-1)中,每个人都有不同数目的钱,以及不同程度的安静(quietness)。为了方便起见,我们将编号为 x 的人简称为 "person x "。如果能够肯定 person x 比 person y 更有钱的话,我们会说 richer[i] = [x, y] 。注意 richer 可能只是有效观察的一个子集。另外,如果 person x 的安静程度为 q ,我们会说 quiet[x] = q 。现在,返回答案 answer ,其中 answer[x] = y 的前提是,在所有拥有的钱不少于 person x 的人中,person y 是最安静的人(也就是安静值 quiet[y] 最小的人)

题目分析

  1. 直观上看,对每个人,我们需要找出比他有钱或者和他一样有钱(他自己)的人,然后比较找出这些人(包括他自己)中最安静的一个作为结果。(解法1)
  2. 事实上,在寻找结果过程中,我们没必要找出所有比他有钱的人,比如A比B有钱,C比A有钱,在查找过程中,对于B,我们没有必要同时比较A、B、C三个人的安静值,我们可以先比较A、C的安静值,将min(A, C)结果存起来,然后再比较min(min(A, C), B)的值,即得出比B有钱且最安静的人。(解法2)

算法

深度优先遍历(Depth-first-Search)

代码

import java.util.*;

class Solution {
    public int[] loudAndRich(int[][] richer, int[] quiet) {
        int N = quiet.length; 
        Map<Integer, Set<Integer>> map = new HashMap<>(); // value值存的是比key值更有钱的人
        for (int[] r : richer) {
            Set<Integer> tmp = map.getOrDefault(r[1], new HashSet<>());
            tmp.add(r[0]);
            map.put(r[1], tmp);
        }
        for (int i = 0; i < N; i++) {
            // 遍历深搜,对每个人,找出比他更有钱的人
            Set<Integer> tmp = new HashSet<>();
            dfs(map, tmp, i);
            map.put(i, tmp);
        }

        int[] result = new int[N];
        for (int i = 0; i < N; i++) {
            // 比较,对每个人,从比他更有钱的人找出最安静的人
            result[i] = i;
            for (int p : map.get(i)) {
                if (quiet[result[i]] > quiet[p])
                    result[i] = p;
            }
        }
        return result;
    }
    
    public void dfs(Map<Integer, Set<Integer>> map, Set<Integer> cur, int j) {
        Set<Integer> tmp = new HashSet<>(map.getOrDefault(j, new HashSet<>()));
        for (int richer : tmp) {
            if (!cur.contains(richer)) {
                cur.add(richer);
                dfs(map, cur, richer);                
            }
        }
    }    
}

深度优先遍历(优化)(Depth-first-Search)

代码

import java.util.*;

class Solution {
    List<Integer>[] graph; // 同解法1map,graph[i]表示比i更有钱的人(不完全集合)
    int[] result;
    int[] quiet;
    
    public int[] loudAndRich(int[][] richer, int[] quiet) {
        int N = quiet.length; 
        graph = new ArrayList[N];
        result = new int[N];
        this.quiet = quiet;
        
        for (int i = 0; i < N; i++) {
            graph[i] = new ArrayList<Integer>();
            result[i] = -1;
        }
        for (int[] edge : richer) {
            graph[edge[1]].add(edge[0]);
        }
        for (int node = 0; node < N; node++) {
            dfs(node);
        }
        return result;
    }
    
    // 返回比node更有钱或同样有钱(包括他自己)的人中最安静的人的编号
    public int dfs(int node) {
        if (result[node] == -1) {
            result[node] = node;
            for (int child : graph[node]) {
                int cand = dfs(child);
                if (quiet[cand] < quiet[result[node]]) {
                    result[node] = cand;
                }
            }
        }
        return result[node];
    }    
}
资源下载链接为: https://pan.quark.cn/s/d9ef5828b597 在本文中,我们将探讨如何通过 Vue.js 实现一个带有动画效果的“回到顶部”功能。Vue.js 是一款用于构建用户界面的流行 JavaScript 框架,其组件化和响应式设计让实现这种交互功能变得十分便捷。 首先,我们来分析 HTML 代码。在这个示例中,存在一个 ID 为 back-to-top 的 div 元素,其中包含两个 span 标签,分别显示“回到”和“顶部”文字。该 div 元素绑定了 Vue.js 的 @click 事件处理器 backToTop,用于处理点击事件,同时还绑定了 v-show 指令来控制按钮的显示与隐藏。v-cloak 指令的作用是在 Vue 实例渲染完成之前隐藏该元素,避免出现闪烁现象。 CSS 部分(backTop.css)主要负责样式设计。它首先清除了一些默认的边距和填充,对 html 和 body 进行了全屏布局,并设置了相对定位。.back-to-top 类则定义了“回到顶部”按钮的样式,包括其位置、圆角、阴影、填充以及悬停时背景颜色的变化。此外,与 v-cloak 相关的 CSS 确保在 Vue 实例加载过程中隐藏该元素。每个 .page 类代表一个页面,每个页面的高度设置为 400px,用于模拟多页面的滚动效果。 接下来是 JavaScript 部分(backTop.js)。在这里,我们创建了一个 Vue 实例。实例的 el 属性指定 Vue 将挂载到的 DOM 元素(#back-to-top)。data 对象中包含三个属性:backTopShow 用于控制按钮的显示状态;backTopAllow 用于防止用户快速连续点击;backSeconds 定义了回到顶部所需的时间;showPx 则规定了滚动多少像素后显示“回到顶部”按钮。 在 V
资源下载链接为: https://pan.quark.cn/s/9e7ef05254f8 以下是简化后的内容: 程序集变量 计数器:整数型 文本发送计次:整数型 子程序 __启动窗口_创建完毕 _手动发送数据_被单击 停止发送 发送预处理 判断端口是否启动成功,失败则提示并返回 根据组合框选择的进制类型,将编辑框内容转换后发送 发送失败则提示并返回 进制转换(被转换文本,被转换进制,转换的进制) 检查进制范围,错误则返回提示 规范参数,逐字符检查是否符合进制要求,不符合则返回错误提示 若进制相同直接返回原文本 否则进行进制转换并返回结果 _退出_被单击销毁 _组合框_端口号_列表项被选择 停止发送 设置端口号 _组合框_波特率_列表项被选择 停止发送 设置波特率 _组合框_数据位_列表项被选择 停止发送 设置数据位数 _组合框_校验_列表项被选择 停止发送 设置奇偶校验方案 _组合框_停止位_列表项被选择 停止发送 设置停止位数 发送预处理 停止发送 设置波特率、端口号、数据位数、奇偶校验方案、停止位数 根据奇偶校验方案设置校验标志 _选择框_DTR_被单击 根据选中状态设置信号操作 _选择框_RTS_被单击 根据选中状态设置信号操作 _选择框_Break_被单击 根据选中状态设置信号操作 _编辑框_发送周期_内容被改变 若时钟标志选中,设置时钟周期 _选择框_时钟标志_被单击 若选中,设置发送方式为时钟模式,启动发送并设置时钟周期 否则,停止发送,设置时钟周期为0 _组合框_发送方式_列表项被选择 根据选择设置时钟标志和时钟周期 _端口_发送数据_收到信号 _端口_接收数据_收到信号 _端口_接收数据_数据到达 根据接收数据的进制选择,将数据转换后显示在编辑框中 _时钟1_周期事件 根据发送方式和进制选择,周期性发送数据 打开并读入文件 打开文件,读取内容到编辑框 _打开
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值