blog

611. 有効な三角形の数

最初の数学的前提は、3 つのセグメントのうち、どれか 2 つのセグメントの和が 3 番目の辺より大きければ、3 つのセグメントは三角形を形成できるということです。つまり、3つのセグメントa、b、cが与...

Jun 8, 2020 · 5 min. read
シェア

問題 アドレス

説明

非負整数の配列が与えられたとき、三角形の3辺を形成する三角形の数を数える 
例1:
 : [2,2,3,4]
 : 3
 :
効率的な組み合わせは:
2,3,4 (最初の2)を使う
2,3,4 (2)を使用する
2,2,3
注意:
配列の長さは1000を超えない。
配列中の整数の範囲は [0, 1000]。

事前知識

  • ソート
  • ダブルポインタ
  • (毛沢東主義)を2つに分けます。
  • 三角形の辺の関係

ブルートフォース法

アイデア

3つのセグメントのうち、どれか2つの和が3番目の辺より大きければ、3つのセグメントは三角形を形成できるこれは数学的な前提から始まります。つまり、3つの線分a、b、cが与えられたとき、線分a、b、cが三角形を形成できるのは、a+b>c、a+c>b、b+c>aを満たす場合であり、そうでない場合は三角形を形成できません。

パワーバックルには、数学的な前提知識を必要とするトピックがいくつかありますが、それは比較的簡単なもので、通常は高校数学程度の知識で、特に複雑なものではありません。通常は小中学校の知識で十分です。

" "

キーポイント分析

  • 三角形の辺の関係
  • トリプルループは3つの線分を識別します。

コード

コードサポート: Python

class Solution:
 def is_triangle(self, a, b, c):
 if a == 0 or b == 0 or c == 0: return False
 if a + b > c and a + c > b and b + c > a: return True
 return False
 def triangleNumber(self, nums: List[int]) -> int:
 n = len(nums)
 ans = 0
 for i in range(n - 2):
 for j in range(i + 1, n - 1):
 for k in range(j + 1, n):
 if self.is_triangle(nums[i], nums[j], nums[k]): ans += 1
 return ans

「複雑性解析

  • 時間の複雑さ:N は配列の長さ。
  • 空間の複雑さ

最適化された暴力的方法

アイデア

暴力的手法の時間複雑度は であり は最大1000です。 このアルゴリズムは、データサイズ <= 500ではACであり、1000を超える桁では を考慮する必要があります。

よし、これで良し。辛口でいきますよ。 他のブロガーがあまり触れないようなものでなければなりません。その理由は、知らないか、話すにはあまりに平凡だと思うからでしょう。

  1. 先ほど私は、データのサイズに基づく解の複雑さの区間は であることがわかりました。 であるはずがありません。 .
  2. 時間の複雑さを減らす主な方法は、space-for-timeとsort-for-timeです。時間並べ替えは、全体の複雑さが0.5より大きい場合にのみ適用されます。 全体の複雑さが

ここで、全体の時間の複雑さは であるため、当然、時間のソートを考えました。numsを一度ソートした後、私は見つけました:

  • is_triangle 関数には有効でない判定があります。
 def is_triangle(self, a, b, c):
 if a == 0 or b == 0 or c == 0: return False
 # a + c > b および + c > a は定数が成り立つので、無効な判断である
 if a + b > c and a + c > b and b + c > a: return True
 return False
  • 従って、a + b > cを見つけることが目標となり、ループの第3レベルを早期に終了することができます。
for i in range(n - 2):
 for j in range(i + 1, n - 1):
 k = j + 1
 while k < n and num[i] + nums[j] > nums[k]:
 k += 1
 ans += k - j - 1
  • これも単なる分岐の削減であり、複雑さは変わりません。さらに観察すると、kは毎回j + 1から始める必要はないことがわかります。代わりに、見つけたkの値から始めればいいのです。理由は簡単で、nums[i] + nums[j] > nums[k]のとき、nums[i] + nums[j] > nums[k]を満たす次の新しいkの値を見つけたい場合、このkはソートのため見つけたkより大きくなければならないので、前のkの値は無効でスキップできるからです。
for i in range(n - 2):
 k = i + 2
 for j in range(i + 1, n - 1):
 while k < n and nums[i] + nums[j] > nums[k]:
 k += 1
 ans += k - j - 1

Kはバックオフしないので、最も内側のループは合計で最大N回実行され、全体の時間複雑度は 全体の時間複雑度は

"

この複雑さの分析は、モノトニック・スタックのようなもので、組み合わせて理解することができます。

"

キーポイント分析

  • ソート

コード

class Solution:
 def triangleNumber(self, nums: List[int]) -> int:
 n = len(nums)
 ans = 0
 nums.sort()
 for i in range(n - 2):
 if nums[i] == 0: continue
 k = i + 2
 for j in range(i + 1, n - 1):
 while k < n and nums[i] + nums[j] > nums[k]:
 k += 1
 ans += k - j - 1
 return ans

「複雑性解析

  • 時間の複雑さ
  • 空間の複雑さ:ソートアルゴリズムに依存
Read next

.NETオンライン可読プログラムログアシスタント

log4netのsqliteデータベースを使用してプログラムのログを記録し、ログの内容を表示するためにhtmlページを使用して、ログの内容を表示するためにサーバーに入らないという目的を達成するために。すべてのプログラムのログは、log4netは、インクリメンタルログで、sqliteデータベースに書き込まれ、ログを書いている間、ログを表示するには、少し遅く表示されます。 1、3つのログレベルを持つログを設計するオフ(...

Jun 7, 2020 · 7 min read