|
56 | 56 |
|
57 | 57 | <!-- 这里可写通用的实现逻辑 -->
|
58 | 58 |
|
| 59 | +**方法一:逆向构造 + 优先队列(大根堆)** |
| 60 | + |
| 61 | +我们发现,如果从数组 $arr$ 开始正向构造目标数组 $target$,每次都不好确定选择哪个下标 $i$,问题比较复杂。而如果我们从数组 $target$ 开始逆向构造,每次构造都一定是选择当前数组中最大的元素,这样就可以保证每次构造都是唯一的,问题比较简单。 |
| 62 | + |
| 63 | +因此,我们可以使用优先队列(大根堆)来存储数组 $target$ 中的元素,用一个变量 $s$ 记录数组 $target$ 中所有元素的和。每次从优先队列中取出最大的元素 $mx$,计算当前数组中除 $mx$ 以外的所有元素之和 $t$,如果 $t \lt 1$ 或者 $mx - t \lt 1$,则说明无法构造目标数组 $target$,返回 `false`。否则,我们计算 $mx \bmod t$,如果 $mx \bmod t = 0$,则令 $x = t$,否则令 $x = mx \bmod t$,将 $x$ 加入优先队列中,并更新 $s$ 的值,重复上述操作,直到优先队列中的所有元素都变为 $1$,此时返回 `true`。 |
| 64 | + |
| 65 | +时间复杂度 $O(n \log n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $target$ 的长度。 |
| 66 | + |
59 | 67 | <!-- tabs:start -->
|
60 | 68 |
|
61 | 69 | ### **Python3**
|
|
65 | 73 | ```python
|
66 | 74 | class Solution:
|
67 | 75 | def isPossible(self, target: List[int]) -> bool:
|
68 |
| - if len(target) == 1: |
69 |
| - return target[0] == 1 |
70 |
| - |
71 |
| - summ = sum(target) |
72 |
| - maxHeap = [-num for num in target] |
73 |
| - heapq.heapify(maxHeap) |
74 |
| - |
75 |
| - while -maxHeap[0] > 1: |
76 |
| - maxi = -heapq.heappop(maxHeap) |
77 |
| - restSum = summ - maxi |
78 |
| - # Only occurs if n == 2. |
79 |
| - if restSum == 1: |
80 |
| - return True |
81 |
| - updated = maxi % restSum |
82 |
| - # Updated == 0 (invalid) or didn't change. |
83 |
| - if updated == 0 or updated == maxi: |
| 76 | + s = sum(target) |
| 77 | + pq = [-x for x in target] |
| 78 | + heapify(pq) |
| 79 | + while -pq[0] > 1: |
| 80 | + mx = -heappop(pq) |
| 81 | + t = s - mx |
| 82 | + if t == 0 or mx - t < 1: |
84 | 83 | return False
|
85 |
| - heapq.heappush(maxHeap, -updated) |
86 |
| - summ = summ - maxi + updated |
87 |
| - |
| 84 | + x = (mx % t) or t |
| 85 | + heappush(pq, -x) |
| 86 | + s = s - mx + x |
88 | 87 | return True
|
89 |
| - |
90 | 88 | ```
|
91 | 89 |
|
92 | 90 | ### **Java**
|
93 | 91 |
|
94 | 92 | <!-- 这里可写当前语言的特殊实现逻辑 -->
|
95 | 93 |
|
96 | 94 | ```java
|
| 95 | +class Solution { |
| 96 | + public boolean isPossible(int[] target) { |
| 97 | + PriorityQueue<Long> pq = new PriorityQueue<>(Collections.reverseOrder()); |
| 98 | + long s = 0; |
| 99 | + for (int x : target) { |
| 100 | + s += x; |
| 101 | + pq.offer((long) x); |
| 102 | + } |
| 103 | + while (pq.peek() > 1) { |
| 104 | + long mx = pq.poll(); |
| 105 | + long t = s - mx; |
| 106 | + if (t == 0 || mx - t < 1) { |
| 107 | + return false; |
| 108 | + } |
| 109 | + long x = mx % t; |
| 110 | + if (x == 0) { |
| 111 | + x = t; |
| 112 | + } |
| 113 | + pq.offer(x); |
| 114 | + s = s - mx + x; |
| 115 | + } |
| 116 | + return true; |
| 117 | + } |
| 118 | +} |
| 119 | +``` |
| 120 | + |
| 121 | +### **C++** |
| 122 | + |
| 123 | +```cpp |
| 124 | +class Solution { |
| 125 | +public: |
| 126 | + bool isPossible(vector<int>& target) { |
| 127 | + priority_queue<int> pq; |
| 128 | + long long s = 0; |
| 129 | + for (int i = 0; i < target.size(); i++) { |
| 130 | + s += target[i]; |
| 131 | + pq.push(target[i]); |
| 132 | + } |
| 133 | + while (pq.top() != 1) { |
| 134 | + int mx = pq.top(); |
| 135 | + pq.pop(); |
| 136 | + long long t = s - mx; |
| 137 | + if (t < 1 || mx - t < 1) { |
| 138 | + return false; |
| 139 | + } |
| 140 | + int x = mx % t; |
| 141 | + if (x == 0) { |
| 142 | + x = t; |
| 143 | + } |
| 144 | + pq.push(x); |
| 145 | + s = s - mx + x; |
| 146 | + } |
| 147 | + return true; |
| 148 | + } |
| 149 | +}; |
| 150 | +``` |
| 151 | +
|
| 152 | +### **Go** |
| 153 | +
|
| 154 | +```go |
| 155 | +func isPossible(target []int) bool { |
| 156 | + pq := &hp{target} |
| 157 | + s := 0 |
| 158 | + for _, x := range target { |
| 159 | + s += x |
| 160 | + } |
| 161 | + heap.Init(pq) |
| 162 | + for target[0] > 1 { |
| 163 | + mx := target[0] |
| 164 | + t := s - mx |
| 165 | + if t < 1 || mx-t < 1 { |
| 166 | + return false |
| 167 | + } |
| 168 | + x := mx % t |
| 169 | + if x == 0 { |
| 170 | + x = t |
| 171 | + } |
| 172 | + target[0] = x |
| 173 | + heap.Fix(pq, 0) |
| 174 | + s = s - mx + x |
| 175 | + } |
| 176 | + return true |
| 177 | +} |
| 178 | +
|
| 179 | +type hp struct{ sort.IntSlice } |
| 180 | +
|
| 181 | +func (h hp) Less(i, j int) bool { return h.IntSlice[i] > h.IntSlice[j] } |
| 182 | +func (hp) Pop() (_ any) { return } |
| 183 | +func (hp) Push(any) {} |
| 184 | +``` |
97 | 185 |
|
| 186 | +### **TypeScript** |
| 187 | + |
| 188 | +```ts |
| 189 | +function isPossible(target: number[]): boolean { |
| 190 | + const pq = new MaxPriorityQueue(); |
| 191 | + let s = 0; |
| 192 | + for (const x of target) { |
| 193 | + s += x; |
| 194 | + pq.enqueue(x); |
| 195 | + } |
| 196 | + while (pq.front().element > 1) { |
| 197 | + const mx = pq.dequeue().element; |
| 198 | + const t = s - mx; |
| 199 | + if (t < 1 || mx - t < 1) { |
| 200 | + return false; |
| 201 | + } |
| 202 | + const x = mx % t || t; |
| 203 | + pq.enqueue(x); |
| 204 | + s = s - mx + x; |
| 205 | + } |
| 206 | + return true; |
| 207 | +} |
98 | 208 | ```
|
99 | 209 |
|
100 | 210 | ### **...**
|
|
0 commit comments