數組是最基礎的數據結構,也是面試與算法競賽的高頻考點。本文匯總了十餘道經典數組問題,涵蓋遞歸、分治、位運算、雙指針、二分查找、滑動窗口等核心技巧,並提供 C/C++ 風格的參考實現,幫助你建立完整的解題思維框架。
題目:給定含 n 個整數的數組,僅用一行遞歸代碼求和。
思路:邊界條件 n=0 返回 0;否則返回前 n-1 項和加上第 n 項。
代碼:
int sum(int *a, int n) {
return n == 0 ? 0 : sum(a, n - 1) + a[n - 1];
}
題目:求數組最大值與最小值。
思路:將數組二分,遞歸求左右半部的極值,再合併。將比較次數從 2n-2 降至約 1.5n。
代碼:
void MaxMin(int *a, int l, int r, int &maxV, int &minV) {
if (l == r) { maxV = minV = a[l]; return; }
if (l + 1 == r) {
if (a[l] >= a[r]) { maxV = a[l]; minV = a[r]; }
else { maxV = a[r]; minV = a[l]; }
return;
}
int m = (l + r) / 2;
int lmax, lmin, rmax, rmin;
MaxMin(a, l, m, lmax, lmin);
MaxMin(a, m+1, r, rmax, rmin);
maxV = max(lmax, rmax);
minV = min(lmin, rmin);
}
題目:求最大值與第二大值。
思路:同分治,合併時比較左右兩組的最大值,較大者為整體最大值,另一組的最大值與較小組的最大值比較得出次大值。
代碼關鍵合併邏輯:
max = leftmax > rightmax ? leftmax : rightmax;
second = leftmax < rightmax ? leftmax : rightmax; // 此處需嚴謹處理邊界
題目:數組中某元素出現 > n/2 次,找出該元素。
思路:維護候選值與計數器,相同則+1,不同則-1,歸零時換候選。最終候選即為答案。
代碼:
int FindMajority(int* a, int n) {
int cand = a[0], cnt = 1;
for (int i = 1; i < n; ++i) {
if (a[i] == cand) ++cnt;
else if (--cnt < 0) { cand = a[i]; cnt = 1; }
}
return cand; // 題目保證存在,無需二次驗證
}
備選:排序後取中位數 a[n/2],時間 O(n log n)。
題目:找出兩元素差值絕對值最小的數對。
思路:排序後,最小差值必出現在相鄰元素間。單次遍歷即可。
代碼:
void MinDistance(int* a, int n) {
qsort(a, n, sizeof(int), cmp);
int minD = INT_MAX, x, y;
for (int i = 0; i < n-1; ++i) {
if (a[i+1] - a[i] < minD) {
minD = a[i+1] - a[i];
x = a[i]; y = a[i+1];
}
}
}
1. 公共元素:兩指針 i,j 分別指向兩有序數組頭部,小者前進,相等則輸出並雙進。O(n)。
2. 固定和數對:一指針指頭,一指尾,根據和與目標值大小移動指針。O(n)。
int r = 0; for (int x : a) r ^= x;最大子段和 (Kadane 算法):維護以當前元素結尾的最大和 cur 及全局最大和 ans。cur = max(0, cur + a[i]); ans = max(ans, cur);
最大子段積:需同時維護當前最大正積與最小負積,遇負數交換兩者。見文中完整代碼。
從 n 中選 m,經典 DFS 回溯,利用 buffer 記錄當前路徑,IsValid 保證遞增順序避免重複。
數組題核心模式有限:有序→二分/雙指針;無序→排序+二分/哈希/位運算。熟練掌握分治、雙指針、位運算、動態規劃、回溯等範式,配合邊界條件處理,即可迎刃而解絕大多數數組問題。