首页 > 其他分享 >图解LeetCode——886. 可能的二分法(难度:中等)

图解LeetCode——886. 可能的二分法(难度:中等)

时间:2023-05-23 11:01:31浏览次数:31  
标签:遍历 matrix record int dislikes 二分法 item LeetCode 886


一、题目

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

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

二、示例

2.1> 示例 1:

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

2.2> 示例 2:

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

2.3> 示例 3:

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

提示:

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

三、解题思路

首先,创建一个二维数组,用来记录1到n个数之间的互斥关系。我们以n = 10,dislikes = [[1,2],[3,4],[5,6],[6,7],[8,9],[7,8]]为例,那么我们就可以得出如下矩阵图,如下图所示:

图解LeetCode——886. 可能的二分法(难度:中等)_i++

然后我们从第1行(row1)开始遍历,如果发现有“红色”,即表示发生了排斥,那么我们在对其进行深度遍历,如下图所示,我们遍历第1行的时候,发现2与其排斥,那么我们深度遍历第2行,由于第二行中没有与2排斥的数字了,所以我们得出结论,即:1在a组2在b组

我们继续遍历其他行,由于2已经被分配给了b组,所以第2行(row2)不遍历。

我们遍历第3行,由于发现与4发生了排斥,那么深度遍历到第4行,发现没有其他数组与4发生排斥,所以我们得出结论,即:3在a组4在b组

由于4已经被分配给了b组,所以第4行(row4)不遍历。我们遍历到第5行,发生如下遍历情况:

row5发现数字6与它发生排斥,深度遍历到row6row6发现数字7与它发生排斥,深度遍历到row7row7发现数字8与它发生排斥,深度遍历到row8row8发现数字9与它发生排斥,深度遍历到row9row9发现没有数字与其排斥,所得得出分组结论:即:5在a组6在b组7在a组8在b组9在a组

最终结论就是,a组里有[1,3,5,7,9]b组里有[2,4,6,8] ,具体详情请见下图:

图解LeetCode——886. 可能的二分法(难度:中等)_深度遍历_02

四、代码实现

4.1> 以二维数组方式实现矩阵

class Solution {
    public boolean possibleBipartition(int n, int[][] dislikes) {
        int[][] matrix = new int[n + 1][n + 1];
        for (int[] item : dislikes)
            matrix[item[0]][item[1]] = matrix[item[1]][item[0]] = 1;
        int[] record = new int[n + 1]; // 记录分组情况
        for (int i = 1; i <= n ; i ++)
            if (record[i] == 0 && ! dfs(matrix, record, i, 1, n)) return false;
        return true;
    }

    private boolean dfs(int[][] matrix, int[] record, int index,int group, int n) {
        record[index] = group;
        for (int i = 1; i <= n ; i++) {
            if(i == index || matrix[index][i] == 0) continue;
            if (record[i] == group) return false;
            if (record[i] == 0 && !dfs(matrix, record, i, group * -1, n)) return false;
        }
        return true;
    }
}

4.2> 以List方式进行改造

class Solution {
    public boolean possibleBipartition(int n, int[][] dislikes) {
        List<Integer>[] matrix = new ArrayList[n + 1];
        for (int i = 1; i < matrix.length; i++) matrix[i] = new ArrayList(n + 1);
        for (int[] item : dislikes) {
            matrix[item[0]].add(item[1]);
            matrix[item[1]].add(item[0]);
        }
        int[] record = new int[n + 1]; // 记录分组情况
        for (int i = 1; i < matrix.length ; i ++)
            if (record[i] == 0 && !dfs(matrix, record, i, 1)) return false;
        return true;
    }

    private boolean dfs(List<Integer>[] matrix, int[] record, int index, int group) {
        record[index] = group;
        for (int i = 0; i < matrix[index].size() ; i++) {
            int num = matrix[index].get(i);
            if (record[num] == group) return false;
            if (record[num] == 0 && !dfs(matrix, record, num, group * -1)) return false;
        }
        return true;
    }
}

今天的文章内容就这些了:

写作不易,笔者几个小时甚至数天完成的一篇文章,只愿换来您几秒钟的 点赞 & 分享

更多技术干货,欢迎大家关注公众号“爪哇缪斯” ~ \(^o^)/ ~ 「干货分享,每天更新」

标签:遍历,matrix,record,int,dislikes,二分法,item,LeetCode,886
From: https://blog.51cto.com/u_15003301/6330129

相关文章

  • 图解LeetCode——827. 最大人工岛(难度:困难)
    给你一个大小为nxn二进制矩阵grid。最多只能将一格 0变成 1。返回执行此操作后,grid中最大的岛屿面积是多少?岛屿由一组上、下、左、右四个方向相连的 1形成。二、示例2.1>示例1:【输入】grid=[[1,0],[0,1]]【输出】3【解释】将一格0变成1,最终连通两个小......
  • 图解LeetCode——904. 水果成篮(难度:中等)
    一、题目你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组fruits表示,其中fruits[i]是第i棵树上的水果种类。你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:你只有两个篮子,并且每个篮子只能装单一类型的水果......
  • #yyds干货盘点# LeetCode程序员面试金典:平衡二叉树
    题目:给定一个二叉树,判断它是否是高度平衡的二叉树。本题中,一棵高度平衡二叉树定义为:一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。 示例1:输入:root=[3,9,20,null,null,15,7]输出:true示例2:输入:root=[1,2,2,3,3,null,null,4,4]输出:false示例3:输入:root=[]......
  • #yyds干货盘点# LeetCode程序员面试金典:分数到小数
    1.简述:给定两个整数,分别表示分数的分子 numerator和分母denominator,以字符串形式返回小数。如果小数部分为循环小数,则将循环的部分括在括号内。如果存在多个答案,只需返回任意一个。对于所有给定的输入,保证答案字符串的长度小于104。 示例1:输入:numerator=1,denominat......
  • 二分法
    【二】二分法二分法查找,也称为折半法,是一种在有序数组中查找特定元素的搜索算法。二分法查找的思路如下:(1)首先,从数组的中间元素开始搜索,如果该元素正好是目标元素,则搜索过程结束,否则执行下一步。(2)如果目标元素大于/小于中间元素,则在数组大于/小于中间元素的那一半区域......
  • LeetCode 103. 二叉树的锯齿形层次遍历
    classSolution{public:vector<vector<int>>res;voidbfs(TreeNode*root){queue<TreeNode*>q;q.push(root);intcnt=0;while(!q.empty()){vector<int>level;......
  • LeetCode 周赛 346(2023/05/21)仅 68 人 AK 的最短路问题
    本文已收录到AndroidFamily,技术和职场问题,请关注公众号[彭旭锐]提问。LeetCode单周赛第345场·体验一题多解的算法之美单周赛345概览T1.删除子串后的字符串最小长度(Easy)标签:栈T2.字典序最小回文串(Medium)标签:贪心、双指针T3.求一个整数的惩罚数(Medium)标签......
  • leetcode724
    使用数学方法:假设左边的所有数加起来的和是sum,total为数组所有元素加起来的和,当i满足中心下标的条件时,即:sum=total-sum-nums[i];2*sum+nums[i]=total;当中心下标是首位时,即左边sum为0;当中心下标是尾位时,右边total-sum-nums[i]为0;for(inti=0;i<n;++i){if(2*sum+nums[i]==......
  • 图解LeetCode——19. 删除链表的倒数第 N 个结点
    一、题目给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。二、示例2.1>示例1:【输入】head=[1,2,3,4,5],n=2【输出】[1,2,3,5]2.2>示例2:【输入】head=[1],n=1【输出】[]2.3>示例3:【输入】head=[1,2],n=1【输出】[1]提示:链......
  • #yyds干货盘点# LeetCode程序员面试金典:有序链表转换二叉搜索树
    题目:给定一个单链表的头节点 head ,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树。本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差不超过1。 示例1:输入:head=[-10,-3,0,5,9]输出:[0,-3,9,-10,null,5]解释:一个可能的答案是[0,-3,9,-1......