-
Notifications
You must be signed in to change notification settings - Fork 0
373. Find K Pairs With Smallest Sums #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| ## step1 | ||
| - 一旦愚直に解く方法を考える | ||
| - 選び方はnums1.length*nums2.length通りで、合計でsortする場合O(NlogN) | ||
| - 10^5*10^5 + 10^10log10 が大体 10^10(1+3.1)で1秒間に10^8回計算できる場合は410秒でTLE | ||
|
|
||
| - 改善案 | ||
| - 取り方的にkを超えるindexは無視して良さそう | ||
| - その場合でも4.1秒でTLEしそう | ||
| - 全てのパターンを列挙するので1秒掛かる | ||
| - 一旦実装したが、Memory Limit Exceededになった | ||
|
|
||
| ```py | ||
| def kSmallestPairs( | ||
| self, nums1: List[int], nums2: List[int], k: int | ||
| ) -> List[List[int]]: | ||
| sum_combibations = [] | ||
| for num1 in nums1[:k]: | ||
| for num2 in nums2[:k]: | ||
| sum_combibations.append([num1 + num2, [num1, num2]]) | ||
|
|
||
| sum_combibations.sort() | ||
|
|
||
| return [combination for [_sum, combination] in sum_combibations[:k]] | ||
| ``` | ||
|
|
||
| - 愚直に列挙するやり方は無理そうなので前から数字を見ていき、取り方のルールを整理する[nums1のindex, nums2のindex]とする | ||
| - 1番目の答え: [0,0] | ||
| - 2番目の答えの候補:[0,1] or [1,0] | ||
| - 3番目の答えの候補 | ||
| - 2番目の答えが[0,1]: [1,0] or [0,2] | ||
| - 2番目の答えが[1,0]: [0,1] or [2,1] | ||
| - 4番目の答えの候補 | ||
| - 3番目の答えが[1,0]2番目の答えが[0,1]: [1,1] or [2,0] or [0,2] | ||
| - n=>n+1の時にindexが戻ることがあるのが嫌すぎる | ||
| - これまでの履歴から答えの候補になるindexは決まっているのでその中から都度選んでいくのがいい? | ||
| - 合計とindexをheapqに入れておいてpopしていく作戦 | ||
| - 最初の提出では重複して同じペアをカウントしてしまったが、その後修正したらAcceptedになった | ||
|
|
||
| ## step2 | ||
| - 次のindexの存在確認とリストへの追加のところがごちゃごちゃしてるように感じるし、繰り返しているように見える | ||
| - 時間計算量はO(klogk),空間計算量はO(k)だと思う | ||
| - 他の人のコードを読む | ||
| - https://github.com/Hiroto-Iizuka/coding_practice/pull/10/files | ||
| - 十分に理解できておらず、swapさせるうまみみたいなのがわからなかった | ||
| - https://github.com/mamo3gr/arai60/pull/10/files | ||
| - `空間計算量を求めたあと、実際のどの程度のメモリを使用するか推定されましたでしょうか?もししていないのであれば、推定することをお勧めいたします。推定するには、時間計算量の式に最大サイズを代入し、 1 要素当たりのサイズを掛けてみてください。`. `sys.getsizeof`など勉強になった | ||
| - 自分で言うところのsum_heapは最小値候補なので、`candidates`とした方が良いように思った | ||
| - 自分の命名だと意味が付け加えられていないように感じた | ||
| - `enqueue_if_valid_and_not_visited`確かにわかりやすい | ||
| - https://github.com/Yuto729/LeetCode_arai60/pull/16/files | ||
| - `C++: 約 1~10 億ステップ/秒` | ||
| - `CPU の周波数が数 GHz 程度であるため、IPC(Instructions per Cycle)を 1 と仮定すると、1 秒間に数十億命令を実行できます。C++ はオーバーヘッドが小さく、1 ステップを数命令〜数十命令で実行できるため、おおよそ 1~10 億ステップ/秒が目安となります。` | ||
| - `Python: 約 100 万~1000 万ステップ/秒` | ||
| - `インタープリタ方式によるオーバーヘッドが大きく、C++ の約 100 倍遅いため、この程度が目安になります。` | ||
|
|
||
| - 一旦、`enqueue_if_valid_and_not_visited`の対応を行う | ||
| - 個人的には`visited_pair_set`にすると候補というニュアンスが薄れる気がする | ||
| - candidateにaddしたという意味で`processed`を使っていたがなんでも`process`なので`added`とかにしておく | ||
|
|
||
| ## step3 | ||
| - 関数の中でnum1_index, num2_indexと書くと、読む量が増えてくどく感じたのでi,jにした | ||
| - n1_indexでも十分伝わると思ったので少し省略した | ||
| - データ構造を名前に含めがちな癖があるので`added_indice_set`とせず`added_indice`とした | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| # | ||
| # @lc app=leetcode id=373 lang=python3 | ||
| # | ||
| # [373] Find K Pairs with Smallest Sums | ||
| # | ||
|
|
||
| # @lc code=start | ||
| import heapq | ||
|
|
||
|
|
||
| class Solution: | ||
| def kSmallestPairs( | ||
| self, nums1: List[int], nums2: List[int], k: int | ||
| ) -> List[List[int]]: | ||
| sum_heap = [[nums1[0] + nums2[0], [0, 0]]] | ||
|
|
||
| k_small_pairs = [] | ||
| processed_pair_set = set((0, 0)) | ||
|
|
||
| while len(k_small_pairs) < k: | ||
| [_, num1_num2_index] = heapq.heappop(sum_heap) | ||
| [num1_index, num2_index] = num1_num2_index | ||
| k_small_pairs.append([nums1[num1_index], nums2[num2_index]]) | ||
| if ( | ||
| num1_index + 1 < len(nums1) | ||
| and (num1_index + 1, num2_index) not in processed_pair_set | ||
| ): | ||
| heapq.heappush( | ||
| sum_heap, | ||
| [ | ||
| nums1[num1_index + 1] + nums2[num2_index], | ||
| [num1_index + 1, num2_index], | ||
| ], | ||
| ) | ||
| processed_pair_set.add((num1_index + 1, num2_index)) | ||
| if ( | ||
| num2_index + 1 < len(nums2) | ||
| and (num1_index, num2_index + 1) not in processed_pair_set | ||
| ): | ||
| heapq.heappush( | ||
| sum_heap, | ||
| [ | ||
| nums1[num1_index] + nums2[num2_index + 1], | ||
| [num1_index, num2_index + 1], | ||
| ], | ||
| ) | ||
| processed_pair_set.add((num1_index, num2_index + 1)) | ||
| return k_small_pairs | ||
|
|
||
|
|
||
| # @lc code=end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| # | ||
| # @lc app=leetcode id=373 lang=python3 | ||
| # | ||
| # [373] Find K Pairs with Smallest Sums | ||
| # | ||
|
|
||
| # @lc code=start | ||
| import heapq | ||
|
|
||
|
|
||
| class Solution: | ||
| def kSmallestPairs( | ||
| self, nums1: List[int], nums2: List[int], k: int | ||
| ) -> List[List[int]]: | ||
| candidate = [] | ||
|
|
||
| k_small_pairs = [] | ||
| added_pair_set = set((0, 0)) | ||
|
|
||
| def enqueue_if_valid_and_not_added(num1_index, num2_index): | ||
| if num1_index >= len(nums1) or num2_index >= len(nums2): | ||
| return | ||
| if (num1_index, num2_index) in added_pair_set: | ||
| return | ||
| heapq.heappush( | ||
| candidate, | ||
| [ | ||
| nums1[num1_index] + nums2[num2_index], | ||
| [num1_index, num2_index], | ||
| ], | ||
| ) | ||
| added_pair_set.add((num1_index, num2_index)) | ||
|
|
||
| enqueue_if_valid_and_not_added(0, 0) | ||
|
|
||
| while len(k_small_pairs) < k: | ||
| [_, num1_num2_index] = heapq.heappop(candidate) | ||
| [num1_index, num2_index] = num1_num2_index | ||
| k_small_pairs.append([nums1[num1_index], nums2[num2_index]]) | ||
| enqueue_if_valid_and_not_added(num1_index + 1, num2_index) | ||
| enqueue_if_valid_and_not_added(num1_index, num2_index + 1) | ||
| return k_small_pairs | ||
|
|
||
|
|
||
| # @lc code=end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| # | ||
| # @lc app=leetcode id=373 lang=python3 | ||
| # | ||
| # [373] Find K Pairs with Smallest Sums | ||
| # | ||
|
|
||
| # @lc code=start | ||
|
|
||
| import heapq | ||
|
|
||
|
|
||
| class Solution: | ||
| def kSmallestPairs( | ||
| self, nums1: List[int], nums2: List[int], k: int | ||
| ) -> List[List[int]]: | ||
| candidate = [] | ||
| added_indice = set() | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ご指摘ありがとうございます。 |
||
|
|
||
| smallest_pairs = [] | ||
|
|
||
| def enqueue_if_valid_and_not_added(i, j): | ||
| if i >= len(nums1) or j >= len(nums2): | ||
| return | ||
| if (i, j) in added_indice: | ||
| return | ||
| heapq.heappush(candidate, [nums1[i] + nums2[j], [i, j]]) | ||
| added_indice.add((i, j)) | ||
|
|
||
| enqueue_if_valid_and_not_added(0, 0) | ||
|
|
||
| while len(smallest_pairs) < k: | ||
| _sum, [n1_index, n2_index] = heapq.heappop(candidate) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 元々は無視をしていい変数だが和が入っていますというニュアンスで_sumとしておりました。 |
||
| smallest_pairs.append([nums1[n1_index], nums2[n2_index]]) | ||
| enqueue_if_valid_and_not_added(n1_index + 1, n2_index) | ||
| enqueue_if_valid_and_not_added(n1_index, n2_index + 1) | ||
|
|
||
| return smallest_pairs | ||
|
|
||
|
|
||
| # @lc code=end | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
関数名はこれくらいしつこいものを付けても構わないと思います。