LeetCodeノート:毎週のコンテスト217コンテストの記録

0.試合後のまとめ

残念ながら、昨日は美しいターンアラウンドと戦い、先週の不正の復讐を果たしました。その結果、今日はウォータールーに悲劇的な打撃を受けました。突然2つの質問をしたところ、2番目の質問も3回続けて間違っていました。 。

すると、国内は579、世界は1501になり、最初の15%は入場できず、上位20%に入ることができず、本名では悲惨です。

2番目の質問の3つの間違いのうちの2つは完全にメンタリティによるものですが、メンタリティを調整する能力も強さの一部ですよね。すべての悲劇は、当事者自身の能力の欠如によって引き起こされているということわざがあります。

悲しいかな、結局ファンタジーが壊れる瞬間があるでしょう。あなたの弱さを認識して、それから登るのに苦労します、サンニアン。

道は長くて難しいので、上下を探します。

1.トピック1

質問1に与えられた質問へのリンクは次のとおりです。

1.問題解決のアイデア

この質問を解決するという考えは非常に簡単です。今回の質問の中で最も単純なものです。各行を合計して最大値を見つけるだけです。

2.コードの実装

Pythonコードは次のとおりです。

class Solution:
    def maximumWealth(self, accounts: List[List[int]]) -> int:
        return max([sum(x) for x in accounts])

コード評価を送信して取得:100ミリ秒かかり、14.2MBのメモリを消費します。

現在の最適なコード実装には52ミリ秒かかりますが、考え方はまったく同じで、実装の詳細のみがわずかに異なります。

2.トピック2

トピック2のテスト問題へのリンクは次のとおりです。

1.問題解決のアイデア

この質問は実際には非常に単純な考えです。前者は最初に最初のn-k数の中からその位置を参照して最小数をidx見つけ、次にidx+1最初のn-k+1最小数から2番目の数として見つけ、すべてが入力されるまで上記の操作を繰り返します。数字。

コードの効率を最適化するために、heapqライブラリを使用してコードの実装を最適化します。

2.コードの実装

Pythonコードは次のとおりです。

class Solution:
    def mostCompetitive(self, nums: List[int], k: int) -> List[int]:
        n = len(nums)
        q = [(x, idx) for idx, x in enumerate(nums[:-k])]
        heapq.heapify(q)
        res = [0 for _ in range(k)]
        pre = -1
        for i in range(k):
            heapq.heappush(q, (nums[n-k+i], n-k+i))
            while q:
                x, idx = heapq.heappop(q)
                if idx > pre:
                    res[i] = x
                    pre = idx
                    break
        return res

評価のためにコードを送信した後、1608ミリ秒かかり、31.6MBのメモリを消費しました。

現在の最適なコード実装は852msしかかかりません。実際の測定後、実行に1260msかかることがわかりました。実行効率は私たちに比べて向上していますが、2倍ほど誇張されていません。

残念ながら、彼らのコードを見た後、私は彼らのコードロジックを理解できず、パフォーマンスの最適化のポイントも理解できませんでした。興味のある読者は自分でそれをチェックすることができ、ここでは拡張しません。悲しいかな、それを理解していません。

他の人は問題を解決するための別のアイデアを持っています理論的には、アルゴリズムの複雑さはO(N)O(N)だけですO N ですが、実際の操作を行った後、実行効率が低下していることがわかり、よくわかりません。

3.トピック3

トピック3のテスト問題へのリンクは次のとおりです。

1.問題解決のアイデア

この質問の最初のアイデアは、現在の合計の頻度を調査して、合計ターゲットとして選択する必要がある数を調査することです。このようにして、特定のトラバースの複雑さを軽減することもできますが、タイムアウトの問題は、最後に、タイムアウトの問題は解決されませんでした。

大会終了後、大物の問題解決のアイデアを見てみると、彼らのアイデアはとても賢いものでした。

基本的に、彼らは、各世代範囲の各番号がターゲットの補数として使用されるときに受ける必要のある変換の数を数えています。最初にこのアイデアについて考えましたが、後でアルゴリズムの複雑さのアイデアは放棄されました、しかし、大物私たちはこれに対して優れた最適化を行いました。

小さいものから大きいものまでの2つの数値がxxであると仮定して、統計のラウンドでいくつかの主要なノードのみを考慮します。xyyおよび

  1. で、2 22からxxxの範囲で、これらの数になるために必要な変換の数は2です。
  2. で、XXxx + y-1 x + y-1バツ+Y範囲1、変換の数は1です。
  3. X + Y、X + Yバツ+y、追加の変換操作は必要ありません。つまり、変換の数は0です。
  4. x + y + 1 x + y + 1バツ+Y+1到来+制限y +制限Y+l i m i tの範囲内で、変換の数は1です。
  5. +制限+ 1年+制限+1Y+l i m i t+1以上の目標の場合、必要な変換の数は2です。

したがって、実際には、キーノードでの変更の数を記録してから、累積合計を行うだけで済みます。

実際、私は以前にこのソリューションを使用したことがありますが、残念ながらここでは考えていなかったため、この質問は失敗しました。確かに、山を山として、水をの領域として見ることはまだ不可能です。水。

2.コードの実装

Pythonコードは次のとおりです。

class Solution:
    def minMoves(self, nums: List[int], limit: int) -> int:
        counter = [0] * (limit*2+2)
        n = len(nums)
        for i in range(n // 2):
            x, y = sorted([nums[i], nums[n-1-i]])
            counter[2] += 2
            counter[x+1] -= 1
            counter[x+y] -= 1
            counter[x+y+1] += 1
            counter[y+limit+1] +=1
        counter = list(accumulate(counter))
        return min(counter[2:-1])

評価のためにコードを送信した後、1124ミリ秒かかり、28.9MBのメモリを消費しました。

現在の最適なコードの実装には1080msかかりますが、本質的には上記の問題解決のアイデアとまったく同じです。

4.トピック4

質問4のテスト問題へのリンクは次のとおりです。

1.問題解決のアイデア

この質問が出されたとき、私の考えはめちゃくちゃになり、私は長い間さまざまな問題に取り組みました。

ゲーム終了後、大物の答えを見てみると、コードが意外と簡潔で、少しびっくりしました。よく見てみると、意外と簡単な答えでした。

まず、すべての数を偶数に変換します。このように、すべての数を除算することしかできません。つまり、すべての数を小さくすることはできますが、大きくすることはできません。したがって、最大の要素を取り出し続けるだけで済みます。 。最大の要素が2で割り切れる場合は、それを2で除算し、新しい配列の最大の要素と最小の要素の違いを調べて、最小の値を取得します。それだけです。

2.コードの実装

Pythonコードは次のとおりです。

class Solution:
    def minimumDeviation(self, nums: List[int]) -> int:
        for i, x in enumerate(nums):
            if x % 2 == 1:
                nums[i] = x * 2
        nums = sorted(nums)

        ans = nums[-1] - nums[0]
        while nums[-1] % 2 == 0:
            x = nums.pop()
            x = x // 2
            bisect.insort(nums, x)
            ans = min(ans, nums[-1] - nums[0])
        return ans

上記のコード評価を送信して取得します。3860msかかり、26.4MBのメモリを消費します。

ただし、現在の最適なコードの実装にかかる時間は720ミリ秒で、アルゴリズムの5倍近く高速です。したがって、アルゴリズムのアイデアを検討する必要があります。

3.コードの最適化

現在の最適なコード実装を詳しく見てみると、アイデアは私たちのものとほぼ同じであることがわかりました。唯一の違いは、順序付けられた配列を維持するためにバイナリ挿入を使用せず、ヒープを維持するためにheapqを使用することです。

そのため、ヒープメソッドを使用してコードの実装も継続しました。

class Solution:
    def minimumDeviation(self, nums: List[int]) -> int:
        for i, x in enumerate(nums):
            if x % 2 == 1:
                nums[i] = -x * 2
            else:
                nums[i] = -x
        _max = max(nums)
        
        heapq.heapify(nums)
        ans = _max - nums[0]
        while nums[0] % 2 == 0:
            x = heapq.heappop(nums)
            x = x // 2
            _max = max(x, _max)
            heapq.heappush(nums, x)
            ans = min(ans, _max - nums[0])
        return ans

コードを送信した後、940ミリ秒かかり、26.5MBのメモリを消費することがわかりました。これは、現在の最適なコード実装とほぼ同じです。

困惑しています。原則として、すべてのアルゴリズムの複雑さはO(N・log N)O(N \ cdot logN)です。O Nl o g N ああ、なぜヒープソート効率を使用して救済を大幅に改善するのですか?

残念ながら、私は考えをあきらめたということです。読者がこの質問を理解できる場合は、コメント領域にいくつかのポインタを必ず教えてください。感謝しています。

おすすめ

転載: blog.csdn.net/codename_cys/article/details/110499260