算法基础——异或运算符(^)的骚操作

1,229 阅读2分钟

异或运算符

这是百度百科给出的解释

对于程序算法来说 归零律 1 ^ 1 输出 0 相同的输出0,恒等律 1 ^ 0 输出1

二进制异或运算

210number
1015
1106
1^1=00^1=11^0=15^6=3
0113

从这个表格可以看出来 5^6 输出结果是3

从表格看,还是比较清晰的,那么下面看一下十进制和二进制之间的关系

(为啥十进制的5转为2进制是101)

十进制转二进制

使用短除法

javascript转换方法是num.toString(2) 十进制数字转为二进制

可以通过这样的规律写出一个转换工具,方便理解

BinaryToDecimalSystem = function (num) {
  if (typeof num === "number") {
    const nrArr = [];
    // 通过根号计算出需要除几次2 (二进制有几位)
    const s = Math.ceil(Math.sqrt(num));
    let n = num;
    // 需要计算s次
    for (let i = s; i >= 0; i--) {
      let nr = n % 2 === 0 ? 0 : 1;
      // 数组向后添加
      nrArr.unshift(nr);
      // 将下一次的计算值赋值给n
      n = Math.floor(n / 2);
    }
    // 至于输出格式这里是数组转字符串 字符串转数字
    // 也可以不用数组的unshift,可以直接+=的方式直接输出字符串
    return Number(nrArr.join(""));
  } else {
    return "error";
  }
};
const decimal = BinaryToDecimalSystem(65);
console.log(decimal); // 1000001

试了几个数字 感觉没什么异样,如果还有其他逻辑,可以一起沟通

可以通过这个方法计算出 5的二进制是101 6的二进制是110

那么二进制异或算法得出结果 011 转数字 0去掉 结果是 11

那么接下来就是将11通过二进制转十进制的方法 得出结果3 javascript提供的方法是

var num = 11
parseInt(num,2) // 3

我们通过自己写的方法来计算一下 方便理解

二进制转十进制采用按权相加法,以1100100为例 转换结果应该是100

同样可以通过这个逻辑写一个方法

DecimalSystemToBinary = function (num) {
  if (typeof num === "number") {
    const toStr = num.toString();
    const len = toStr.length;
    let count = 0;
    for (let i = 1; i <= len; i++) {
      let n = Number(toStr[i - 1]);
      if (n !== 0) {
        count += n * 2 ** (len - i);
      }
    }
    return count
  } else {
    return 'error'
  }
};

const count = DecimalSystemToBinary(11);
console.log(count) // 3

通过这样的互相转换方法 轻易的计算出 5^6=3

例题

在使用异或运算符之前 我们可以通过自己的方法来实现这个功能

var singleNumber = function (nums) {
  let num = nums.sort((a, b) => {
    return a - b;
  });
  let n = num[0];
  for (let i = 1; i < num.length; i++) {
    if (n === num[i]) {
      n = num[i + 1] || num[num.length-1];
      i++
    }
  }
  return n;
};
const arr = [4,1,2,1,2];
console.log(singleNumber(arr));  // 4

用这种方法 又要排序 又要循环 很复杂 如果用异或运算符的话 几行代码就搞定

    var singleNumber = function (nums) {
      let n = 0;
      for (let i = 0; i < nums.length; i++) {
        n ^= nums[i]
      }
      return n;
    };
    const arr = [2,2,1];
    console.log(singleNumber(arr)); // 4

这种写法非常简便,而且高效,看起来比较复杂 我们分开几步,一步一步看具体怎么实现的

var singleNumber = function (nums) {
  let n = 0;
  // for (let i = 0; i < nums.length; i++) {
  //   n ^= nums[i]
  // }
  let a = nums[0]
  let b = nums[1]
  let c = nums[2]

  n = n^a // 0^2 ==> n=2  恒等率
  n = n^b // 2^2 ==> n=0  归零率
  n = n^c // 0^1 ==> n=1  恒等率
  return n;
};
const arr = [2,2,1];
console.log(singleNumber(arr)); // 1

另一种情况

var singleNumber = function (nums) {
  let n = 0;
  // for (let i = 0; i < nums.length; i++) {
  //   n ^= nums[i]
  // }
  let a = nums[0]
  let b = nums[1]
  let c = nums[2]

  n = n^a // 0^1 ==> n=1 衡等律
  n = n^b // 1^3 ==> n=2 交换律
  n = n^c // 2^3 ==> n=1 交换律
  return n;
};
const arr = [1,3,3];
console.log(singleNumber(arr)); // 1