Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions arai60/combination_sum/phase1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from typing import List

class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
# 再帰でも解けそうな気がするが, ひとまず単純な探索で解く

stack = [[[], 0, target]] # [current_combination, current_candidate_index, current_target]
combinations = []
while stack:
current_combination, current_candidate_index, current_target = stack.pop()

if current_target == 0 and current_combination not in combinations:
combinations.append(current_combination)
continue

if current_target - candidates[current_candidate_index] >= 0:
tmp_current_combination = current_combination.copy() # copy
tmp_current_combination.append(candidates[current_candidate_index])
stack.append([tmp_current_combination, current_candidate_index, current_target - candidates[current_candidate_index]])

if current_candidate_index + 1 < len(candidates) and current_target - candidates[current_candidate_index+1] >= 0:
tmp_current_combination = current_combination.copy() # copy
tmp_current_combination.append(candidates[current_candidate_index+1])
stack.append([tmp_current_combination, current_candidate_index+1, current_target - candidates[current_candidate_index+1]])

if current_candidate_index + 1 < len(candidates):
tmp_current_combination = current_combination.copy() # copy
stack.append([tmp_current_combination, current_candidate_index+1, current_target])

return combinations
66 changes: 66 additions & 0 deletions arai60/combination_sum/phase2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"""
Reference
hayashi-ay: https://github.com/hayashi-ay/leetcode/pull/65/files
shining-ai: https://github.com/shining-ai/leetcode/pull/52/files
phase1の方法だと重複する場合が出てきた分だけ状態数も増えていることに気づいた。
indexを増やすか今のindexが指す値を足すかで場合分けすれば十分であることがわかった。
あと現在の足し込んだ値がtargetより大きいかで判断した方が多分素直な実装ですね(phase1でcurrent_target - candidates[current_candidate_index] >= 0と書いていた)

あとは,
make_combination(index + 1, current_sum)
partial_combination.append(candidates[index])
make_combination(index, current_sum + candidates[index])
partial_combination.pop()
のような再帰を考えたことはなかったですね, これで再帰関数の引数から現在のcombinationを入れなくて済むんですね

Mike0121: https://github.com/Mike0121/LeetCode/pull/1/files
時間計算量が分割数というらしい
"""

# 再帰, whileの2通りで書く
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
combinations = []
stack = [[[], 0, 0]] # current_combination, current_index, current_value
while stack:
current_combination, current_index, current_value = stack.pop()
if current_value == target:
combinations.append(current_combination)
continue

if current_value > target:
continue

if current_index >= len(candidates):
continue

stack.append([current_combination, current_index + 1, current_value])
added_current_combination = current_combination.copy()
added_current_combination.append(candidates[current_index])
stack.append([added_current_combination, current_index, current_value + candidates[current_index]])

return combinations

# 再帰
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
combinations = []
partial_combination = []
def make_combinations(index: int, total: int) -> None:
if total == target:
combinations.append(partial_combination.copy())
return

if total > target:
return

if index >= len(candidates):
return

make_combinations(index + 1, total)
partial_combination.append(candidates[index])
make_combinations(index, total + candidates[index])
partial_combination.pop()

make_combinations(0, 0)
return combinations
23 changes: 23 additions & 0 deletions arai60/combination_sum/phase3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
# 書くのが安定しているwhileで書く
combinations = []
stack = [[[], 0, 0]] # current_combination, current_index, current_value
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

私は長さが固定のときには tuple にしますね。

while stack:
current_combination, current_index, current_value = stack.pop()
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

current にほとんど情報がなく、むしろ擬態しているように見えます。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

つまり, どういうことでしょうか?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://discord.com/channels/1084280443945353267/1225849404037009609/1232382815849414656

あたりでも話しているんですが、とにかく名前の付け方に抵抗感があります。
伝える意図が感じられません。
普段一文字で書いているのを、形式的に長くしたように感じています。

if current_value == target:
combinations.append(current_combination)
continue

if current_value > target:
continue

if current_index >= len(candidates):
continue

stack.append([current_combination, current_index + 1, current_value])
added_current_combination = current_combination.copy()
added_current_combination.append(candidates[current_index])
stack.append([added_current_combination, current_index, current_value + candidates[current_index]])

return combinations
20 changes: 20 additions & 0 deletions arai60/combination_sum/phase4.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
combinations_of_sum_equals_target: List[List[int]] = [] # You will get the value of the target when all the elements of combinations are added together.
stack = [([], 0, 0)]
while stack:
combinations_so_far, index_to_append, sum_so_far = stack.pop()
# sum(combinations_so_far) == sum_so_far
if sum_so_far == target:
combinations_of_sum_equals_target.append(combinations_so_far)
continue
if sum_so_far > target:
continue
if index_to_append >= len(candidates):
continue

stack.append((combinations_so_far, index_to_append + 1, sum_so_far))
append_value = candidates[index_to_append]
stack.append((combinations_so_far + [append_value], index_to_append, sum_so_far + append_value))

return combinations_of_sum_equals_target