TLP-Task04研究ノート


この記事は、Datawhaleチームの調査計画の21番目のLeetCodeが選択したトピックグループTask04調査ノートです。
初心者の方は少し時間がかかり、多くの解決策は詳細に分析されておらず、将来改訂される予定ですので、ご容赦ください。
すべてのトピックは、Datawhale学習ドキュメントのオープンソースアドレスを参照しています:
https //github.com/datawhalechina/team-learning-program/tree/master/LeetCodeTencent

0163つの数値の最も近い合計

出典:LeetCode
リンク:https ://leetcode-cn.com/problems/3sum-closest

n個の整数numsの配列とターゲット値targetが与えられます。それらの合計がターゲットに最も近くなるように、numsで3つの整数を見つけます。これらの3つの数値の合計を返します。入力のセットごとに1つの答えしかないと仮定します。

例:

入力:nums = [-1,2,1、-4]、target = 1
出力:2
説明:targetに最も近い合計は2(-1 + 2 + 1 = 2)です。

アイデア

昨日の015の3つの数値の合計と同様に、[ソート+ダブルポインター]のソリューションが引き続き採用されています。
列挙の最初の数aが決定されたとすると、残りの2つの数の合計はターゲットaにできるだけ近い必要があります。ループを回避するために、最初に配列を並べ替えましょう(おそらく昇順で):

配列の長さがnであると仮定して、最初にaを列挙し、配列内のその位置はiです。
繰り返しの列挙を防ぐために、位置[i + 1、n)の範囲でbとcを列挙します。

ダブルポインタの助けを借りて、列挙プロセスを最適化することができます。分析プロセスは、前回の011のロングボードとショートボードに似ています。

pbとpcを使用して、それぞれbとcへのポインタを示します。最初に、pbは左側の境界である位置i + 1を指し、pcは右側の境界である位置n-1を指します。列挙プロセスの各ステップで、a + b + cを使用して回答を更新します。a+ b +c≥targetの場合、
pcを1つ左に移動します
。a+ b + c <t argetの場合、Just pbを1つ右に移動します。

実際、pbとpcは、現在選択できる数値の範囲を表しています。各列挙プロセス中に、境界で2つの要素を試し、それらと目標値の関係に応じて「破棄」を選択します。 borderは右の境界線の要素でもあるため、列挙の範囲が狭くなります。このアイデアは、11の2ポインターソリューションに似ています。水が最も多いコンテナー。

Pythonの実装

コードとコメントは公式ソリューションからのものであり、その他のマイナーな最適化もソリューションに記載されています。

class Solution:
    def threeSumClosest(self, nums: List[int], target: int) -> int:
        nums.sort()
        n = len(nums)
        best = 10**7
        
        # 根据差值的绝对值来更新答案
        def update(cur):
            nonlocal best
            if abs(cur - target) < abs(best - target):
                best = cur
        
        # 枚举 a
        for i in range(n):
            # 保证和上一次枚举的元素不相等
            if i > 0 and nums[i] == nums[i - 1]:
                continue
            # 使用双指针枚举 b 和 c
            j, k = i + 1, n - 1
            while j < k:
                s = nums[i] + nums[j] + nums[k]
                # 如果和为 target 直接返回答案
                if s == target:
                    return target
                update(s)
                if s > target:
                    # 如果和大于 target,移动 c 对应的指针
                    k0 = k - 1
                    # 移动到下一个不相等的元素
                    while j < k0 and nums[k0] == nums[k]:
                        k0 -= 1
                    k = k0
                else:
                    # 如果和小于 target,移动 b 对应的指针
                    j0 = j + 1
                    # 移动到下一个不相等的元素
                    while j0 < k and nums[j0] == nums[j]:
                        j0 += 1
                    j = j0

        return best


#作者:LeetCode-Solution
#链接:https://leetcode-cn.com/problems/3sum-closest/solution/zui-jie-jin-de-san-shu-zhi-he-by-leetcode-solution/
#来源:力扣(LeetCode)
#著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

020有効な括弧

ソース:LeetCode
リンク:https ://leetcode-cn.com/problems/valid-parentheses

'('、 ')'、 '{'、 '}'、 '['、 ']'のみを含む文字列が与えられた場合、その文字列が有効かどうかを判断します。有効な文字列は次の条件を満たす必要があります。

  • オープニングブラケットは、同じタイプのクロージングブラケットで閉じる必要があります。
  • 開き括弧は正しい順序で閉じる必要があります。

空の文字列は有効な文字列と見なすことができることに注意してください。

例:

入力: "()"
出力:true

入力: "()[] {}"
出力:true

入力: "(]"
出力:false

入力: "([)]"
出力:false

入力: "{[]}"
出力:true

アイデア

より一般的な(そして比較的単純な)質問については、[スタック]を確認してください。公式ソリューション

括弧の有効性の判断は、データ構造「スタック」を使用して解決できます。

指定された文字列sをトラバースし、左括弧に遭遇すると、後続のトラバースで、同じタイプの右括弧が文字列を閉じると予想します。後で遭遇する左括弧は最初に閉じる必要があるため、この左括弧をスタックの一番上に置くことができます。

右括弧に遭遇したら、同じタイプの左括弧を閉じる必要があります。この時点で、スタックの一番上にある左括弧を取り出して、それらが同じタイプの括弧であるかどうかを判別できます。同じタイプでない場合、またはスタックに左括弧がない場合、文字列sは無効であり、Falseが返されます。括弧のタイプをすばやく判別するために、HashMapを使用して各タイプの括弧を格納できます。ハッシュマップのキーは右括弧であり、値は同じタイプの左括弧です。

トラバーサルが終了した後、スタックに左括弧がない場合は、文字列sのすべての左括弧を閉じてTrueを返し、それ以外の場合はFalseを返します。

その他の最適化:

有効な文字列の長さは偶数でなければならないことに注意してください。したがって、文字列の長さが奇数の場合、Falseを直接返すことができ、後続のトラバーサル判定プロセスを節約できます。

Pythonの実装

class Solution:
    def isValid(self, s: str) -> bool:
        if len(s) % 2 == 1:
            return False
        
        pairs = {
    
    
            ")": "(",
            "]": "[",
            "}": "{",
        }
        stack = list()
        for ch in s:
            if ch in pairs:
                if not stack or stack[-1] != pairs[ch]:
                    return False
                stack.pop()
            else:
                stack.append(ch)
        
        return not stack


#作者:LeetCode-Solution
#链接:https://leetcode-cn.com/problems/valid-parentheses/solution/you-xiao-de-gua-hao-by-leetcode-solution/
#来源:力扣(LeetCode)
#著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0212つの順序付けられたリンクリストをマージします

ソース:LeetCode
リンク:https ://leetcode-cn.com/problems/merge-two-sorted-lists

2つの昇順リンクリストを新しい昇順リンクリストに結合して戻ります。新しいリンクリストは、指定された2つのリンクリストのすべてのノードを接続することによって構成されます。

例:

入力:l1 = [1,2,4]、l2 = [1,3,4]
出力:[1,1,2,3,4,4]

入力:l1 = []、l2 = []
出力:[]
入力:l1 = []、l2 = [0]
出力:[0]

促す:

2つのリンクリスト内のノード数の範囲は[
0、50 ] -100 <= Node.val <= 100l1
とl2は降順ではありません。

アイデア

ここでは再帰を使用し、反復法も公式ソリューションで説明されています

次のように、2つのリンクリストでマージ操作を再帰的に定義できます(空のリンクリストなどの境界条件を無視します):
list1 [0] + merge(list1 [1:]、list2)(if list1 [0] < list2 [0])
List2 [0] + merge(list1、list2 [1:])(それ以外の場合)
つまり、2つのリンクリストのヘッド値が小さいノードが、のマージ操作の結果とマージされます。残りの要素。

アルゴリズム

上記の再帰的プロセスを直接モデル化し、境界条件を考慮する必要があります。

l1またはl2が最初から空のリンクリストである場合、マージする操作はないため、空でないリンクリストを返すだけで済みます。それ以外の場合は、l1とl2のリンクリストのどちらのヘッドノードの値が小さいかを判断し、結果に追加する次のノードを再帰的に決定する必要があります。2つのリンクリストのいずれかが空の場合、再帰は終了します。

Pythonの実装

class Solution:
    def mergeTwoLists(self, l1, l2):
        if l1 is None: # 判断是否为空/结束
            return l2
        elif l2 is None:
            return l1
        elif l1.val < l2.val: 
        	# 递归,将较小节点与剩下元素的操作合并
            l1.next = self.mergeTwoLists(l1.next, l2)
            return l1
        else:
            l2.next = self.mergeTwoLists(l1, l2.next)
            return l2


#作者:LeetCode-Solution
#链接:https://leetcode-cn.com/problems/merge-two-sorted-lists/solution/he-bing-liang-ge-you-xu-lian-biao-by-leetcode-solu/
#来源:力扣(LeetCode)
#著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

おすすめ

転載: blog.csdn.net/cosima0/article/details/112642535