LeetCode探索(152):886-可能的二分法

123 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第17天,点击查看活动详情

题目

给定一组 n 人(编号为 1, 2, ..., n), 我们想把每个人分进任意大小的两组。每个人都可能不喜欢其他人,那么他们不应该属于同一组。

给定整数 n 和数组 dislikes ,其中 dislikes[i] = [ai, bi] ,表示不允许将编号为 aibi的人归入同一组。当可以用这种方法将所有人分进两组时,返回 true;否则返回 false

示例 1:

输入:n = 4, dislikes = [[1,2],[1,3],[2,4]]
输出:true
解释:group1 [1,4], group2 [2,3]

示例 2:

输入:n = 3, dislikes = [[1,2],[1,3],[2,3]]
输出:false

示例 3:

输入:n = 5, dislikes = [[1,2],[2,3],[3,4],[4,5],[1,5]]
输出:false

提示:

  • 1 <= n <= 2000
  • 0 <= dislikes.length <= 10^4
  • dislikes[i].length == 2
  • 1 <= dislikes[i][j] <= n
  • ai < bi
  • dislikes 中每一组都 不同

思考

本题难度中等。

首先是读懂题意。给定一组 n 人(编号为 1, 2, ..., n), 把每个人分进任意大小的两组。每个人都可能不喜欢其他人,那么他们不应该属于同一组。

一开始没有好的思路,后来参考题解,了解到可以使用染色法深度优先搜索进行解题。也就是:

定义数组 color,数组长度为 n。规定染成颜色 A 的数字满足 color[i] = 1,染成颜色 B 的数字满足 color[i] = 2,初始化 color[i] = 0,表示该数字尚未被染色。

定义二维数组 g,g[i] 表示对于数字 i 来说不喜欢的数字的集合。

遍历数组 dislikes,判断 数字 i 和 g[i] 中的元素是否会在同一组,如果分到同一组,则返回 false。

本题的时间复杂度和空间复杂度均为 O(n + m),其中 n 题目给定的人数,m 为给定的 dislike 数组的大小。

解答

方法一:染色法、深度优先搜索

/**
 * @param {number} n
 * @param {number[][]} dislikes
 * @return {boolean}
 */
var possibleBipartition = function(n, dislikes) {
  const dfs = (curnode, nowcolor, color, g) => {
    color[curnode] = nowcolor
    for (const nextnode of g[curnode]) {
      // nextnode 已经分组了,且和 curnode 是同一颜色
      if (color[nextnode] !== 0 && color[nextnode] === color[curnode]) {
        return false
      }
      // nextnode 未分组,nextnode 是另一种颜色(3^nowcolor)
      if (color[nextnode] === 0 && !dfs(nextnode, 3 ^ nowcolor, color, g)) {
        return false
      }
    }
    return true
  }
  // 数组 color,规定染成颜色 A 的数字满足 color[i] = 1,染成颜色 B 的数字满足 color[i] = 2,初始化 color[i] = 0 表示该数字尚未被染色。
  const color = new Array(n + 1).fill(0)
  // 二维数组
  const g = new Array(n + 1).fill(0).map(() => [])
  for (const p of dislikes) {
    g[p[0]].push(p[1])
    g[p[1]].push(p[0])
  }
  for (let i = 1; i <= n; ++i) {
    if (color[i] === 0 && !dfs(i, 1, color, g)) { // 默认颜色是1
      return false
    }
  }
  return true
}

复杂度分析:

  • 时间复杂度:O(n + m),其中 n 题目给定的人数,m 为给定的 dislike 数组的大小。
  • 空间复杂度:O(n + m),其中 n 题目给定的人数,m 为给定的 dislike 数组的大小。

参考