|
| 1 | +# 1726. Tuple with Same Product |
| 2 | + |
| 3 | +Given an array `nums` of distinct positive integers, |
| 4 | +return the number of tuples `(a, b, c, d)` such that `a * b = c * d` where |
| 5 | +`a`, `b`, `c`, and `d` are elements of `nums`, and `a != b != c != d`. |
| 6 | + |
| 7 | +## 基礎思路 |
| 8 | +利用暴力枚舉所有兩兩組合的方式,記錄每個乘積出現的次數,並在遇到重複乘積時,根據已經出現的次數計算出可以構成多少個新的四元組。 |
| 9 | +由於每兩組數對可以產生 8 種排列,所以每次發現重複乘積時,都會將計數器增加 8 乘上(已出現次數 + 1)。 |
| 10 | + |
| 11 | +> Tips |
| 12 | +> `A`, `B`, `C`, `D` 會有 8 種排列組合,因為會有 2 組 `A與B`、`C與D`,其排列是 2! * 2! = 4。 |
| 13 | +> 而 `A與B` 與 `C與D` 也可以交換位置,所以是 4 * 2! = 8。 |
| 14 | +
|
| 15 | +## 解題步驟 |
| 16 | + |
| 17 | +### Step 1: 初始化變數 |
| 18 | + |
| 19 | +```typescript |
| 20 | +const n = nums.length; // 輸入陣列長度 |
| 21 | +const productMap = new Map<number, number>(); // 乘積與出現次數的對應表 |
| 22 | +``` |
| 23 | + |
| 24 | +### Step 2: 枚舉所有兩兩組合 |
| 25 | + |
| 26 | +```typescript |
| 27 | +let count = 0; |
| 28 | +for (let i = 0; i < n; i++) { |
| 29 | + for (let j = i + 1; j < n; j++) { |
| 30 | + // 計算該對數字的乘積 |
| 31 | + const product = nums[i] * nums[j]; |
| 32 | + |
| 33 | + /* |
| 34 | + 當前這一對的乘積 product 已經在之前出現過了多少次,就代表之前有這麼多對 (a, b) |
| 35 | + 滿足 a * b = product。新的這一對 (nums[i], nums[j]) 與之前每一對組合起來, |
| 36 | + 都可以形成一組滿足條件的四元組 (因為兩對數字的乘積相等)。 |
| 37 | + 而每組兩對數字可以排列出 8 種不同的 tuple,所以增加的計數就是 8 * (目前 product 在 map 中已經出現的次數) |
| 38 | + */ |
| 39 | + count += 8 * (productMap.get(product) || 0); |
| 40 | + |
| 41 | + // 更新 productMap:將當前乘積 product 出現的次數增加 1 |
| 42 | + productMap.set(product, (productMap.get(product) || 0) + 1); |
| 43 | + } |
| 44 | +} |
| 45 | +``` |
| 46 | + |
| 47 | +## 時間複雜度 |
| 48 | +- 需要比對所有兩兩組合,所以時間複雜度為 $O(n^2)$ |
| 49 | +- 總體時間複雜度為 $O(n^2)$ |
| 50 | + |
| 51 | +> $O(n^2)$ |
| 52 | +
|
| 53 | +## 空間複雜度 |
| 54 | +- 在最壞情況下,假如每一對數字所計算出的乘積都是唯一的,那麼 productMap 中就會有 $O(n^2)$ 個不同的鍵值對。 |
| 55 | +- 總體空間複雜度為 $O(n^2)$ |
| 56 | + |
| 57 | +> $O(n^2)$ |
0 commit comments