Missing Number--^异或位运算--leetcode

Given an array containing n distinct numbers taken from 0, 1, 2, …, n, find the one that is missing from the array.
For example,
Given nums = [0, 1, 3] return 2.
Note:
Your algorithm should run in linear runtime complexity. Could you implement it using only constant extra space complexity?
题意:
一个正确的数组,包含n个不同的数,现在给你一个少了一个数的数组,求出少了的那个数。要求:时间复杂度O(n),空间复杂度就是变量个数恒定。
怎么说呢,这题乍一看还真以为它在说0到n里面少了一个数,算出来就好了,同意的+1,T-T,T-T,T-T。
这道题用到了异或^这个运算,意思是a和b相等,异或结果为0,a和b不等结果就不为零。如果数组是完整的,当数组中的数依次从0开始一直到n异或一遍,结果应该为零;如果数组缺少一个数,当异或到n-1位(不完整数组的最后一位)数时,再与n异或之后的结果num,结果(num)应该是缺少的那位数,因为此时再与缺少的那个数异或结果必须为0,而我们根据异或运算法则可知相等的数运算结果为0,所以结果就这么出来了,有木有觉得真的是醉了。。。

public class Solution {
    public int missingNumber(int[] nums) {
        int i,num = 0 ^ nums[0],len = nums.length;
        for(i = 1; i < len; i++){
            num ^= i ^ nums[i];
        }
        return num ^ i;
    }
}

这里额外一提另一种做法:
将缺了个数的数组看成一组乱序的等差数列,等差数列求和,就是把数组里的数求和,得出Sn-1,而完整数组的和就是1到n的和Sn=n*(n+1)/2,
那么缺的那个数出来了,就是(Sn-Sn-1)了。

<think>我们被要求介绍C++中的位运算知识。根据引用内容,我们可以整理出以下结构: 1. 位运算符概述:介绍C++中的位运算符及其规则。 2. 底层机制:补码表示和符号位的影响。 3. 核心应用场景:包括一些基础应用和算法题示例。 同时,注意回答要求: - 行内数学表达式用$...$,例如:$x^2$ - 独立公式用$$...$$并单独成段 - 使用中文 - 生成相关问题 我们将按照以下结构组织回答: 一、位运算符概述 二、底层机制(补码表示与符号位影响) 三、核心应用场景(包含基础应用和示例) 四、总结 然后生成相关问题。 注意:由于引用中提供了多个来源,我们将综合这些信息,确保内容准确。 </think> ### C++位运算详解 位运算直接操作二进制位,在C++中常用于优化性能和解决特定算法问题。以下是核心知识点: #### 一、位运算符概述 C++提供6种位运算符,规则如下表: | 运算符 | 名称 | 规则描述 | 示例(二进制) | 十进制结果 | |--------|------------|------------------------------|---------------------------|------------| | `&` | 按位与 | 两位均为1时结果为1 | `0101 & 0011 = 0001` | 1 | | `\|` | 按位或 | 任一位为1时结果为1 | `0101 \| 0011 = 0111` | 7 | | `^` | 按位异或 | 两位不同时结果为1 | `0101 ^ 0011 = 0110` | 6 | | `~` | 按位取反 | 每位取反(含符号位) | `~0101 → 1010`(8位补码) | -6 | | `<<` | 左移 | 左移n位,右侧补0 | `5 << 1 → 10` | 10 | | `>>` | 右移 | 无符号数补0,有符号数补符号位 | `-5 >> 1 → -3` | -3 | > 注:右移有符号数时执行**算术右移**(保留符号位)[^2][^4]。 #### 二、底层机制 1. **补码表示** 负数的二进制存储形式为绝对值的补码: $$原码 \xrightarrow{取反} 反码 \xrightarrow{+1} 补码$$ 例如 -5 的8位补码计算: 原码: `1000 0101` → 反码: `1111 1010` → 补码: `1111 1011`[^4]。 2. **符号位影响** 最高位为符号位(0正1负),影响`~`和`>>`运算结果: ```cpp int a = 5; // 二进制 0101 int b = ~a; // 结果为 -6(补码: 1010) ``` #### 三、核心应用场景 1. **基础应用** - **奇偶判断**:`x & 1`(结果为1是奇数) - **乘除2的幂**:`x << n`(等价于 $x \times 2^n$),`x >> n`(等价于 $x \div 2^n$) - **交换变量**: ```cpp a ^= b; b ^= a; a ^= b; // 无需临时变量 ``` 2. **算法问题** - **缺失数字**(LeetCode 268): ```cpp int missingNumber(vector<int>& nums) { int tmp = 0; for (int x : nums) tmp ^= x; // 异或所有数组元素 for (int i = 0; i <= nums.size(); i++) tmp ^= i; // 异或完整序列 return tmp; // 结果即缺失数字 } ``` 原理:利用 $a \oplus a = 0$ 和 $0 \oplus b = b$[^5]。 - **只出现一次的数字**(LeetCode 136): ```cpp int singleNumber(vector<int>& nums) { int res = 0; for (int x : nums) res ^= x; // 成对数字相消 return res; } ``` #### 四、注意事项 1. **优先级问题**:位运算符优先级低于算术运算符,建议用括号明确顺序 2. **符号处理**:右移有符号数时编译器行为可能不同 3. **位移越界**:避免超出数据类型位数(如`int`左移超过31位) 位运算通过直接操作二进制位,可将某些操作时间复杂度降至 $O(1)$,常用于状态压缩、位掩码、哈希计算等场景[^1][^6]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值