From 8c75b603af54bbb31c92fe77ec1c1944c7e66de2 Mon Sep 17 00:00:00 2001 From: shintaroyoshida20 Date: Sun, 20 Apr 2025 12:41:06 +0900 Subject: [PATCH 1/8] feat : #15 add the empty markdown file for creating a PR --- heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md diff --git a/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md b/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md new file mode 100644 index 0000000..e69de29 From 750087a25312b4713311e4f0a7fd5c658cc8602e Mon Sep 17 00:00:00 2001 From: shintaroyoshida20 Date: Sat, 3 May 2025 18:47:53 +0900 Subject: [PATCH 2/8] feat : #15 add the STEP 1 --- .../find-k-pairs-with-smallest-sums/answer.md | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md b/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md index e69de29..a3f5512 100644 --- a/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md +++ b/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md @@ -0,0 +1,104 @@ +# Title + +## STEP1 + +* 発想 + * うまくいかなかったケース + * 全てのペアを優先度付きキューに入れる。 + * 毎回入れた後に、k個を超えていた場合には、最大の和をもつペアを取り除く。 + * K個を取り出す。 + + +```javascript +var kSmallestPairs = function(nums1, nums2, k) { + this.top_k = new PriorityQueue((a, b) => b.sum - a.sum) + for (const num1 of nums1) { + for (const num2 of nums2) { + const pair = { + num1: num1, + num2: num2, + sum: num1 + num2, + } + if (this.top_k.size() < k) { + this.top_k.enqueue(pair) + continue + } + const max_pair = this.top_k.front() + if (max_pair.sum > pair.sum) { + this.top_k.enqueue(pair) + while (this.top_k.size() > k) { + this.top_k.dequeue() + } + } + } + } + const ans = [] + while (this.top_k.size() > 0) { + const pair_and_sum = this.top_k.pop() + ans.push([pair_and_sum.num1, pair_and_sum.num2]) + } + return ans +}; +``` + +* 上の例だと、Time Limit Exceededが発生した。 + * nums1とnums2がソートされていることを利用した。 + nusm1の個数 x nums2の個数を全て探索するのではなく、ある1つが条件を満たさない場合に + それ以上大きいnums2を探さないように変更した。 + +```javascript +const kSmallestPairs = function(nums1, nums2, k) { + this.top_k = new PriorityQueue((a, b) => b.sum - a.sum) + for (const num1 of nums1) { + for (const num2 of nums2) { + const pair = { + num1: num1, + num2: num2, + sum: num1 + num2, + } + if (this.top_k.size() < k) { + this.top_k.enqueue(pair) + continue + } + const max_pair = this.top_k.front() + // Add these 3 lines compared with Time Limit Exceeded Code. + if (max_pair.sum <= pair.sum) { + break + } + this.top_k.enqueue(pair) + while (this.top_k.size() > k) { + this.top_k.dequeue() + } + } + } + const ans = [] + while (this.top_k.size() > 0) { + const pair_and_sum = this.top_k.pop() + ans.push([pair_and_sum.num1, pair_and_sum.num2]) + } + return ans +}; +``` + +* 改善した方法 + +## STEP2 + +### 整える +* 毎回優先度付きキューにペアを入れるのではなく、より小さいペアが見つかった際に入れる。 +* + +```javascript +``` + +## STEP3 + +```javascript +``` + +## 感想 + +### コメント集を読んで + +## その他の解法 + From 7867e26f746b9ada23b0d5aa235f635b1d6daaf2 Mon Sep 17 00:00:00 2001 From: shintaroyoshida20 Date: Sat, 3 May 2025 21:15:35 +0900 Subject: [PATCH 3/8] feat : #15 add the STEP2 / STEP3 --- .../find-k-pairs-with-smallest-sums/answer.md | 115 ++++++++++++++++-- 1 file changed, 108 insertions(+), 7 deletions(-) diff --git a/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md b/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md index a3f5512..4506016 100644 --- a/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md +++ b/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md @@ -1,4 +1,4 @@ -# Title +# 373. Find K Pairs with Smallest Sums ## STEP1 @@ -8,9 +8,8 @@ * 毎回入れた後に、k個を超えていた場合には、最大の和をもつペアを取り除く。 * K個を取り出す。 - ```javascript -var kSmallestPairs = function(nums1, nums2, k) { +const kSmallestPairs = function(nums1, nums2, k) { this.top_k = new PriorityQueue((a, b) => b.sum - a.sum) for (const num1 of nums1) { for (const num2 of nums2) { @@ -42,7 +41,7 @@ var kSmallestPairs = function(nums1, nums2, k) { ``` * 上の例だと、Time Limit Exceededが発生した。 - * nums1とnums2がソートされていることを利用した。 + * nums1とnums2がソートされていることを利用し、Time Limit Exceededが発生しないようにした。 nusm1の個数 x nums2の個数を全て探索するのではなく、ある1つが条件を満たさない場合に それ以上大きいnums2を探さないように変更した。 @@ -84,21 +83,123 @@ const kSmallestPairs = function(nums1, nums2, k) { ## STEP2 -### 整える -* 毎回優先度付きキューにペアを入れるのではなく、より小さいペアが見つかった際に入れる。 -* +* nums1, nums2を全て探索する方法. ```javascript +const kSmallestPairs = function(nums1, nums2, k) { + this.top_k = new PriorityQueue((a, b) => b.sum - a.sum) + for (const num1 of nums1) { + for (const num2 of nums2) { + const pair = { + num1, + num2, + sum: num1 + num2, + } + if (this.top_k.size() < k) { + this.top_k.push(pair) + continue + } + const max_pair = this.top_k.front() + if (max_pair.sum <= pair.sum) { + break + } + this.top_k.push(pair) + this.top_k.pop() + } + } + const ans = [] + while (this.top_k.size() > 0) { + const pair_and_sum = this.top_k.pop() + ans.push([pair_and_sum.num1, pair_and_sum.num2]) + } + return ans +}; ``` ## STEP3 +* nums1, nums2を全て探索する方法. + ```javascript +const kSmallestPairs = function(nums1, nums2, k) { + const top_k = new PriorityQueue((a, b) => b.sum - a.sum) + for (const num1 of nums1) { + for (const num2 of nums2) { + const pair = { + num1, + num2, + sum: num1 + num2, + } + if (top_k.size() < k) { + top_k.push(pair) + continue + } + const max_pair = top_k.front() + if (max_pair.sum <= pair.sum) { + break + } + top_k.push(pair) + top_k.pop() + } + } + const ans = [] + while (top_k.size() > 0) { + const pair = top_k.pop() + ans.push([pair.num1, pair.num2]) + } + return ans +}; ``` ## 感想 +* 3回書く中で、頭の中が整理されてくる感覚を持つことができた。 +* 先頭と最後を、対応させると書きやすい。 + ### コメント集を読んで ## その他の解法 +* LeetCodeの解法 + 発想は、 + * 1. [0,0]を箱に入れる。 + * 2. 最小となるの和となるペアを取り出す。 + * 3. ペアに対して、id1 + 1をしたペアとid2 + 1をしたペアを作り、箱に入れる。 + * 4. 2と3をkが満たされるまで実行する。 + +```javascript +const kSmallestPairs = function(nums1, nums2, k) { + const visited_pairs = new Set() + // nums1のインデックスをid1とする。 + const id1 = 0 + // nums2のインデックスをid2とする。 + const id2 = 0 + const key = `${id1}_${id2}` + visited_pairs.add(key) + const container = new PriorityQueue((a, b) => a.sum - b.sum) + container.push({id1, id2, sum: nums1[id1] + nums2[id2]}) + + const ans = [] + while (k > 0) { + const min_pair = container.pop() + const id1 = min_pair.id1 + const id2 = min_pair.id2 + ans.push([nums1[id1], nums2[id2]]) + + const key1 = `${id1 + 1}_${id2}` + if (id1 + 1 < nums1.length && !visited_pairs.has(key1)) { + container.push({id1: id1 + 1, id2, sum: nums1[id1 + 1] + nums2[id2]}) + visited_pairs.add(key1) + } + + const key2 = `${id1}_${id2 + 1}` + if (id2 + 1 < nums2.length && !visited_pairs.has(key2)) { + container.push({id1, id2: id2 + 1, sum: nums1[id1] + nums2[id2 + 1]}) + visited_pairs.add(key2) + } + + k-- + } + return ans +}; +``` From c5cfb429334a90ce44542d851e07ccc5372173eb Mon Sep 17 00:00:00 2001 From: shintaroyoshida20 Date: Sun, 4 May 2025 10:31:18 +0900 Subject: [PATCH 4/8] feat : #15 add two more solutions --- .../find-k-pairs-with-smallest-sums/answer.md | 159 +++++++++++++++++- 1 file changed, 152 insertions(+), 7 deletions(-) diff --git a/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md b/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md index 4506016..8e0d639 100644 --- a/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md +++ b/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md @@ -83,7 +83,7 @@ const kSmallestPairs = function(nums1, nums2, k) { ## STEP2 -* nums1, nums2を全て探索する方法. +* nums1, nums2の全ての組み合わせを探索する方法. ```javascript const kSmallestPairs = function(nums1, nums2, k) { @@ -118,7 +118,7 @@ const kSmallestPairs = function(nums1, nums2, k) { ## STEP3 -* nums1, nums2を全て探索する方法. +* nums1, nums2no全ての組み合わせを探索する方法. ```javascript const kSmallestPairs = function(nums1, nums2, k) { @@ -158,14 +158,36 @@ const kSmallestPairs = function(nums1, nums2, k) { ### コメント集を読んで +* k個未満の要素が返ってきた時にどうするか? + +### 他の人のコードを読んで + +* Mike0121のコード + * Folder : https://github.com/Mike0121/LeetCode/tree/528c89c1dfc93228cecabcc524b0eaf449cf9735/Arai60%202023/50.%20Find%20K%20Pairs%20with%20Smallest%20Sums + * PR : https://github.com/Mike0121/LeetCode/pull/20 + * `while k > 0 and heap:` が読みづらい。 + * condition の中の個数を心の理論で決める。 + * 長くなった場合には、for/while statementの中で制御することも検討する。 + * while statement / for statementの主役となる変数を元に考えれば良さそう。 + +* YukiMichishitaのコード + * PR : https://github.com/YukiMichishita/LeetCode/pull/4/ + * 二方向ではなく、一方向だけチェックすればよい。 + +* https://github.com/nittoco/leetcode/pull/33/ + * + +* https://github.com/TORUS0818/leetcode/pull/12/ + ## その他の解法 -* LeetCodeの解法 - 発想は、 +* LeetCodeの解法 (左上を基点として、右方向/下方向に伸びていく方法) + 発想(手でやる) * 1. [0,0]を箱に入れる。 - * 2. 最小となるの和となるペアを取り出す。 - * 3. ペアに対して、id1 + 1をしたペアとid2 + 1をしたペアを作り、箱に入れる。 - * 4. 2と3をkが満たされるまで実行する。 + * 2. 最小の和となるペアを箱から取り出す。 + * 3. ペアを紙袋に詰める。 + * 4. ペアに対して、id1 + 1をしたペアとid2 + 1をしたペアを作り、箱に入れる。 + * 5. 2と3を、紙袋の中身がk個になるまで実行する。 ```javascript const kSmallestPairs = function(nums1, nums2, k) { @@ -203,3 +225,126 @@ const kSmallestPairs = function(nums1, nums2, k) { return ans }; ``` + +* setを使わずに解く方法 https://github.com/TORUS0818/leetcode/pull/12#discussion_r1623146530 + +``` +const kSmallestPairs = function(nums1, nums2, k) { + // \ i_1, i_2, i_3, ... (nums1) + // j_1 O O X + // j_2 O X X + // j_3 O X X + // j_4 X X X + // ... + // (nums2) + + // 上の例だと、配列は以下になる。 + // next_i_in_each_j = [2, 1, 1, 0, ...] + // next_j_in_each_i = [3, 1, 0, ...] + + + // next_i_in_each_j: j行目が次に何を出すかを表す配列。 + // 言い換えると、nums2の各値に対して、 + // nums1の探索が小さい方からどれだけ終わったかを表す。 + const next_i_in_each_j = new Array(nums2.length).fill(0) + + // next_j_in_each_i: i列目が次に何を出すかを表す配列。 + // 言い換えると、nums1の各値に対して、 + // nums2の探索が小さい方からどれだけ終わったかを表す。 + const next_j_in_each_i = new Array(nums1.length).fill(0) + + const index_pairs = new PriorityQueue((pair1, pair2) => { + const sum1 = nums1[pair1[0]] + nums2[pair1[1]] + const sum2 = nums1[pair2[0]] + nums2[pair2[1]] + return sum1 - sum2 + }) + + index_pairs.push([0, 0]) + const ans = [] + while (ans.length < k) { + const [i, j] = index_pairs.pop() + console.log(i, j, nums1[i], nums2[j]) + ans.push([nums1[i], nums2[j]]) + ++next_i_in_each_j[j]; + ++next_j_in_each_i[i]; + + if (i + 1 < nums1.length && next_j_in_each_i[i + 1] === j) { + if (next_i_in_each_j[j] !== i + 1) { + throw new Error("unexepected behavior") + } + index_pairs.push([i + 1, j]) + } + + if (j + 1 < nums2.length && next_i_in_each_j[j + 1] === i) { + if (next_j_in_each_i[i] !== j + 1) { + throw new Error("unexepected behavior") + } + index_pairs.push([i, j + 1]) + } + } + return ans +}; +``` + +* ahayashiのPR に対するOdaのコメントを考慮した方法 + * 参考: https://discord.com/channels/1084280443945353267/1200089668901937312/1222573940610695341 + * `add_to_heap_if_necessary(i + 1, j)`を関数化した方がよい + * (x - 1, y) と (x, y - 1) が両方 pairs の中にある、または、x, y どちらかが0でなければ、heap に足さなくていいとは思うんですよね。 + +```javascript +const kSmallestPairs = function(nums1, nums2, k) { + const candidates = new PriorityQueue((index_pair1, index_pair2) => { + const [i1, j1] = index_pair1 + const [i2, j2] = index_pair2 + return nums1[i1] + nums2[j1] - (nums1[i2] + nums2[j2]) + }) + const seen = new Set() + + function add_to_heap_if_necessary(i, j) { + const key = `${i}_${j}` + if (seen.has(key)) { + return + } + if (i >= nums1.length || j >= nums2.length) { + return + } + if (i === 0 || j === 0) { + candidates.push([i, j]) + seen.add(key) + return + } + const key1 = `${i - 1}_${j}` + const key2 = `${i}_${j - 1}` + if (seen.has(key1) && seen.has(key2)) { + candidates.push([i, j]) + seen.add(key) + return + } + } + + add_to_heap_if_necessary(0, 0) + const ans = [] + while (ans.length < k) { + if (candidates.size() === 0) { + break + } + const [i, j] = candidates.pop() + ans.push([nums1[i], nums2[j]]) + + add_to_heap_if_necessary(i + 1, j) + add_to_heap_if_necessary(i, j + 1) + } + return ans +}; +``` + +* yield generatorを使った方法 + +```javascript +``` + +* 右と下への探索ではなく、下方向のみにする方法もある。(右方向のみも可能) + +``` +``` + From 0fad2f7b5a39cdeb7d41dab70d2e4fb475c50ca6 Mon Sep 17 00:00:00 2001 From: shintaroyoshida20 Date: Mon, 5 May 2025 17:01:56 +0900 Subject: [PATCH 5/8] feat : #15 add 4 more solutions --- .../find-k-pairs-with-smallest-sums/answer.md | 250 +++++++++++++++++- 1 file changed, 239 insertions(+), 11 deletions(-) diff --git a/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md b/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md index 8e0d639..04ee424 100644 --- a/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md +++ b/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md @@ -116,6 +116,10 @@ const kSmallestPairs = function(nums1, nums2, k) { }; ``` +* [0, 0]から右方向/下方向に探索し、[i,j-1]と[i-1,j]がseenだった場合に追加する。 + +* yieldを用いる方法 + ## STEP3 * nums1, nums2no全ての組み合わせを探索する方法. @@ -154,11 +158,13 @@ const kSmallestPairs = function(nums1, nums2, k) { ## 感想 * 3回書く中で、頭の中が整理されてくる感覚を持つことができた。 -* 先頭と最後を、対応させると書きやすい。 +* マトリューシカのように外側から書くと書きやすい。 ### コメント集を読んで -* k個未満の要素が返ってきた時にどうするか? +* yieldのgeneratorを使った実装と分割統治法の実装の理解に時間がかかった。 + +* 射影の箇所は理解できず、スキップした。 ### 他の人のコードを読んで @@ -170,18 +176,77 @@ const kSmallestPairs = function(nums1, nums2, k) { * 長くなった場合には、for/while statementの中で制御することも検討する。 * while statement / for statementの主役となる変数を元に考えれば良さそう。 +* hayashi-ayのコード + * PR: https://github.com/hayashi-ay/leetcode/pull/66 + * この関数がすごくわかりやすいと思った。 + * 条件ではなく、関数の全体に意識をもっていくことができる。 + +``` + def need_to_add(x, y): + if x >= len(nums1) or y >= len(nums2): + return False + if x == 0 or y == 0: + return True + return (x - 1, y) in added and (x, y - 1) in added + def add_to_candidates_if_necessary(x, y): + if need_to_add(x, y): + heapq.heappush(candidates, (nums1[x] + nums2[y], x, y)) +``` + +* Ryotaro25のコード + * PR: https://github.com/Ryotaro25/leetcode_first60/pull/11 + * early returnをすると読みやすくなる。 + * if/else if ではなく、ifとcontinueでelse文を消して欲しい. + +* olsen-blueのコード + * PR: https://github.com/olsen-blue/Arai60/pull/10/ + * 毎回はheapに追加をしない関数に対して、`_if_necessary` や`maybe_heappush`という名前を使えると確かに読み手に優しい。 + * YukiMichishitaのコード * PR : https://github.com/YukiMichishita/LeetCode/pull/4/ * 二方向ではなく、一方向だけチェックすればよい。 -* https://github.com/nittoco/leetcode/pull/33/ - * +* エラーハンドリングについて + * Javascriptのdatstructure-js/priority-queueだと、空の状態でpopすると、nullが返ってくる。 + https://github.com/datastructures-js/heap/blob/master/src/heap.js#L208-L211 + +(変更前) + +```javascript + while (ans.length < k) { + const [i, j] = candidates.pop() + ans.push([nums1[i], nums2[j]]) + if (j + 1 < nums2.length) { + candidates.push([i, j + 1]) + } + } + return ans +``` + +(変更前) + +```javascript + while (ans.length < k) { + // UPDATED: エラーハンドリングを追加。 + if (candidates.size() === 0) { + // k個未満の要素しか存在しない場合には、 + // あるだけの要素を返すようにする。 + break + } + const [i, j] = candidates.pop() + ans.push([nums1[i], nums2[j]]) + if (j + 1 < nums2.length) { + candidates.push([i, j + 1]) + } + } + return ans +``` * https://github.com/TORUS0818/leetcode/pull/12/ ## その他の解法 -* LeetCodeの解法 (左上を基点として、右方向/下方向に伸びていく方法) +* (`*0`) LeetCodeの解法 (左上を基点として、右方向/下方向に伸びていく方法) 発想(手でやる) * 1. [0,0]を箱に入れる。 * 2. 最小の和となるペアを箱から取り出す。 @@ -226,7 +291,7 @@ const kSmallestPairs = function(nums1, nums2, k) { }; ``` -* setを使わずに解く方法 https://github.com/TORUS0818/leetcode/pull/12#discussion_r1623146530 +* (`*1`) setを使わずに解く方法 https://github.com/TORUS0818/leetcode/pull/12#discussion_r1623146530 ``` const kSmallestPairs = function(nums1, nums2, k) { @@ -286,10 +351,11 @@ const kSmallestPairs = function(nums1, nums2, k) { }; ``` -* ahayashiのPR に対するOdaのコメントを考慮した方法 +* (`*2`) ahayashiのPR に対するOdaのコメントを考慮した方法 * 参考: https://discord.com/channels/1084280443945353267/1200089668901937312/1222573940610695341 - * `add_to_heap_if_necessary(i + 1, j)`を関数化した方がよい - * (x - 1, y) と (x, y - 1) が両方 pairs の中にある、または、x, y どちらかが0でなければ、heap に足さなくていいとは思うんですよね。 + * 以下の2つのコメント + * `add_to_heap_if_necessary(i + 1, j)`を関数化した方がよい + * (x - 1, y) と (x, y - 1) が両方 pairs の中にある、または、x, y どちらかが0でなければ、heap に足さなくていいとは思うんですよね。 ```javascript const kSmallestPairs = function(nums1, nums2, k) { @@ -338,13 +404,175 @@ const kSmallestPairs = function(nums1, nums2, k) { }; ``` -* yield generatorを使った方法 +* (`*3`) yield generatorを使った方法 ```javascript +const kSmallestPairs = function(nums1, nums2, k) { + function sum(pair) { + const [i, j] = pair + return nums1[i] + nums2[j] + } + function* generator(j) { + if (j >= nums2.length) { + yield [Infinity, Infinity] + return + } + yield [0, j] + let i = 1 + // j+1行目以降の最小値と j行目の最小値を比較する。 + for (const next_row_pair of generator(j + 1)) { + if (next_row_pair[0] === Infinity) { + while (i < nums1.length) { + yield[i, j] + ++i + } + return + } + while (i < nums1.length && sum([i, j]) <= sum(next_row_pair)) { + yield [i, j] + ++i + } + yield next_row_pair + } + } + const ans = [] + const iterator = generator(0) + while (ans.length < k) { + const next = iterator.next() + if (next.done) { + break + } + const [i, j] = next.value + console.log(i, j) + ans.push([nums1[i], nums2[j]]) + } + return ans +}; ``` -* 右と下への探索ではなく、下方向のみにする方法もある。(右方向のみも可能) +* (`*4`) 右と下への探索ではなく、下方向のみにする方法もある。(右方向のみも可能) + * num1 が右方向に、 + * num2 が下方向に伸びていると考える。 ``` +// 下方向のみに探索する方法. +const kSmallestPairs = function(nums1, nums2, k) { + const candidates = new PriorityQueue((coord1, coord2) => { + const [i1, j1] = coord1 + const [i2, j2] = coord2 + return nums1[i1] + nums2[j1] - (nums1[i2] + nums2[j2]) + }) + for (const num1 in nums1) { + candidates.push([Number(num1), 0]) + } + + const ans = [] + while (ans.length < k) { + const [i, j] = candidates.pop() + ans.push([nums1[i], nums2[j]]) + if (j + 1 < nums2.length) { + candidates.push([i, j + 1]) + } + } + return ans +}; +``` + +* (`*5`) 分割統治法と再帰を用いて実装する方法 + +```javascript +var kSmallestPairs = function(nums1, nums2, k) { + function pair(i, j) { + return [i, j] + } + function sum(pair) { + const [i, j] = pair + return nums1[i] + nums2[j] + } + function* generateLine(j) { + for (let i = 0; i < nums1.length; i++) { + yield pair(i, j) + } + yield [Infinity, Infinity] + } + // j <= target < j_max + function* generateRange(j, j_max) { + if (j >= j_max) { + yield [Infinity, Infinity] + return + } + if (j === j_max - 1) { + const generator = generateLine(j) + while (true) { + const next = generator.next() + if (next.done) { + break + } + yield next.value + } + return + } + const j_middle = Math.floor((j + j_max) / 2) + const generator_former = generateRange(j, j_middle) + const generator_latter = generateRange(j_middle, j_max) + for (let i = j; i < j_middle; i++) { + const next = generator_former.next() + yield next.value + } + let former = generator_former.next() + let latter = generator_latter.next() + while (true) { + if (sum(former.value) <= sum(latter.value)) { + yield former.value + former = generator_former.next() + continue + } + yield latter.value + latter = generator_latter.next() + } + } + const ans = [] + const iterator = generateRange(0, nums2.length) + while (ans.length < k) { + const next = iterator.next() + if (next.done) { + break + } + const [i, j] = next.value + ans.push([nums1[i], nums2[j]]) + } + return ans +}; ``` +* (`*6`) iが0の時だけ、下方向に行き、それ以外は右方向を探索するという方法もある。 + * この方法だと、Setを使わなく良く、シンプルなため好み。 +``` +const kSmallestPairs = function(nums1, nums2, k) { + function pair(i, j) { + return [nums1[i], nums2[j]] + } + const top_k = new PriorityQueue((pair1, pair2) => { + const [i1, j1] = pair1 + const [i2, j2] = pair2 + return nums1[i1] + nums2[j1] - (nums1[i2] + nums2[j2]) + }) + top_k.push([0, 0]) + + const ans = [] + while (ans.length < k) { + if (top_k.size() === 0) { + break + } + const [i, j] = top_k.pop() + ans.push(pair(i, j)) + if (i === 0 && j + 1 < nums2.length) { + top_k.push([i, j + 1]) + } + if (i + 1 < nums1.length) { + top_k.push([i + 1, j]) + } + } + return ans +}; +``` From 6a2d8d507a63b31514ca64293b089050ee2ac371 Mon Sep 17 00:00:00 2001 From: shintaroyoshida20 Date: Mon, 5 May 2025 17:03:24 +0900 Subject: [PATCH 6/8] feat : #15 add the syntax highlight for javascript --- .../find-k-pairs-with-smallest-sums/answer.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md b/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md index 04ee424..fce625f 100644 --- a/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md +++ b/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md @@ -293,7 +293,7 @@ const kSmallestPairs = function(nums1, nums2, k) { * (`*1`) setを使わずに解く方法 https://github.com/TORUS0818/leetcode/pull/12#discussion_r1623146530 -``` +```javascript const kSmallestPairs = function(nums1, nums2, k) { // \ i_1, i_2, i_3, ... (nums1) // j_1 O O X @@ -454,7 +454,7 @@ const kSmallestPairs = function(nums1, nums2, k) { * num1 が右方向に、 * num2 が下方向に伸びていると考える。 -``` +```javascript // 下方向のみに探索する方法. const kSmallestPairs = function(nums1, nums2, k) { const candidates = new PriorityQueue((coord1, coord2) => { @@ -547,7 +547,8 @@ var kSmallestPairs = function(nums1, nums2, k) { * (`*6`) iが0の時だけ、下方向に行き、それ以外は右方向を探索するという方法もある。 * この方法だと、Setを使わなく良く、シンプルなため好み。 -``` + +```javascript const kSmallestPairs = function(nums1, nums2, k) { function pair(i, j) { return [nums1[i], nums2[j]] From 3b1757c1c88401a692b1365b3ff7a74cfdf4a205 Mon Sep 17 00:00:00 2001 From: shintaroyoshida20 Date: Mon, 5 May 2025 17:07:38 +0900 Subject: [PATCH 7/8] feat : #15 add the impression of the question --- .../find-k-pairs-with-smallest-sums/answer.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md b/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md index fce625f..68fea86 100644 --- a/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md +++ b/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md @@ -157,8 +157,10 @@ const kSmallestPairs = function(nums1, nums2, k) { ## 感想 -* 3回書く中で、頭の中が整理されてくる感覚を持つことができた。 -* マトリューシカのように外側から書くと書きやすい。 +* 3回書く際の工夫 + * 3回書くなかで、頭の中が整理されてくる感覚を初めて持つことができた。 + * コードを書く際に、マトリューシカのように外側(最初/最後)から書くと書きやすい。 +* yieldやsetを用いない方法など学びがすごく多い問題だった ### コメント集を読んで From 496d4d163ffafd95cdf32ee5504980f6ba40bd2c Mon Sep 17 00:00:00 2001 From: shintaroyoshida20 Date: Mon, 5 May 2025 23:42:49 +0900 Subject: [PATCH 8/8] feat : #15 add the syntax highlight for javascript code --- .../find-k-pairs-with-smallest-sums/answer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md b/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md index 68fea86..d2ef9b7 100644 --- a/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md +++ b/heap-and-priority-queue/find-k-pairs-with-smallest-sums/answer.md @@ -183,7 +183,7 @@ const kSmallestPairs = function(nums1, nums2, k) { * この関数がすごくわかりやすいと思った。 * 条件ではなく、関数の全体に意識をもっていくことができる。 -``` +```python def need_to_add(x, y): if x >= len(nums1) or y >= len(nums2): return False