力扣题目链接: 886: 可能的二分法
问题分析:
1. 题目要求: 将 1 到 n 的正整数, 分成两组, 两个组中包含的数字长度不做限制; 但是列表dislikes中的每一组数字不能分到同一组;如果可以实现, 那就返回 True, 否则返回 False.
2. 关键点: dislikes中的所有数组是否都可以满足不分到同一组, 判断是否有冲突的情况.另外注意, 不包含在dislikes中的数字, 不会存在冲突的可能, 分到任何一组都可以, 因此可以不必考虑.
3. 具体逻辑:
a. 将dislikes中的不能分在一组的数字以dict的形式先都存储起来
b. 单独创建一个字典, 用来存储dislikes中的数字的分组标记, 比如分成A,B两组, 一组用1表示, 一组用-1表示(红蓝染色)
c. 先取dislikes中的一个数字, 对其赋值为1, 然后将与其`冲突`的数字 置为-1
d. 采用深度搜索(depth first search)的方式, 遍历所有的 dislikes中的数字
e. 判断有没有冲突, 即一个数字既要是1, 又要是-1
f. 如果有冲突, 那就返回False, 没有冲突, 返回True
完整代码及解释:
class Solution:
def possibleBipartition(self, n: int, dislikes) -> bool:
disNumDict = dict()
for i, j in dislikes:
if disNumDict.get(i):
disNumDict[i].add(j)
else:
disNumDict[i] = {j}
if disNumDict.get(j):
disNumDict[j].add(i)
else:
disNumDict[j] = {i}
render_dict = {k_num: 0 for k_num in disNumDict}
def dfs(disA, render_color):
render_dict[disA] = render_color
for disB in disNumDict[disA]:
if not render_dict[disB]:
# 当有冲突时才需要退出; 如果直接 使用 return dfs(disB, -render_color), 会导致当返回结果为True时, 会跳过部分数字的情况, 需要注意
if not dfs(disB, -render_color):
return False
else:
if render_dict[disB] == render_color:
return False
return True
for disA in disNumDict:
if not render_dict[disA]:
if not dfs(disA, 1):
return False
return True
此外, 也可以像力扣的官方题解一样, 使用 一行流, 将dfs方法进行替换
class Solution:
def possibleBipartition(self, n: int, dislikes) -> bool:
disNumDict = dict()
for i, j in dislikes:
if disNumDict.get(i):
disNumDict[i].add(j)
else:
disNumDict[i] = {j}
if disNumDict.get(j):
disNumDict[j].add(i)
else:
disNumDict[j] = {i}
render_dict = {k_num: 0 for k_num in disNumDict}
def dfs(disA, render_color):
render_dict[disA] = render_color
return all(render_dict[disB] != render_color and (render_dict[disB] or dfs(disB, -render_color)) for disB in disNumDict[disA])
return all([dfs(disA, 1) for disA in disNumDict if not render_dict[disA]])