[路飞]_leetcode第277场周赛总结(下)

183 阅读2分钟

「这是我参与2022首次更文挑战的第6天,活动详情查看:2022首次更文挑战

5992. 基于陈述统计最多好人数

题目

游戏中存在两种角色:

  • 好人:该角色只说真话。

  • 坏人:该角色可能说真话,也可能说假话。 给你一个下标从 0 开始的二维整数数组 statements ,大小为 n x n ,表示 n 个玩家对彼此角色的陈述。具体来说,statements[i][j] 可以是下述值之一:

  • 0 表示 i 的陈述认为 j 是 坏人 。

  • 1 表示 i 的陈述认为 j 是 好人 。

  • 2 表示 i 没有对 j 作出陈述。 另外,玩家不会对自己进行陈述。形式上,对所有 0 <= i < n ,都有 statements[i][i] = 2 。

根据这 n 个玩家的陈述,返回可以认为是 好人 的 最大 数目。

示例

image.png

输入:statements = [[2,1,2],[1,2,2],[2,0,2]]
输出:2
解释:每个人都做一条陈述。
- 0 认为 1 是好人。
- 1 认为 0 是好人。
- 2 认为 1 是坏人。
以 2 为突破点。
- 假设 2 是一个好人:
    - 基于 2 的陈述,1 是坏人。
    - 那么可以确认 1 是坏人,2 是好人。
    - 基于 1 的陈述,由于 1 是坏人,那么他在陈述时可能:
        - 说真话。在这种情况下会出现矛盾,所以假设无效。
        - 说假话。在这种情况下,0 也是坏人并且在陈述时说假话。
    - 在认为 2 是好人的情况下,这组玩家中只有一个好人。
- 假设 2 是一个坏人:
    - 基于 2 的陈述,由于 2 是坏人,那么他在陈述时可能:
        - 说真话。在这种情况下,0 和 1 都是坏人。
            - 在认为 2 是坏人但说真话的情况下,这组玩家中没有一个好人。
        - 说假话。在这种情况下,1 是好人。
            - 由于 1 是好人,0 也是好人。
            - 在认为 2 是坏人且说假话的情况下,这组玩家中有两个好人。
在最佳情况下,至多有两个好人,所以返回 2 。
注意,能得到此结论的方法不止一种。

引言

真的是被题目给难倒了,这是啥?连示例都比别的题目场。这些重要吗?不重要!重要的是,我不懂啊。懵懵的。一个二维数组,每个二维数组节点又有一个状态【陈述】,此处姑且理解为一种状态。找到有多少好人。一看数据量最大15个人;得,这题肯定是O(2n)O(2^n)复杂度的题;竞赛期间就想这么多

题解

假设数组statements = [[2,1,2],[1,2,2],[2,0,2]];

有3个人,假设0表示坏人,1表示好人,可以有多少中组合;

可能的组合共(232^3)8种['000','100','110','010','101','001','011','111'];

最复杂的可能性就是枚举这8种可能;如果其中一个组合符合statements数组中每个人的一条陈述,将这种组合存在的好人数量保存。找打符合条件的好人数量最大值即可

这么说我还要构建一个全排列的二进制??

不用不用,8种组合字符串(000 100 010 110 001 101 011 111)可以通过位运算得到 ;

位运算得到全排列二进制字符串代码

const n = 3
let string = ''
for (let i = 0; i < Math.pow(2, n); i++) {
  for (let j = 0; j < n; j++) {
    const s = (i >> j) & 1
    string += s
  }
}

枚举8种可能,000可以忽略,因为坏人说的话,没有参考意义,可以说真话可以说假话。那另一个人可能是好人,也可能是坏人。所以意义不大,以好人为切入点,他们说的话都是真话,真话如果产生矛盾,这种组合不符合每个人的陈述。

对可能100分析

  • 忽略自己对自己的评价
  • 1是好人,根据statements数组中的陈述,1说2是好人,3是坏人;
  • 但是在100中只有1是好人,与陈述矛盾,所以100不是一种合理的结论 对可能010分析
  • 忽略自己对自己的评价
  • 2是好人,根据statements数组中的陈述,2说1是好人,3是坏人;
  • 但是在010这种可能中只有2是好人,与陈述矛盾,所以010不是一种合理的结论 对可能110分析
  • 忽略自己对自己的评价
  • 2是好人,根据statements数组中的陈述,2说1是好人,3是坏人;
  • 在110这种可能中1是好人,3是坏人,符合statements数组陈述,所以这种可能下有2个好人 ...

计算出全部232^3种可能,得到最大可能的好人数即可

根据上述分析思路编辑代码如下

代码

var maximumGood = function (statements) {
  let result = 0
  const len = statements.length
  const end = 1 << len
  for (let i = 0; i < end; i++) {
    let sign = true
    for (let j = 0; j < len; j++) {
      const t = i >> j
      if (t & 1) {
        for (let k = 0; k < statements[j].length; k++) {
          if (statements[j][k] === 2) continue
          if (
            (statements[j][k] == 1 && ((i >> k) & 1) == 0) ||
            (statements[j][k] == 0 && ((i >> k) & 1) == 1)
          ) {
            sign = false
            break
          }
        }
      }
    }
    let max = 0
    if (sign) {
      for (let j = 0; j < len; j++) {
        if (i & (1 << j)) max += 1
      }

      result = Math.max(result, max)
    }
  }

  return result
}