Skip to content

Commit 3c29740

Browse files
committed
Add: Add 2025/10/28
1 parent 3f5f606 commit 3c29740

File tree

3 files changed

+159
-0
lines changed

3 files changed

+159
-0
lines changed
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# 3354. Make Array Elements Equal to Zero
2+
3+
You are given an integer array `nums`.
4+
5+
Start by selecting a starting position `curr` such that `nums[curr] == 0`, and choose a movement direction of either left or right.
6+
7+
After that, you repeat the following process:
8+
9+
- If `curr` is out of the `range [0, n - 1]`, this process ends.
10+
- If `nums[curr] == 0`, move in the current direction by incrementing `curr` if you are moving right, or decrementing `curr` if you are moving left.
11+
- Else if `nums[curr] > 0`:
12+
- Decrement `nums[curr]` by 1.
13+
- Reverse your movement direction (left becomes right and vice versa).
14+
- Take a step in your new direction.
15+
A selection of the initial position `curr` and movement direction is considered valid if every element in `nums` becomes 0 by the end of the process.
16+
17+
Return the number of possible valid selections.
18+
19+
**Constraints:**
20+
21+
- `1 <= nums.length <= 100`
22+
- `0 <= nums[i] <= 100`
23+
- There is at least one element `i` where `nums[i] == 0`.
24+
25+
## 基礎思路
26+
27+
本題要求我們判斷從哪些起始位置與方向出發,最終能使陣列 `nums` 的所有元素都歸零。
28+
29+
整個模擬過程如下:
30+
31+
1. 選擇一個初始位置 `curr`,且該位置的值必須為 `0`
32+
2. 選擇移動方向(向左或向右)。
33+
3. 不斷重複以下動作直到 `curr` 超出邊界:
34+
-`nums[curr] == 0`,則在當前方向上前進一步;
35+
-`nums[curr] > 0`,則先將該值減一、反轉移動方向,再前進一步。
36+
37+
我們要找出所有「能使最終所有元素變為 0」的初始 `(curr, direction)` 配置。
38+
39+
在理解過程後,可以發現直接模擬所有情況的成本太高(每次都會改變陣列內容)。因此必須尋找**規律性條件**
40+
41+
- 假設整體數組中有 `totalSum` 代表所有元素的總和;
42+
- 當我們從左側移動到右側時,左側累積的和(`leftSum`)逐漸增加;
43+
- 若以 `i` 為起點,則左側的能量與右側的能量差應該平衡,否則不可能讓整體歸零。
44+
45+
於是可以導出條件:
46+
47+
-`nums[i] == 0` 時,計算 `difference = |2 * leftSum - totalSum|`
48+
- 若差值為 `0`,代表左右能量平衡,可以往**左右兩邊**出發;
49+
- 若差值為 `1`,代表左右能量相差一單位,只能往其中一側出發;
50+
- 其他情況無法平衡。
51+
52+
藉此即可在單次線性掃描中,統計所有合法起始選項。
53+
54+
## 解題步驟
55+
56+
### Step 1:初始化變數與計算總和
57+
58+
首先遍歷整個陣列,計算 `totalSum`(代表所有元素總量),並建立一個變數 `leftSum` 來累積左側部分的和。
59+
60+
```typescript
61+
// 取得陣列長度
62+
const length = nums.length;
63+
64+
// 計算所有元素總和
65+
let totalSum = 0;
66+
for (let i = 0; i < length; i++) {
67+
totalSum += nums[i];
68+
}
69+
70+
// 統計合法選擇數量
71+
let totalValidSelections = 0;
72+
73+
// 累計左側前綴和
74+
let leftSum = 0;
75+
```
76+
77+
### Step 2:逐一檢查每個可能起始點
78+
79+
僅在 `nums[i] == 0` 的情況下檢查,因為題目明確要求初始位置必須為零。
80+
81+
```typescript
82+
for (let i = 0; i < length; i++) {
83+
// 只考慮數值為 0 的位置作為起點
84+
if (nums[i] === 0) {
85+
// 計算左右區域能量差異
86+
const difference = Math.abs(2 * leftSum - totalSum);
87+
88+
// 若差值 <= 1,則可能為合法起始組合
89+
// 差值 = 0 → 可向左右兩邊出發 (加 2)
90+
// 差值 = 1 → 只可向一側出發 (加 1)
91+
if (difference <= 1) {
92+
totalValidSelections += 2 - difference;
93+
}
94+
}
95+
96+
// 每輪更新左側和,為下一次迭代做準備
97+
leftSum += nums[i];
98+
}
99+
```
100+
101+
### Step 3:返回最終結果
102+
103+
掃描結束後,所有可能起始組合的數量即為答案。
104+
105+
```typescript
106+
// 回傳總合法起始配置數量
107+
return totalValidSelections;
108+
```
109+
110+
## 時間複雜度
111+
112+
- 一次遍歷求總和為 $O(n)$;
113+
- 再次線性掃描以檢查所有位置,亦為 $O(n)$;
114+
- 所有操作皆為常數級運算。
115+
- 總時間複雜度為 $O(n)$。
116+
117+
> $O(n)$
118+
119+
## 空間複雜度
120+
121+
- 只使用了常數級變數(`totalSum`, `leftSum`, `difference` 等);
122+
- 未使用額外陣列或輔助結構。
123+
- 總空間複雜度為 $O(1)$。
124+
125+
> $O(1)$
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
function countValidSelections(nums: number[]): number {
2+
const length = nums.length;
3+
4+
// Compute total sum of all elements
5+
let totalSum = 0;
6+
for (let i = 0; i < length; i++) {
7+
totalSum += nums[i];
8+
}
9+
10+
let totalValidSelections = 0;
11+
let leftSum = 0; // Running sum of elements to the left
12+
13+
for (let i = 0; i < length; i++) {
14+
// Check only positions where value is zero
15+
if (nums[i] === 0) {
16+
// Compute the difference between left and right sums
17+
const difference = Math.abs(2 * leftSum - totalSum);
18+
19+
// Valid if difference <= 1 (add 2 for diff=0, add 1 for diff=1)
20+
if (difference <= 1) {
21+
totalValidSelections += 2 - difference;
22+
}
23+
}
24+
25+
// Update prefix sum including current element
26+
leftSum += nums[i];
27+
}
28+
29+
// Return total number of valid selections
30+
return totalValidSelections;
31+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
function countValidSelections(nums: number[]): number {
2+
3+
}

0 commit comments

Comments
 (0)