指標之間 題解
指標之間 題解
簡潔題意
實作 int count_between(int *a, int *b);。兩個指標指向同一個陣列中的元素,請回傳兩個位置中間夾了幾個元素,不含兩個端點。指標的先後順序不保證。
這一題完全不用碰值
交換指標指向的整數 練的是用 *a 改到位置上的值。這一題相反:值長什麼樣子完全不重要,要算的是兩個位置離多遠。
11.2 教過,同一個陣列裡的兩個指標可以相減,而且相減的單位是元素個數,不是位元組:
int a[10];
int *p = &a[2];
int *q = &a[7];
cout << q - p << '\n'; // 5
q - p 是 \(5\),意思是「從 p 走到 q 要跨 \(5\) 步」。
從距離到答案
拿範例 1 的第一筆來看:兩個指標指向第 \(2\) 格與第 \(5\) 格,距離是 \(3\),中間夾的是第 \(3\)、第 \(4\) 格共 \(2\) 個。
距離 \(3\)、答案 \(2\)——跨過去的每一步都會踩過一個新格子,但最後那一步踩到的是端點本身,不能算。所以答案是距離減 \(1\)。
兩個特殊情況順著這個想法就通了:
- 相鄰兩格:距離 \(1\),減 \(1\) 得 \(0\),中間確實沒東西(範例 1 第二筆)。
- 同一格:距離 \(0\),這時候不能再減 \(1\),答案直接是 \(0\)(範例 1 第三筆)。
最後一件事:題目沒保證 a 在 b 左邊。a - b 可能是負的,先把它變成非負再往下算。
每次呼叫只做固定次數的運算,時間複雜度 \(O(1)\)。
參考程式碼
int count_between(int *a, int *b) {
int distance = a - b; // 兩個位置之間差幾格
if (distance < 0) {
distance = -distance; // 不管誰在左邊,距離都當成正的
}
if (distance == 0) {
return 0; // 指向同一格,中間夾 0 個
}
return distance - 1; // 扣掉「跨過去那一步」
}
常犯錯誤
- 回傳距離本身,忘了減 \(1\):範例 1 第一筆會印
3,正解是2。 - 直接寫
b - a - 1:假設了a一定在左邊。範例 2 第一筆(第 \(9\) 格與第 \(2\) 格)印出-8;而且兩個指標指同一格時會得到-1,範例 1 第三筆就掛了。 - 拿
*a - *b相減:那是兩個格子裡的數字相減。格子裡放的是什麼數字,跟它排在第幾格是兩回事,評分程式也不會讓它們剛好相等——範例 1 第一筆會印出110。
接下來
到這裡,指標的兩個基本動作都用過了:*p 取值寫值、指標相減算距離。指標陣列加總 會把「位置」本身當成資料存進陣列裡——那裡的每一格存的都是一個門牌號碼。