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
35 changes: 35 additions & 0 deletions grind75_hard/03_42_Trapping Rain Water/level_1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# brute force
# 現在地より左側の最大値が左の壁、右側の最大値が右の壁となる。
# 現在地の水位は、左右の壁の小さいほうになる。
# 現在地が壁より低ければ、水が貯まる。
# O(n^2)
class Solution:
def trap(self, height: List[int]) -> int:
total_water = 0
for i in range(1, len(height) - 1): # 両端には水が貯まらないので除外
left_wall = max(height[:i])
right_wall = max(height[i + 1 :])
water_height = min(left_wall, right_wall)
if water_height < height[i]:
continue
total_water += water_height - height[i]
return total_water


# stackを使って実装
# 左側の壁をstackで記憶し、右側の壁が見つかったら、貯まる水を計算する。
class Solution:
def trap(self, height: List[int]) -> int:
left_walls = []
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

変数名 left_walls ですと、中にどのような値が含まれているのか分かりませんでした。 left_wall_indexes 等、インデックスが含まれていることを表す変数名のほうが良いと思います。

total_water = 0
for right in range(len(height)):
while left_walls and height[left_walls[-1]] <= height[right]:
bottom_index = left_walls.pop()
if not left_walls:
break
left = left_walls[-1]
distance = right - left - 1
depth = min(height[left], height[right]) - height[bottom_index]
total_water += distance * depth
left_walls.append(right)
return total_water
16 changes: 16 additions & 0 deletions grind75_hard/03_42_Trapping Rain Water/level_2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# DPを使って解く
# brute forceと同じ考え方だが、左右の壁の最大値を記憶しておく
class Solution:
def trap(self, height: List[int]) -> int:
max_left = [0] * len(height) # [0,i]の範囲の最大値
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

max_left ですと、最大の左を表しているように感じられます。 max_heights_in_left あたりはいかがでしょうか?

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.

うまく命名できていないと思っていたので、ありがたいです。
前置詞をあまり使っていなかったので、勉強になります。

max_right = [0] * len(height) # [i,length)の範囲の最大値
max_left[0] = height[0]
max_right[-1] = height[-1]
for i in range(1, len(height)):
max_left[i] = max(max_left[i - 1], height[i])
max_right[-i - 1] = max(max_right[-i], height[-i - 1])
total_water = 0
for i in range(1, len(height) - 1):
water_height = min(max_left[i], max_right[i])
total_water += water_height - height[i]
return total_water
14 changes: 14 additions & 0 deletions grind75_hard/03_42_Trapping Rain Water/level_3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Solution:
def trap(self, height: List[int]) -> int:
max_left = [0] * len(height)
max_right = [0] * len(height)
max_left[0] = height[0]
max_right[-1] = height[-1]
for i in range(1, len(height)):
max_left[i] = max(max_left[i - 1], height[i])
max_right[-i - 1] = max(max_right[-i], height[-i - 1])
total_water = 0
for i in range(1, len(height) - 1):
water_height = min(max_left[i], max_right[i])
total_water += water_height - height[i]
return total_water
37 changes: 37 additions & 0 deletions grind75_hard/03_42_Trapping Rain Water/level_4.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# DPを使って解く
# 変数名を修正
# max_height_in_rightはmax_heights_in_leftとは別のループで構築する
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

max_height_in_rightmax_heights_in_leftの二つの変数名何か気になるところありませんか?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

max_height_in_rightとmax_heights_in_leftの二つの変数名何か気になるところありませんか?

これ、私が推奨した変数名ですね…。申し訳ないです…。

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.

right側だけheightが複数形になってませんでした。

Copy link
Copy Markdown

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.

height と heights の違い、見落としておりました。 nice catch です。

class Solution:
def trap(self, height: List[int]) -> int:
max_heights_in_left = [0] * len(height) # [0,i]の範囲の最大値
max_height_in_right = [0] * len(height) # [i,length)の範囲の最大値
max_heights_in_left[0] = height[0]
max_height_in_right[-1] = height[-1]
for i in range(1, len(height)):
max_heights_in_left[i] = max(max_heights_in_left[i - 1], height[i])
for i in range(len(height) - 2, -1, -1):
max_height_in_right[i] = max(max_height_in_right[i + 1], height[i])
total_water = 0
for i in range(1, len(height) - 1):
water_height = min(max_heights_in_left[i], max_height_in_right[i])
total_water += water_height - height[i]
return total_water


# stackを使って実装
# 変数名を修正
class Solution:
def trap(self, height: List[int]) -> int:
left_wall_indexes = []
total_water = 0
for right in range(len(height)):
while left_wall_indexes and height[left_wall_indexes[-1]] <= height[right]:
bottom_index = left_wall_indexes.pop()
if not left_wall_indexes:
break
left = left_wall_indexes[-1]
distance = right - left - 1
depth = min(height[left], height[right]) - height[bottom_index]
total_water += distance * depth
left_wall_indexes.append(right)
return total_water
39 changes: 39 additions & 0 deletions grind75_hard/03_42_Trapping Rain Water/level_5.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Space: O(1)
# 左右からポインタをずらしていく
# 片方のポインタは今までの最大値で止まるようにしておく
class Solution:
def trap(self, height: List[int]) -> int:
left_max = 0
right_max = 0
left = 0
right = len(height) - 1
total_water = 0
while left < right:
if height[left] < height[right]:
left_max = max(left_max, height[left])
total_water += left_max - height[left]
left += 1
else:
right_max = max(right_max, height[right])
total_water += right_max - height[right]
right -= 1
return total_water


# DPを使って解く
# 変数名を修正
class Solution:
def trap(self, height: List[int]) -> int:
max_heights_in_left = [0] * len(height) # [0,i]の範囲の最大値
max_heights_in_right = [0] * len(height) # [i,length)の範囲の最大値
max_heights_in_left[0] = height[0]
max_heights_in_right[-1] = height[-1]
for i in range(1, len(height)):
max_heights_in_left[i] = max(max_heights_in_left[i - 1], height[i])
for i in range(len(height) - 2, -1, -1):
max_heights_in_right[i] = max(max_heights_in_right[i + 1], height[i])
total_water = 0
for i in range(1, len(height) - 1):
water_height = min(max_heights_in_left[i], max_heights_in_right[i])
total_water += water_height - height[i]
return total_water