C++ 异或运算直觉
我最近遇到了一个关于Leetcode的问题,并找到了一个需要澄清的解决方案: 给定一个整数数组,除了一个之外,每个元素都会出现两次。找到那个 注: 您的算法应该具有线性运行时复杂性。你能在不使用额外内存的情况下实现它吗C++ 异或运算直觉,c++,bit-manipulation,C++,Bit Manipulation,我最近遇到了一个关于Leetcode的问题,并找到了一个需要澄清的解决方案: 给定一个整数数组,除了一个之外,每个元素都会出现两次。找到那个 注: 您的算法应该具有线性运行时复杂性。你能在不使用额外内存的情况下实现它吗 类解决方案{ 公众: 整数单数(向量和nums){ int结果=0; 用于(自动和控制:nums){ 结果^=c; } 返回结果; } }; 首先,我应该注意什么类型的关键字,以便弄清楚我应该对这个问题使用XOR运算 还有,为什么向量中的所有项彼此异或会得到一个不重复的项 感
类解决方案{
公众:
整数单数(向量和nums){
int结果=0;
用于(自动和控制:nums){
结果^=c;
}
返回结果;
}
};
首先,我应该注意什么类型的关键字,以便弄清楚我应该对这个问题使用XOR运算
还有,为什么向量中的所有项彼此异或会得到一个不重复的项
感谢大家的回复,下面是其他感兴趣的人关于按位属性的更多信息:异或运算符是可交换的: 和关联: 因此,任何
xor
操作序列的结果都完全独立于操作数的顺序(即数组中元素的顺序)
在这个问题中,我们有一个表达式,其中每个元素Ai出现两次,除了一些奇异元素B。得到的异或运算等价于:
(A1 ⊕ A1) ⊕ (A2 ⊕ A2) ⊕ ... ⊕ B
=
0 ⊕ 0 ⊕ ... ⊕ B
=
B
我应该注意哪些类型的关键字,以便弄清楚我应该对这个问题使用XOR运算 使用位操作可以快速解决一些问题。在熟悉了布尔运算符及其属性,并看到了足够多的像这样的应用程序之后,您自然会“感觉”到它们对解决给定问题有用
A^0==A
A^A==0
A^B==B^A
(A^B)^C==A^(B^C)
A^B^X^C^B^A^C
等于A^A^B^B^C^C^X
因为(2)等于0^0^0^X
因为(1)等于X
我不认为有任何特定的关键字可以帮助您识别此类问题。您应该知道XOR的上述属性。XOR总是以二进制数字(或一些等价的概念,如true或false语句)来定义的。除了二进制表示的相应位的异或外,整数没有特殊的异或 设A和B为两个布尔变量,设XOR为接受两个布尔变量的布尔函数。
A.⊕如果(A=0和B=1)或(A=1和B=0)(即两者不同),则B=1,
A.⊕如果(A=0和B=0)或(A=1和B=1),则B=0。(即它们是相同的) 因此,考虑到你的问题,因为在给定的n个向量元素中,除了一个元素外,每个元素都出现两次,这个想法是 重复数的二进制表示形式是相同的,因此,XOR结果将相互抵消为1⊕1=0和0⊕0=0 对于A=5,其二进制表示为101,因此A⊕A=(101)⊕(101)=000,其十进制表示为0 请记住,数字的顺序并不重要,因为((A⊕(B)⊕C) =(A)⊕(B)⊕C) )。 最终,对每个数字进行XOR运算后,最后得到的是一次出现的数字 要回答您关于何时需要使用异或运算来解决问题的问题,请练习一些位操作问题,最终您将能够理解。
提示:要求查找除rest之外具有唯一属性的元素的问题需要位操作。
示例:给定一个数组,其中每个元素出现三次,只有一个元素只出现一次。查找一次出现的元素。将异或与其他逻辑运算符区分开来的关键直观方面是它是无损耗的,也就是说,与和和或(在这方面更类似于非),它是确定可逆的:在给定剩余的计算历史的情况下,您可以精确地恢复其中一个输入值 下图说明了和和以及或都至少有一种情况,其中一个输入的状态在给定另一个输入的特定值时是不可恢复的。我将这些表示为“丢失”输入 对于异或门,考虑到剩余的计算历史,不存在无法恢复输入或输出值的情况。事实上,有一种对称性,知道三元组
(in0,in1,out)
的任意两个值可以恢复第三个值。换句话说,无论输入或输出如何,这三个值中的每一个都是其他两个值的异或
这张图片表明,另一种看待异或操作的方式是将其看作一个可控的非门。通过切换其中一个输入(上例中的上一个),可以控制另一个(下一个)输入是否为负
另一个等价的观点是,XOR实现了不等于(≠) 函数相对于其两个输入。因此,也等于下的函数(=)
根据其对称性和信息保持特性,XOR应该考虑需要可逆性或完美数据恢复的问题。最明显的例子是,XOR使用恒定的“键”对数据集进行加密会使数据变得模糊,从而知道键(可能是kep)
1. X ⊕ Y = Y ⊕ X for any integers X and Y
2. X ⊕ (Y ⊕ Z) = (X ⊕ Y) ⊕ Z for any integers X, Y and Z
3. X ⊕ X = 0 for any integer X
4. X ⊕ 0 = 0 ⊕ X = X for any integer X
(A1 ⊕ A1) ⊕ (A2 ⊕ A2) ⊕ ... ⊕ B
=
0 ⊕ 0 ⊕ ... ⊕ B
=
B
uint GetHashCode(ulong ul)
{
return (uint)ul ^ (uint)(ul >> 32);
}
unsigned int v; // the value to modify
unsigned int m; // mask: the bits to set or clear
int f; // condition: 0 to 'set', or 1 to 'clear'
v ^= (-f ^ v) & m; // if (f) v |= m; else v &= ~m;
class Solution:
def singleNumber(self, nums):
return (sum(set(nums)) << 1) - sum(nums)
// The following block might slightly improve the execution time;
// Can be removed;
static const auto __optimize__ = []() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
return 0;
}();
// Most of headers are already included;
// Can be removed;
#include <cstdint>
using ValueType = std::uint_fast16_t;
static const struct Solution {
static const int singleNumber(
const std::vector<int> nums
) {
ValueType single_number = 0;
for (ValueType index = 0; index < std::size(nums); index++) {
single_number ^= nums[index];
}
return single_number;
}
};
public final class Solution {
public static final int singleNumber(
final int[] nums
) {
int singleNumber = 0;
for (int index = 0; index != nums.length; index++) {
singleNumber ^= nums[index];
}
return singleNumber;
}
}