【我也想刷穿 LeetCode啊】851. 喧闹和富有

61 阅读3分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

现在前端很多岗位面试需要有一定的算法基础,或者说经常刷算法的会优先考虑。

因此每天刷刷LeetCode非常有必要

在这之前我也刷过一些算法题,也希望以后也坚持刷,跟某掘友一样,我也想刷穿 LeetCode

一、题目描述

有一组 n 个人作为实验对象,从 0 到 n - 1 编号,其中每个人都有不同数目的钱,以及不同程度的安静值(quietness)。为了方便起见,我们将编号为 x 的人简称为 "person x "。

给你一个数组 richer ,其中 richer[i] = [ai, bi] 表示 person ai 比 person bi 更有钱。另给你一个整数数组 quiet ,其中 quiet[i] 是 person i 的安静值。richer 中所给出的数据 逻辑自洽(也就是说,在 person x 比 person y 更有钱的同时,不会出现 person y 比 person x 更有钱的情况 )。

现在,返回一个整数数组 answer 作为答案,其中 answer[x] = y 的前提是,在所有拥有的钱肯定不少于 person x 的人中,person y 是最安静的人(也就是安静值 quiet[y] 最小的人)。

 

示例 1:

输入:richer = [[1,0],[2,1],[3,1],[3,7],[4,3],[5,3],[6,3]], quiet = [3,2,5,4,6,1,7,0]
输出:[5,5,2,5,4,5,6,7]
解释: 
answer[0] = 5,
person 5 比 person 3 有更多的钱,person 3 比 person 1 有更多的钱,person 1 比 person 0 有更多的钱。
唯一较为安静(有较低的安静值 quiet[x])的人是 person 7,
但是目前还不清楚他是否比 person 0 更有钱。
answer[7] = 7,
在所有拥有的钱肯定不少于 person 7 的人中(这可能包括 person 3456 以及 7),
最安静(有较低安静值 quiet[x])的人是 person 7。
其他的答案也可以用类似的推理来解释。

示例 2:

输入:richer = [], quiet = [0]
输出:[0]

二、思路分析

题目抽象出来就是:一个DAG,求一个ans数组,ans[i]表示i号点能到达的点中a值最小的点编号。

有一些特殊限制帮助我们简化代码:a数组数值都是0~n-1且两两不同。

利用以上特殊限制,我们先求最小a值,再查映射表转换即可。i号点能到达的点中的最小a值,这是一个经典的DAG上dp问题,记忆化搜索也可做,不再赘述。

这里用拓扑排序做。首先要把图反向,于是问题转化为:求能到i点的所有点的最小a值。在遍历出边的时候进行dp更新即可。

三、代码实现

"use strict";

var loudAndRich = function(e, a) {
  const n = a.length
  let G = Array.from({length: n}, () => [])
  let ideg = Array(n).fill(0)
  for (let [u, v] of e) G[u].push(v), ideg[v]++
  let q = []
  for (let i = 0; i < n; ++i) if (!ideg[i]) q.push(i)
  let dp = a.slice()
  while (q.length) {
    let u = q.shift()
    for (let v of G[u]) {
      dp[v] = Math.min(dp[v], dp[u])
      if (!(--ideg[v])) q.push(v)
    }
  }
  let mp = a.reduce((mp, v, i) => {
    mp[v] = i
    return mp
  }, Array(n))
  return dp.map(v => mp[v])
};


四、总结

以上就是本道题的所有内容了,本系列会持续更,欢迎点赞、关注、收藏,另外如有其他的问题,欢迎下方留言给我,我会第一时间回复你,感谢~