0.試合後のまとめ
今回は質問が3つ、ミスが2つだけでしたが、全体的には順調でしたが、過去2週間の結果を比較すると、比較的嬉しいことです。。。
しかし、今回はまだ幸運で、おそらく最後の質問がより難しいためです。今回は、中国で84/1631、世界で214/7837、中国でほぼ上位5%、上位3%がまだあります。世界。
しかし、今回の最も幸せなことは、最後の質問が以前ほど軽率ではないことです。それは可能です。少なくともアイデアがあり、それを実行したところ、最終的にタイムアウトが発生しました。80個のテストサンプルのうち77個が合格しました。 。最後の3つで行き詰まりましたが、最終的には大丈夫でした。ゲーム中に合計10人以上が最後の質問をしたことを考えると、これは非常に嬉しいことです。
しかし、最後の質問が行われていないか行われていないかにかかわらず、この問題を個別に解決してみてください。
2日で出せなかったのが残念です。。。
1.トピック1
質問1に与えられた質問へのリンクは次のとおりです。
1.問題解決のアイデア
この質問については何も言うことはありません。質問の意味に従って毎週解決してください。
2.コードの実装
Pythonコードは次のとおりです。
class Solution:
def totalMoney(self, n: int) -> int:
res = 0
for i in range(n):
res += (i // 7 + 1) + i % 7
return res
コード評価を送信して取得します。48ミリ秒かかり、14.3MBのメモリを消費します。
現在の最適解は36msかかりますが、本質的には違いはありません。興味のある読者は自分で見てみることができます。ここではこれ以上は行いません。
2.トピック2
トピック2のテスト問題へのリンクは次のとおりです。
1.問題解決のアイデア
あなたがそれを理解している限り、この問題を解決するという考えは実際には良いです:
- 欲張りアルゴリズムを使用して最初にすべての高スコア操作を実行しても、最終結果には影響しません。
したがって、我々はときにのみ、あること、動作するように貪欲なアルゴリズムを実装する必要がab
スコアが高くなってba
、ab
削除のすべてのそれらを、その後、すべてを削除しba
、最終的な最高のスコアを取得し、その逆も同様です。
2.コードの実装
Pythonコードは次のとおりです。
class Solution:
def maximumGain(self, s: str, x: int, y: int) -> int:
res = 0
if x <= y:
s1 = []
for c in s:
if c == "a" and s1 and s1[-1] == "b":
s1.pop()
else:
s1.append(c)
res += y * (len(s) - len(s1)) // 2
s2 = []
for c in s1:
if c == "b" and s2 and s2[-1] == "a":
s2.pop()
else:
s2.append(c)
res += x * (len(s1) - len(s2)) // 2
else:
s1 = []
for c in s:
if c == "b" and s1 and s1[-1] == "a":
s1.pop()
else:
s1.append(c)
res += x * (len(s) - len(s1)) // 2
s2 = []
for c in s1:
if c == "a" and s2 and s2[-1] == "b":
s2.pop()
else:
s2.append(c)
res += y * (len(s1) - len(s2)) // 2
return res
評価のためにコードを送信した後、332ミリ秒かかり、16.1MBのメモリを消費しました。
現在の最適解は296msかかります。大まかに見ても違いはないと思いますが、詳細は詳しくありません。興味のある方はご自身で勉強していただければと思います。コメントエリア。
3.トピック3
トピック3のテスト問題へのリンクは次のとおりです。
1.問題解決のアイデア
この質問では、深さ優先走査を使用できます。つまり、最初の位置から開始して、最初の塗りつぶしが完了するまで、塗りつぶされていない各位置で最大の塗りつぶし可能な値を最初に入力し、塗りつぶしの結果を返すことが、取得できる最大の結果になります。
2.コードの実装
Pythonコードは次のとおりです。
class Solution:
def constructDistancedSequence(self, n: int) -> List[int]:
res = [0 for _ in range(2*n-1)]
status = [0 for _ in range(n+1)]
def dfs(idx):
nonlocal res
if idx >= 2*n-1:
return True
for i in range(n, 0, -1):
if status[i] == 1:
continue
if i != 1 and idx + i < 2*n-1 and res[idx+i] == 0:
res[idx] = i
res[idx+i] = i
status[i] = 1
nxt_idx = res.index(0) if 0 in res else 2*n-1
success = dfs(nxt_idx)
if success:
return True
status[i] = 0
res[idx] = 0
res[idx+i] = 0
elif i == 1:
res[idx] = i
status[i] = 1
nxt_idx = res.index(0) if 0 in res else 2*n-1
success = dfs(nxt_idx)
if success:
return True
status[i] = 0
res[idx] = 0
return False
dfs(0)
return res
評価のためにコードを送信した後、52ミリ秒かかり、14.2MBのメモリを消費しました。現在の最適なコード実装について。
4.トピック4
質問4のテスト問題へのリンクは次のとおりです。
1.問題解決のアイデア
ここでは、いくつかの言葉から始めて、私たちの考えについて話しましょう。
まず、はっきりと見えることが1つあります。
- 特定のノードがルートノードである場合、そのノードはすべてのノードと接続関係にある必要があります。したがって、他の接続されたノードの数に従ってルートノードを直接見つけることができます。
- ルートノードが1つしかない場合は、ルートノードに関連するすべての接続を削除すると、フォレストが取得されます。フォレストでは、各ツリーが上記のアルゴリズムを再帰的に呼び出して、接続があるかどうか、および複数の接続があるかどうかを確認できます。
- ルートノードが複数ある場合は、これらのノードを含むすべての接続を削除してフォレストを取得することもできますが、次のフォレストのツリーを構築できる限り、接続する方法はたくさんあります。
dsuアルゴリズムを使用して、ルートノード接続後のすべてのノードのどれを同じツリーに関連付けることができるかを判断できます。
このようにして、再帰的スケジューリングアルゴリズムを作成できます。
2.コードの実装
Pythonコードは次のとおりです。
class DSU:
def __init__(self, N):
self.dsu = [i for i in range(N)]
def find(self, k):
if self.dsu[k] == k:
return k
self.dsu[k] = self.find(self.dsu[k])
return self.dsu[k]
def union(self, a, b):
x = self.find(a)
y = self.find(b)
if x != y:
self.dsu[y] = x
return
class Solution:
def checkWays(self, pairs: List[List[int]]) -> int:
counter = defaultdict(int)
for x, y in pairs:
counter[x] += 1
counter[y] += 1
n = len(counter)
if all(x == n-1 for x in counter.values()):
return 2 if n >= 2 else 1
if not any(x == n-1 for x in counter.values()):
return 0
roots = [x for x in counter if counter[x] == n-1]
# print(pairs, n, counter, counter.values(), [x for x in counter.values() if x == n-1])
pairs = [[x, y] for x, y in pairs if x not in roots and y not in roots]
dsu = DSU(501)
for x, y in pairs:
dsu.union(x, y)
pairs_group = defaultdict(list)
for x, y in pairs:
pairs_group[dsu.find(x)].append([x, y])
if len(pairs_group) == 0:
return 1 if len(roots) == 1 else 2
res = []
for p in pairs_group.values():
cnt = self.checkWays(p)
if cnt == 0:
return 0
res.append(cnt)
return 1 if all(x == 1 for x in res) and len(roots) == 1 else 2
残念ながら、80個のテストサンプルのうち77個しか合格せず、タイムアウトの問題が発生しました。
3.アルゴリズムの最適化
残念ながら、2日間考えても良い答えはありませんでしたが、結局、他の人の答えを読んでショックを受け、彼らの解決策が本当にエレガントであることに気づきました。
まず第一に、それは私たちの以前の考えでしたが、彼らはさらに2つの重要な中間結論を思いつきました。
- 接続数が同じで相互接続されたポイントが2つある場合は、相互に接続する必要があります。つまり、2つのノードを交換しても、最終的な結果には影響しません。このとき、特定の接続方法がある場合は、一種;
- 息子ノードの接続数は常に親ノードの接続数以下です。したがって、接続数が最も多いノードから接続ポイントをトラバースすると、いつでもその親ノードを新しい下位ノードに更新できます。 。。
したがって、Pythonコードの実装を次のように示します。
class Solution:
def checkWays(self, pairs: List[List[int]]) -> int:
cnt = collections.defaultdict(int)
edges = collections.defaultdict(set)
for u, v in pairs:
cnt[u] += 1
cnt[v] += 1
edges[u].add(v)
edges[v].add(u)
nodes = sorted(cnt.keys(), key = lambda x: cnt[x], reverse = True)
if cnt[nodes[0]] != len(nodes) - 1: return 0
unique = True
for x, y in pairs:
if cnt[x] == cnt[y]:
unique = False
break
pa = collections.defaultdict(int)
pa[nodes[0]] = 0
for o in nodes:
for ch in edges[o]:
if pa[ch] != pa[o]: return 0
pa[ch] = o
edges[ch].remove(o)
return 1 if unique else 2
コード評価を送信した後、1588ミリ秒かかり、43.7MBのメモリを消費しました。これは、アルゴリズム実装の現在の最適なバッチに属しています。