📘 題目敘述
給你一個整數陣列 nums。
請回傳一個整數,表示在
nums
中第一個出現且只出現一次的偶數(也就是陣列 index
最小的那個)。
如果不存在這樣的數字,請回傳 -1。
如果整數 x 可以被 2 整除,則稱它是偶數。
條件限制
1 <= nums.length <= 1001 <= nums[i] <= 100
🧠 解題思路
這題的重點有兩個:
- 這個數字要是偶數
- 這個偶數在整個陣列中只出現一次,而且要回傳最前面的那個
所以我這份寫法分成兩步:
第一步先統計每個偶數出現幾次。
因為題目限制 nums[i] <= 100,所以我直接開一個大小為
101 的陣列 count,用
count[x] 記錄數字 x 出現幾次。
不過我只統計偶數,所以如果某個數字是奇數,就直接跳過。
第二步再照原本 nums 的順序掃一次。
因為題目要的是「第一個」只出現一次的偶數,所以一定要照原陣列順序檢查。
只要遇到某個 j 滿足:
j是偶數count[j] == 1
那它就是答案,直接回傳。
也就是說,這題的核心就是:
先統計每個偶數出現次數,再照原本順序找第一個出現次數剛好為 1 的偶數。
所有變數
-
count[101]:記錄每個數字出現次數的陣列,這份程式只會累計偶數
🪜 主要流程步驟
1. 先開一個 count 陣列記錄每個數字出現幾次
int count[101] = {0};
因為題目保證 nums[i] 介於
1 ~ 100,所以我可以直接開一個大小為
101 的陣列。
這樣就能直接用:
count[2]count[4]count[6]
這種方式記錄某個數字出現幾次。
2. 第一次掃描,只統計偶數出現次數
for (int i : nums) {
if (i % 2 == 0) {
count[i]++;
}
}
這一步是在做次數統計。
如果 i 是偶數,就把它對應的
count[i] 加一。
如果 i 是奇數,就不處理,因為題目只在乎偶數。
做完這一步後:
count[x] == 0表示偶數x沒出現-
count[x] == 1表示偶數x恰好出現一次 -
count[x] > 1表示偶數x出現超過一次
3. 第二次掃描,照原本順序找第一個只出現一次的偶數
for (int j : nums) {
if (count[j] == 1) {
return j;
}
}
這一步是整題最重要的地方。
因為題目要的是:
- 第一個
- 只出現一次的
- 偶數
所以不能只看數值大小,而是要照原本陣列順序掃。
這樣一來,當我第一次遇到某個 j 滿足
count[j] == 1
時,它就是最早出現、而且只出現一次的那個答案。
4. 為什麼這裡不用再另外判斷一次偶數
這份程式第二次掃描時只有寫:
if (count[j] == 1)
沒有再補一個 j % 2 == 0。
原因是:
第一輪統計時,我只有對偶數做 count[i]++。
所以奇數的 count[j] 會一直維持
0,不可能等於 1。
因此第二輪只判斷
count[j] == 1 就夠了,能進來的自然只會是偶數。
5. 如果整個陣列都找不到,就回傳 -1
return -1;
如果第二次掃描整個 nums 都沒有遇到
count[j] == 1 的情況,
就代表不存在只出現一次的偶數,所以答案是 -1。
⏱️ 複雜度
設 n = nums.length。
-
時間複雜度:
O(n)
兩次掃描陣列,各是O(n)。 -
空間複雜度:
O(1)
count的大小固定為101,不會隨n增加。
💻 程式碼實作
class Solution {
public:
int firstUniqueEven(vector<int>& nums) {
int count[101] = {0};
for (int i : nums) {
if (i % 2 == 0) {
count[i]++;
}
}
for (int j : nums) {
if (count[j] == 1) {
return j;
}
}
return -1;
}
};