一道有意思的面試算法題

新年第一篇文章,先祝你們新年快樂!!那麼接下來進入正文。javascript

前言

前陣子突發奇想,忽然開始刷leetcode。其中刷到了一道有意思的題目,發現這道題是當時秋招的時候,騰訊面試官曾經問過個人題目。因而分享給你們看下。java

題目描述

給定一個非空整數數組,除了某個元素只出現一次之外,其他每一個元素均出現兩次。找出那個只出現了一次的元素。git

初步解法

這道題第一眼看過去,思路挺簡單的,咱們只須要維護一個對象來記錄每個元素出現的次數,使用元素的值做爲key,元素出現的次數做爲value。以後再遍歷這個對象,找到value爲1的key。對應的key就是那個元素。代碼以下:github

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

增長限制

是吧,這道題很簡單,那我爲何要說它有意思呢?
由於題目裏面其實還有一個限制:面試

你的算法應該具備線性時間複雜度。 你能夠不使用額外空間來實現嗎?算法

重點在於不使用額外空間。咱們上面那種解法,建立了一個新的對象來儲存結果,明顯是不行的。那麼有沒有辦法能夠只使用原來的數組來實現這個功能呢?數組

最終解法

咱們能夠思考下,一個數組裏,全部的數字都出現兩次,除了一個咱們要找的數字只出現一次。那麼,咱們有沒有辦法將兩個相同的數字給過濾掉呢?學習

好啦,不賣關子了,以前有了解過的人應該就知道解決方案了,若是以前沒了解過這方面東西的人,能夠繼續往下看。code

解決方案:異或操做對象

異或運算是對於二進制數字而言的,好比說一個有兩個二進制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

相關文章
相關標籤/搜索