Skip to main content

๐Ÿš€ 886. Possible Bipartition

Possible Bipartition - LeetCode

Input: n = 4, dislikes = [[1,2],[1,3],[2,4]]
Output: true
Explanation: group1 [1,4] and group2 [2,3].

๋ฌธ์ œ๋ฅผ ๋ณด๋ฉด ๋ฆฌ์ŠคํŠธ๊ฐ€ ์ฃผ์–ด์ง€๊ณ  ํ•จ๊ป˜ ์žˆ์„ ์ˆ˜ ์—†๋Š” ์ˆซ์ž๋“ค์ด 2์ฐจ์› ๋ฐฐ์—ด๋กœ ์ฃผ์–ด์ง„๋‹ค.

1์€ 2์™€ 3๊ณผ ํ•จ๊ป˜ ํ•  ์ˆ˜ ์—†๊ณ 

2๋Š” 1๊ณผ 4์™€ ํ•จ๊ป˜ ์žˆ์„ ์ˆ˜ ์—†๋‹ค

์ฃผ์–ด์ง€๋Š” n๊ฐœ์˜ ์ˆ˜๋ฅผ ์œ„์— ์ฃผ์–ด์ง€๋Š” ๋ฆฌ์ŠคํŠธ์— ์ฐธ๊ณ ํ•ด์„œ ๋‘ ๊ทธ๋ฃน์œผ๋กœ ๋‚˜๋ˆ ์•ผ ํ•œ๋‹ค.

๋งŒ์•ฝ์— ๋‘๊ทธ๋ฃน์œผ๋กœ ๋‚˜๋ˆ ์–ด์ง€๋ฉด True ๋‚˜๋ˆ„์ง€ ๋ชปํ•˜๋ฉด False์ด๋‹ค.


โ†’ ํ•ด๊ฒฐ๋ฐฉ๋ฒ•์„ ์ฒ˜์Œ ์ƒ๊ฐํ•ด๋ณด๋ฉด

์ผ๋‹จ ๊ฐ ์ˆซ์ž๋“ค์ด ์–ด๋–ค ์ˆซ์ž์™€ ํ•จ๊ป˜ ํ•  ์ˆ˜ ์—†๋Š”์ง€๋ฅผ ๋”•์…”๋„ˆ๋ฆฌ ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์ด์šฉํ•ด์„œ ์ •๋ฆฌํ–ˆ๋‹ค.

์ด์ œ ์ด๊ฑธ ๋ฐฐ์น˜ํ•ด์•ผ ํ•˜๋Š”๋ฐ dictionary์—์„œ for๋ฌธ์„ ๋Œ๋ฉด์„œ ์ค‘๋ณต๋˜๋Š”๊ฒŒ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ–ˆ๋‹ค.

from typing import List

class Solution:
def possibleBipartition(self, n: int, dislikes: List[List[int]]) -> bool:
dislike_dic = {}
for dislike in dislikes:
item1 = dislike[0]
item2 = dislike[1]
if item1 in dislike_dic:
dislike_dic[item1].append(item2)
else:
dislike_dic[item1] = [item2]

if item2 in dislike_dic:
dislike_dic[item2].append(item1)
else:
dislike_dic[item2] = [item1]
  • Code(์ž˜๋ชป๋œ ์ฝ”๋“œ์ž„)

    				
    group1 = set()
    group2 = set()
    for i in range(1, n + 1):
    group_name = None
    lst_dislike = []
    if i in dislike_dic:
    lst_dislike = dislike_dic[i]
    group_name = ''
    for dislike in lst_dislike:
    if dislike in group1:
    if dislike in group2:
    return False
    if group_name == '':
    group_name = 'group2'
    elif group_name != 'group2':
    # could this element be in group2?
    if not self.could_be_in_another_group(dislike_dic, dislike, group2, group1):
    return False
    group_name = 'group2'
    elif dislike in group2:
    if dislike in group1:
    return False
    if group_name == '':
    group_name = 'group1'
    elif group_name != 'group1':
    if not self.could_be_in_another_group(dislike_dic, dislike, group1, group2):
    return False
    group_name = 'group1'
    if group_name == '' or group_name == 'group1':
    group1.add(i)
    else:
    group2.add(i)
    return True

    def could_be_in_another_group(self, dislike_dic, dislike, from_group, to_group):
    if dislike in dislike_dic:
    lst_dislike = dislike_dic[dislike]
    for dislike2 in lst_dislike:
    if dislike2 in from_group:
    if self.could_be_in_another_group(dislike_dic, dislike2, from_group, to_group):
    from_group.remove(dislike2)
    to_group.add(dislike2)
    else:
    return False
    return True

๋ณด๋ฉด ์•Œ๊ฒ ์ง€๋งŒ ๋ณ„ ๋‚œ๋ฆฌ๋ฅผ ๋‹ค ๋ถ€๋ ธ๋‹ค.

์ฝ”๋“œ๊ฐ€ ๋„ˆ๋ฌด ์ง€์ €๋ถ„ํ•ด์„œ ๋ฆฌํŽ™ํ† ๋ง ํ•˜๋‹ค๊ฐ€

Chat GPT์—๊ฒŒ ๋ฆฌํŒฉํ† ๋ง์„ ๋ถ€ํƒํ•ด ๋ณด์•˜๋‹ค.

  • Code(์ž˜๋ชป๋œ ์ฝ”๋“œ ๋ฆฌํŒฉํ† ๋ง)

    			groups = [set(), set()]
    for i in range(1, n + 1):
    group_name = None
    lst_dislike = dislike_dic.get(i, [])
    group_name = ''
    for dislike in lst_dislike:
    group_index = None
    if dislike in groups[0]:
    group_index = 0
    elif dislike in groups[1]:
    group_index = 1
    if group_index is not None:
    if group_name == '':
    group_name = group_index
    elif group_name != group_index:
    if not self.could_be_in_another_group(dislike_dic, dislike, groups[group_index], groups[group_index ^ 1]):
    return False
    group_name = group_index
    if group_name == '':
    groups[0].add(i)
    elif group_name == 0:
    groups[0].add(i)
    else:
    groups[1].add(i)
    return True

    def could_be_in_another_group(self, dislike_dic, dislike, from_group, to_group):
    if dislike in dislike_dic:
    lst_dislike = dislike_dic[dislike]
    for dislike2 in lst_dislike:
    if dislike2 in from_group:
    if self.could_be_in_another_group(dislike_dic, dislike2, from_group, to_group):
    from_group.remove(dislike2)
    to_group.add(dislike2)
    else:
    return False
    return True

์˜ค~~~ ์ž˜ํ•œ๋‹ค ์ž˜ํ•ด

๊ฒฐ๋ก ์€ ? ํ•ด๊ฒฐ์•ˆ๋จ

๋ฌธ์ œ๋Š” dictionary์—์„œ for๋ฌธ์„ ๋Œ๋‹ค๊ฐ€ ์š”์†Œ ํ•˜๋‚˜๊ฐ€ 10์ด๋ผ๊ณ  ํ–ˆ์„๋•Œ ์–‘์ชฝ ๊ทธ๋ฃน์— ๋‹ค๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ์—

์ผ๋‹จ ํ•˜๋‚˜์˜ ๊ทธ๋ฃน์— ๋„ฃ์–ด๋‘๋ฉด ๋’ค์— 22์ฏค ์™”์„๋•Œ ์ผ๋‹จ ํ•˜๋‚˜์˜ ๊ทธ๋ฃน์— ๋„ฃ์–ด๋‘” 10์ด ๋ฌธ์ œ๊ฐ€ ๋˜๊ณ 

๊ทธ๋Ÿผ 10์„ ๋‹ค์‹œ ํ™•์ธํ•ด์„œ ๋‹ค๋ฅธ ๊ทธ๋ฃน์— ๋„ฃ์–ด์•ผ ํ•˜๋Š”๋ฐ ๋„ฃ๋Š”๋‹ค๊ณ  ๋‹ค๊ฐ€ ์•„๋‹ˆ๋ผ 1~22๋ฒˆ๊นŒ์ง€ ๋‹ค์‹œ ํ™•์ธํ•ด์•ผ ํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒผ๋‹ค.

๋ชปํ’€์—ˆ๋‹ค GG ๐Ÿ˜ญ

ai์—๊ฒŒ ๋ฌผ์–ด๋ณด๋‹ˆ ๋‹ต์„ ์•Œ๋ ค์ฃผ๋Š”๋ฐ ํŠน์ • ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์žˆ๋‹จ๋‹คโ€ฆ

์ด๋Ÿฐ ํŠน์ • ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๊ณต๋ถ€ํ•ด์•ผ ํ•˜๋Š”๊ฐ€???

๊ทธ๋Ÿผ ์ด๊ฑด ์ข€ ์ œ์™ธํ•˜๊ณ 


๋‹ค์‹œ ์ฒ˜์Œ๋ถ€ํ„ฐ ์ƒ๊ฐํ•˜๊ธฐ๋กœโ€ฆ

(์ด๋ฒˆ ๋ฌธ์ œ๋Š” ์–ด๋ ต๋‹ค ใ… .ใ… )

์ธ์ˆ˜๊ฐ€ ์ด๋ ‡๊ฒŒ ์ฃผ์–ด์กŒ์„ ๋•Œ

 Input: n = 4, dislikes = [[1,2],[1,3],[2,4]] 
  1. ๊ฐ ์ˆ˜๋ณ„๋กœ ์–ด๋–ค์ˆ˜์™€ ํ•จ๊ป˜ ํ•  ์ˆ˜ ์—†๋Š”์ง€ ํ™•์ธ
  2. ๊ฐ ๊ทธ๋ฃน๋ณ„๋กœ 1๊ณผ ํ•จ๊ป˜ ํ•  ์ˆ˜ ์—†๋Š” ์ˆ˜๊ฐ€ ์žˆ๋Š”์ง€ ๋จผ์ € ๊ฒ€์‚ฌ
  3. ํ˜„์žฌ group1 = [ ] group2 = [ ]
  4. ๋‘˜๋‹ค ๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด group1 = [ 1 ]
  5. ๋‹ค๋ฅธ ๊ทธ๋ฃน์— 1๊ณผ ํ•จ๊ป˜ ํ•  ์ˆ˜ ์—†๋Š” ์ˆ˜์ธ 2, 3์„ ๋ฐ˜๋“œ์‹œ ๋„ฃ์–ด์•ผํ•จ
  6. 2์™€ 3์ด ํ•จ๊ป˜ ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ๊ฒ€์‚ฌ
  7. 2์™€ ํ•จ๊ป˜ ํ•  ์ˆ˜ ์—†๋Š” ๋ฆฌ์ŠคํŠธ ๊ตฌํ•˜๊ธฐ
  8. 3๊ณผ ํ•จ๊ป˜ ํ•  ์ˆ˜ ์—†๋Š” ๋ฆฌ์ŠคํŠธ ๊ตฌํ•˜๊ธฐ
  9. ๊ฐ ๋ฆฌ์ŠคํŠธ๋“ค ํ•˜๋‚˜๋กœ ํ•ฉ์น˜๊ธฐ
  10. 2์™€ 3์ด ํ•ฉ์ณ์ง„ ๋ฆฌ์ŠคํŠธ ์•ˆ์— ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ
    1. ๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด 2์™€ 3์€ ํ•œ๋ฒˆ์— group2์— ๋“ค์–ด๊ฐ„๋‹ค.
  11. 2์™€ 3์ด ํ•ฉ์ณ์ง„ ๋ฆฌ์ŠคํŠธ ์•ˆ์— ์žˆ๋‹ค๋ฉด return False
  12. ๋ชจ๋“  for๋ฌธ์ด ๋‹ค ๋Œ์•„๊ฐ€๋ฉด ์ž๋™์œผ๋กœ return True

๊ฒฐ๊ณผ๋Š” ๊ธฐ์กด๋ณด๋‹ค ๋ชปํ•œ ๊ฒฐ๊ณผ๊ฐ€โ€ฆ.์” ๋˜ ํ‹€๋ฆผ

  • ์ฝ”๋“œ

    from typing import List

    class Solution:
    def possibleBipartition(self, n: int, dislikes: List[List[int]]) -> bool:
    dislike_dic = {}
    for dislike in dislikes:
    item1 = dislike[0]
    item2 = dislike[1]
    if item1 in dislike_dic:
    dislike_dic[item1].append(item2)
    else:
    dislike_dic[item1] = [item2]

    if item2 in dislike_dic:
    dislike_dic[item2].append(item1)
    else:
    dislike_dic[item2] = [item1]

    groups = [[], []]
    joined_element = set()
    for key in dislike_dic:
    if key in joined_element:
    continue
    else:
    joined_element.add(key)
    lst_dislike = dislike_dic.get(key, [])
    merge_set = set()
    for dislike in lst_dislike:
    items = dislike_dic.get(dislike, [])
    for item in items:
    merge_set.add(item)
    # ์ž๊ธฐ์ž์‹ ๋ถ€ํ„ฐ ๋จผ์ € ๊ฒ€์‚ฌ
    # dislike๋“ค์ด ํ•จ๊ป˜ ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ๋ถ€ํ„ฐ ๊ฒ€์‚ฌํ•จ
    for item in lst_dislike:
    if item in merge_set:
    return False
    joined_element.add(item)
    # ๋งŒ์•ฝ ํ•จ๊ป˜ ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์–ด๋А ๊ทธ๋ฃน์œผ๋กœ ๊ฐ€์•ผํ• ์ง€ ๊ฒ€์‚ฌ
    idx_group = 0
    for item in groups[0]:
    if item in merge_set:
    idx_group = 1
    break
    for item in groups[1]:
    if item in merge_set and idx_group == 1:
    return False
    groups[idx_group].append(key)
    # ์ƒ๋Œ€๋ฐฉ์ชฝ์— ์žˆ๋Š” ๊ฒƒ๋“ค์€ ์ œ์™ธํ•œ๋‹ค.
    for dislike in lst_dislike:
    if dislike not in groups[idx_group]:
    groups[idx_group ^ 1].append(dislike)
    return True

๋ช‡์ผ์„ ์งฌ์งฌ์ด ์ƒ๊ฐ๋‚ ๋•Œ๋งˆ๋‹ค ๊ณ ๋ฏผํ•ด๋ดค๋Š”๋ฐ ๊ฒฐ๊ตญ Recursive๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ’€ ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์•˜๋‹ค.

๊ฒฐ๊ตญ ์˜ค๋Š˜๋„ ์‹คํŒจํ•˜๊ณ โ€ฆ ์”

์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ๋„์›€์„ ์ข€ ๋ฐ›์•˜๋‹ค. ใ… .ใ… 

from typing import List

class Solution:
def possibleBipartition(self, n: int, dislikes: List[List[int]]) -> bool:
dislike_dic = {}
for dislike in dislikes:
item1 = dislike[0]
item2 = dislike[1]
if item1 in dislike_dic:
dislike_dic[item1].append(item2)
else:
dislike_dic[item1] = [item2]

if item2 in dislike_dic:
dislike_dic[item2].append(item1)
else:
dislike_dic[item2] = [item1]

groups = {}
for n in range(1, n+1):
color = groups.get(n, -1)
if color == -1:
groups[n] = 0
if not self.coloring(groups, dislike_dic, n, 0):
return False
return True

def coloring(self, groups: dict, dislike_dic: dict, n: int, color: int):
coloring = color ^ 1
lst_dislike = dislike_dic.get(n, [])
for i in lst_dislike:
i_color = groups.get(i, -1)
if i_color == -1:
groups[i] = coloring
self.coloring(groups, dislike_dic, i, coloring)
elif i_color != coloring:
return False
return True

ํ•ต์‹ฌ์ฝ”๋“œ๋Š”

self.coloring(groups, dislike_dic, i, coloring)

์ด๋ถ€๋ถ„์ด๋‹ค.

for๋ฌธ์„ ๋Œ๋ฆฌ๋ฉด์„œ 1๋ถ€ํ„ฐ n๊นŒ์ง€ ๋„๋Š”๋ฐ ๋‚ด๊ฐ€ ์„  coloringํ•œ ๋ถ€๋ถ„๊ณผ ์—ฐ๊ด€๋œ dislike๋Š” ์ „๋ถ€ coloring์ฒ˜๋ฆฌ ํ•ด์ค˜์•ผํ•˜๊ณ  ์ผ๋‹จ ๋‹ค coloring ๋˜๋ฉด ๋‹ค์Œ n์ธ 2๋ฅผ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

for๋ฌธ๊ณผ recursive๋ฅผ ๋™์‹œ์— ํ™œ์šฉํ•ด์„œ ํ•ด๊ฒฐํ•ด์•ผ ํ•˜๋Š” ๋ฌธ์ œ์ด๋‹ค.!!

copilot ์ฝ”๋“œ๋ฅผ ์ฐธ๊ณ ํ•ด์„œ ์ง  ์ฝ”๋“œ๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

class Solution:
def possibleBipartition(self, n: int, dislikes: List[List[int]]) -> bool:
lst_dislikes = [[] for _ in range(0, n+1)]
for a, b in dislikes:
lst_dislikes[a].append(b)
lst_dislikes[b].append(a)

colors = [-1 for _ in range(0, n+1)]
for n in range(1, n+1):
if colors[n] == -1 and not self.coloring(lst_dislikes, colors, n, 0):
return False
return True

def coloring(self, lst_dislikes: List[List[int]], colors:List[int], n: int, color: int):
if colors[n] != -1:
return colors[n] == color
colors[n] = color
for i in lst_dislikes[n]:
if not self.coloring(lst_dislikes, colors, i, color ^ 1):
return False
return True

ํ›จ์”ฌ ๊ฐ„๋‹จํ•˜๊ณ  ๋น ๋ฅด๋‹ค.

copilot์›๋ณธ์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

from typing import List

class Solution:
def possibleBipartition(self, n: int, dislikes: List[List[int]]) -> bool:
lst_dislikes = [[] for _ in range(n)]
for i, j in dislikes:
lst_dislikes[i - 1].append(j - 1)
lst_dislikes[j - 1].append(i - 1)

lst_color = [0] * n
for i in range(n):
if lst_color[i] == 0:
lst_color[i] = 1
if not self.dfs(lst_dislikes, lst_color, i):
return False
return True

def dfs(self, lst_dislikes, lst_color, i):
for j in lst_dislikes[i]:
if lst_color[j] == lst_color[i]:
return False
if lst_color[j] == 0:
lst_color[j] = -lst_color[i]
if not self.dfs(lst_dislikes, lst_color, j):
return False
return True