一道有意思的口试算法题

新年第一篇文章,先祝人人新年快乐!!那末接下来进入正文。

媒介

前阵子突发奇想,倏忽最先刷leetcode。个中刷到了一道有意义的题目,发明这道题是当时秋招的时刻,腾讯口试官曾问过我的题目。因而分享给人人看下。

题目形貌

给定一个非空整数数组,除了某个元素只涌现一次之外,其他每一个元素均涌现两次。找出谁人只涌现了一次的元素。

开端解法

这道题第一眼看过去,思绪挺简朴的,我们只须要保护一个对象来纪录每一个元素涌现的次数,运用元素的值作为key,元素涌现的次数作为value。以后再遍历这个对象,找到value为1的key。对应的key就是谁人元素。代码以下:

function singleNumber(nums) {
  const obj = {};
  for (let i = 0; i < nums.length; i++) {
    obj[nums[i]] = obj[nums[i]] ? obj[nums[i]] + 1 : 1;
  }
  for (let key in obj) {
    if (obj[key] === 1) {
      return Number(key); // 由于 key 是 string ,因而我们这里须要转化下
    }
  }
}

console.log(singleNumber([2, 2, 1, 4, 4, 5, 5, 1, 8])); // 8

增添限定

是吧,这道题很简朴,那我为何要说它有意义呢?
由于题目内里实在另有一个限定:

你的算法应当具有线性时候复杂度。 你能够不运用分外空间来完成吗?

重点在于不运用分外空间。我们上面那种解法,创建了一个新的对象来贮存效果,显著是不可的。那末有无方法能够只运用本来的数组来完成这个功用呢?

终究解法

我们能够思索下,一个数组里,一切的数字都涌现两次,除了一个我们要找的数字只涌现一次。那末,我们有无方法将两个雷同的数字给过滤掉呢?

好啦,不卖关子了,之前有相识过的人应当就晓得解决方案了,假如之前没相识过这方面东西的人,能够继承往下看。

解决方案:异或操纵

异或运算是关于二进制数字而言的,比如说一个有两个二进制a、b,假如a、b两个值不雷同,则异或效果为1。假如a、b两个值雷同,异或效果为0。

而javascript的按位异或(即^操纵)操纵,则会对两个数字响应的每一对比特位实行异或操纵。

比如说 1 ^ 2,本质上实际上是1和2的每一对比特位实行异或操纵,等价于下面

  00000000000000000000000000000001 // 数字1对应的二进制
^ 00000000000000000000000000000010 // 数字2对应的二进制
= 00000000000000000000000000000011 // 数字3对应的二进制

因而1^2的效果就为3啦。

那末假如两个雷同的数字举行异或操纵,效果就可想而知,答案为0啦。

假如是0和任何一个数字异或呢?效果是数字自身。

我们举个栗子:
假定我们有一个数组,内里元素为[a, a, c, c, b, b, d]。那末我们对数组里的一切元素举行按位异或操纵,即a ^ a ^ c ^ c ^ b ^ b ^ d,是否是就等价于0 ^ 0 ^ 0 ^ d = d。而d就是数组里只涌现一次的元素。
那末我们能够扩大一下,关于恣意满足某个元素只涌现一次之外,其他每一个元素均涌现两次的数组,是否是能够经由过程这类体式格局来获得谁人只涌现一次的元素。

如许一来的话,我们是否是有了这个题目的解决方法了?我们只须要遍历数组,将一切的值取异或,终究剩下的值,就是谁人只涌现一次的数字。代码以下:

/**
 * 只存在一次的数字
 * https://leetcode-cn.com/explore/interview/card/top-interview-questions-easy/1/array/25/
 * @param {number[]} nums
 * @return {number}
 */
function singleNumber(nums) {
  for (let i = 1; i < nums.length; i++) {
    nums[0] ^= nums[i];
  }
  return nums[0];
};

console.log(singleNumber([2, 2, 1, 4, 4, 5, 5, 1, 8]));

结语

这道口试题主要磨练口试者对异或的明白,以及能不能活学活用,将这道题与异或联络在一起。固然,最主要的照样多进修、多刷题、多看书。如许才不断进步。

本文地点在->本人博客地点, 迎接给个 start 或 follow

    原文作者:我不是陈纪庚
    原文地址: https://segmentfault.com/a/1190000017756829
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞