LeetCodeに挑戦:Weekly Contest 172
Weekly Contest 172 に挑戦しました。
https://leetcode.com/contest/weekly-contest-172
今回の出題は、以下の通りでした。
1323. Maximum 69 Number(Difficulty: Easy)
1324. Print Words Vertically(Difficulty: Medium)
1325. Delete Leaves With a Given Value(Difficulty: Medium)
1326. Minimum Number of Taps to Open to Water a Garden(Difficulty: Hard)
以下に問題の概要と、解答例を紹介します。
1323. Maximum 69 Number
(問題)6 と 9 のみで構成される、正の整数 ( num ) が与えられる。最大1桁の変更で、得られる最大値を返せ。
(例)Input: num = 9669
Output: 9969
(考え方) とにかく大きな数字になれば良いので、桁が上のところから探索して、6 があれば 9に変更すれば良い。
(コーディング)私は、forループを使って地道に検索して、6を探しましたが、Discuss内で見つけたエレガントなコードを以下に記述します。
def maximum69Number(self, num):
return int(str(num).replace('6', '9', 1))
replace( ) を使えば、3つ目の引数を 1 として与えれば、上から1つ目だけ置換できるんですね。。
1324. Print Words Vertically
(問題)ある文字列 (s) が与えられる。文字列内のすべての単語を、s に現れるのと同じ順序で垂直に返しなさい。また、単語は文字列のリストとして返され、必要に応じてスペースが追加されます。ただし、末尾のスペースは使用できません。各単語は1つの列にのみ配置され、1つの列には1つの単語しかありません。
(例)Input: s = “TO BE OR NOT TO BE”
Output: [“TBONTB”,”OEROOE”,” T”]
(コーディング)各単語の長さが違う事がキモで、短い単語はスペースで保管をしなくてはなりません。さらに、末尾にスペースがあってはいけないという制約があるので、そこにも処理が必要です。こちらも、Discuss内で見つけた、きれいなコードを参考に以下に記述します。
def printVertically(self, s):
words = s.split() #文字列 s を単語単位でリストwordsに格納
maxlen = max(len(w) for w in words) #単語の中の最長の長さを取得
res = [""] * maxlen #答えを格納するリストの初期化(最長の単語の長さと同じ要素数になる)
for i in range(maxlen):
for w in words:
res[i] += ' ' if i >= len(w) else w[i] #最長のものより短い単語の場合はスペースで保管
res[i] = res[i].rstrip() #関数rstrip( ) で右側のスペースを除去
return res
1325. Delete Leaves With a Given Value
(問題)2分木(root) と ある整数(target)が与えられる。root の リーフが targetである場合、そのリーフを削除した root を返せ。ただし、リーフを削除した結果、親ノードがリーフになった場合、そのリーフが targetであれば削除しなくてはならない。(問題)2分木(root) と ある整数(target)が与えられる。root の リーフが targetである場合、そのリーフを削除した root を返せ。ただし、リーフを削除した結果、親ノードがリーフになった場合、そのリーフが targetであれば削除しなくてはならない。
(コーデイング)深さ優先探索で解ける問題です。
class Solution:
def removeLeafNodes(self, root: TreeNode, target: int) -> TreeNode:
self.dfs(root, target, cnt)
if root.val == target and not(root.left or root.right):
return None
return root
def dfs(self, root, target, cnt):
#もうnodeはない
if not root:
return False
#左側のリーフの探索
is_left = self.dfs(root.left, target, cnt)
if is_left:
root.left = None
#右側のリーフの探索
is_right = self.dfs(root.right, target, cnt)
if is_right:
root.right = None
#リーフの値がtargetだった場合
if root.val == target and not(root.left or root.right):
return True
else:
return False
1326. Minimum Number of Taps to Open to Water a Garden
(問題)0から始まり n で終わる 1次元の庭がり、庭のポイント [0, 1, …, n] に合計 n + 1 個のタップがある。整数 nと、長さn + 1の整数の配列 ranges が与えられ、ranges[ i ] は、i 番目のタップが領域 [ i – range [ i ]、i + range [ i ] ]の範囲に散水できることを意味する。庭全体に水をまくために必要なタップの最小数を返せ。庭に水をまくことができない場合は、-1を返せ。
(コーデイング)(1) 各要素が1回で到達できる最も遠いインデックスを表すように、ranges を変更します。 (2) 到達するために必要な最小限の個数を見つけます。
class Solution:
def minTaps(self, n: int, ranges: List[int]) -> int:
# (1)
for i,r in enumerate(ranges): # i はindex, r はranges[i]
l = max(0,i-r)
ranges[l] = max(i+r, ranges[l])
# (2)
res = lo = hi = 0
while hi < n:
lo, hi = hi, max(ranges[lo:hi+1])
if hi == lo: return -1
res += 1
return res
最後に、今回私は1323, 1324の2つをAcceptedにできました。その結果 rating は 1417 –> 1427 と +10となりました。。