[1..n]间的数,有的出现2次、有的1次、有的缺失,找重复的那些数(in-place算法)

vector<int> findDuplicates(vector<int>& nums) {
    // 把数x当作下标(1-based),将nums[x-1]标记为负数
    vector<int> ans;
    for (int num : nums) {
        int x = abs(num);
        if (nums[x-1] < 0) ans.push_back(x);
        else nums[x-1] *= -1;
    }
    return ans;
}

[1..n]间的数,有一个数重复、一个数缺失,找这两个数

同上的in-place算法

vector<int> findErrorNums(vector<int>& nums) {
    const int N = nums.size();
    int dup = -1, missing = -1;
    // 把数x当作下标(1-based),将nums[x-1]标记为负数
    for (int num : nums) {
        int x = abs(num);
        if (nums[x-1] < 0) {
            dup = x;
        } else {
            nums[x-1] *= -1;
        }
    }
    // 哪个下标位置仍是正数
    for (int i = 0; i < N; i++) {
        if (nums[i] > 0) missing = i + 1;
    }
    return {dup, missing};
}

或者用位操作

vector<int> findErrorNums(vector<int>& nums) {
    const int N = nums.size();
    int x = 0;
    for (int num : nums) x ^= num;
    for (int i = 1; i <= N; i++) x ^= i;
    // x = duplicate^missing
    int lastBit = x & -x;
    int xor0 = 0, xor1 = 0;
    for (int num : nums) {
        if (num & lastBit) xor1 ^= num;
        else xor0 ^= num;
    }
    for (int i = 1; i <= N; i++) {
        if (i & lastBit) xor1 ^= i;
        else xor0 ^= i;            
    } 
    // xor0和xor1 是 duplicate和missing,不知哪个是哪个
    for (int num : nums) {
        if (num == xor0) {
            return { xor0, xor1 };
        }
    }
    return { xor1, xor0 };
}

长为n的数组中放[1..n]间的数,有的出现多次、有的缺失,in-place统计各出现的次数

vector<int> statArray(vector<int> &nums) {
    // 把数x当作下标(1-based),在下标处计数nums[x-1]++,计数最多增N;
    // 为不影响nums[x-1]原先的值,先将所有数*=(N+1),
    // 这时数x的下标处计数为nums[x/(N+1)-1]++。
    const int N = nums.size();
    for (int &x : nums) {
        x *= (N + 1);
    }
    for (int x : nums) {
        nums[x / (N + 1) - 1]++;
    }

    vector<int> ans;
    for (int x : nums) {
        // x/(N+1) => nums[x/(N+1)-1]%(N+1)
        ans.push_back(nums[x / (N + 1) - 1] % (N + 1));
    }
    return ans;
}

长为n+1的数组中放[1,n]间的数,至少有个数重复,找任一重复的数

不修改数组的 快慢指针法

是否有m长子段连续重复k次

bool containsPattern(vector<int>& arr, int m, int k) {
    // 是否有m长子段连续重复k次
    const int N = arr.size();
    int count = 0;
    for (int i = 0; i + m < N; i++) {
        if (arr[i] != arr[i+m]) {
            count = 0;
        } else {
            count++;
            if (count == m * (k-1)) return true;
        }
    }
    return false;
}