板子:删除所有值为 x 的元素(k 计数法)
用
k记「已经保留下来的元素个数」。扫一遍,不是x的就放到A[k]。一趟扫描完成,原来的相对次序不变。
代码
void delX(int A[], int &n, int x) {
int k = 0; // k:保留下来的元素个数,A[0..k-1] 是结果
for (int i = 0; i < n; i++)
if (A[i] != x) A[k++] = A[i]; // 不是 x 就留下;k <= i,不会覆盖还没扫到的元素
n = k; // 更新长度,所以参数是 int &n
}
void delX(SqList &L, int x) { // 顺序表版本,只是改了名字
int k = 0;
for (int i = 0; i < L.length; i++)
if (L.data[i] != x) L.data[k++] = L.data[i];
L.length = k;
}复杂度:时间
本质:按条件过滤
把 A[i] != x 换成任何「要保留的条件」,就能解一类题:
| 题目 | 保留条件 |
|---|---|
| 删除所有值为 | A[i] != x |
| 删除值在 | A[i] < s 或 A[i] > t |
| 删除所有负数 | A[i] >= 0 |
| 有序表去重 | A[i] != A[k-1],见 有序表去重与合并 |
另一种等价写法是用 k 记已删除的个数,每个保留的元素前移 k 位:A[i-k] = A[i]。
易错点
- 不要找到一个就删一个、再把后面整体前移,那样是
。 - 最后要更新长度
n = k,所以参数必须写成int &n。 - 有序表删除
也可以先二分找到这一段再整体前移,但 k 计数法对有序表、无序表都能用,考场首选。