Skip to content

Commit 149a30c

Browse files
committed
Add: Add 2025/11/24
1 parent 8416d29 commit 149a30c

File tree

3 files changed

+155
-0
lines changed

3 files changed

+155
-0
lines changed
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# 1018. Binary Prefix Divisible By 5
2+
3+
You are given a binary array `nums` (0-indexed).
4+
5+
We define `x_i` as the number whose binary representation is the subarray `nums[0..i]` (from most-significant-bit to least-significant-bit).
6+
7+
- For example, if `nums = [1,0,1]`, then `x_0 = 1`, `x_1 = 2`, and `x_2 = 5`.
8+
9+
Return an array of booleans `answer` where `answer[i]` is `true` if `x_i` is divisible by `5`.
10+
11+
**Constraints:**
12+
13+
- `1 <= nums.length <= 10^5`
14+
- `nums[i]` is either `0` or `1`.
15+
16+
## 基礎思路
17+
18+
本題給定一個二元陣列 `nums`,其前綴子陣列 `nums[0..i]` 代表一個從最高位到最低位的二進位整數 `x_i`
19+
我們需要判斷每個 `x_i` 是否能被 5 整除。
20+
21+
要注意的幾個重點:
22+
23+
- **輸入長度最大可達 10^5,無法將整個前綴轉成大整數再判斷**,因為數值會極度膨脹。
24+
- **二進位左移相當於乘以 2**,因此可用逐步更新方式維護前綴值。
25+
- **只需要前綴值 `mod 5`**:因為判斷是否可被 5 整除,只需知道餘數是否為 0。
26+
- **模運算可維持在小範圍(0–4)**,避免 expensive 的 `%` 運算。
27+
- 每次計算只需要:
28+
29+
- 將前綴值左移(乘以 2)
30+
- 加上目前位元
31+
- 並維持在 `mod 5` 範圍
32+
33+
這樣可以線性時間完成所有前綴的可整除性判斷。
34+
35+
## 解題步驟
36+
37+
### Step 1:初始化結果陣列與前綴餘數狀態
38+
39+
建立用來存放結果的布林陣列,並準備 `prefixModulo` 來追蹤前綴值對 5 的餘數。
40+
41+
```typescript
42+
const length = nums.length;
43+
const result: boolean[] = new Array(length);
44+
45+
// 追蹤目前前綴值對 5 的餘數
46+
let prefixModulo = 0;
47+
```
48+
49+
### Step 2:主迴圈 — 依序處理每一個 bit
50+
51+
逐一讀取 `nums[index]` 作為目前位元,並依據二進位特性更新前綴餘數。
52+
53+
```typescript
54+
for (let index = 0; index < length; index++) {
55+
const currentBit = nums[index];
56+
57+
// ...
58+
}
59+
```
60+
61+
### Step 3:更新前綴值(透過位移與加法)
62+
63+
二進位前綴的更新方式為:
64+
**前綴 × 2 + 當前 bit**
65+
使用左位移以提升效率。
66+
67+
```typescript
68+
for (let index = 0; index < length; index++) {
69+
// Step 2:主迴圈 — 依序處理每一個 bit
70+
71+
// 更新前綴:左移一位(乘以 2)再加上目前位元
72+
prefixModulo = (prefixModulo << 1) + currentBit;
73+
74+
// ...
75+
}
76+
```
77+
78+
### Step 4:維持前綴餘數於 0~4 範圍(避免 expensive 模運算)
79+
80+
若前綴餘數 ≥ 5,扣除 5 即等同於 `% 5`
81+
82+
```typescript
83+
for (let index = 0; index < length; index++) {
84+
// Step 2:主迴圈 — 依序處理每一個 bit
85+
86+
// Step 3:更新前綴值(位移 + 加法)
87+
88+
// 將 prefixModulo 維持在 [0, 4] 範圍,不使用 costly 的 % 運算
89+
if (prefixModulo >= 5) {
90+
prefixModulo -= 5;
91+
}
92+
93+
// ...
94+
}
95+
```
96+
97+
### Step 5:紀錄當前前綴是否可被 5 整除
98+
99+
若當前餘數為 0,表示目前前綴值可被 5 整除。
100+
101+
```typescript
102+
for (let index = 0; index < length; index++) {
103+
// Step 2:主迴圈 — 依序處理每一個 bit
104+
105+
// Step 3:更新前綴值(位移 + 加法)
106+
107+
// Step 4:維持前綴餘數於 0~4 範圍
108+
109+
// 判斷前綴是否可被 5 整除
110+
result[index] = prefixModulo === 0;
111+
}
112+
113+
return result;
114+
```
115+
116+
## 時間複雜度
117+
118+
- 每個元素僅被處理一次,所有更新皆為常數時間。
119+
- 總時間複雜度為 $O(n)$。
120+
121+
> $O(n)$
122+
123+
## 空間複雜度
124+
125+
- 需輸出長度為 n 的 `boolean[]`,其餘變數為常數額外空間。
126+
- 總空間複雜度為 $O(n)$。
127+
128+
> $O(n)$
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
function prefixesDivBy5(nums: number[]): boolean[] {
2+
const length = nums.length;
3+
const result: boolean[] = new Array(length);
4+
5+
// Keep track of the current prefix value modulo 5
6+
let prefixModulo = 0;
7+
8+
for (let index = 0; index < length; index++) {
9+
const currentBit = nums[index];
10+
11+
// Update prefix: multiply by 2 using bit shift and add current bit
12+
prefixModulo = (prefixModulo << 1) + currentBit;
13+
14+
// Keep the prefixModulo in [0, 4] without using costly modulo operator
15+
if (prefixModulo >= 5) {
16+
prefixModulo -= 5;
17+
}
18+
19+
// Record whether current prefix value is divisible by 5
20+
result[index] = prefixModulo === 0;
21+
}
22+
23+
return result;
24+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
function prefixesDivBy5(nums: number[]): boolean[] {
2+
3+
}

0 commit comments

Comments
 (0)