前端面試中常見的算法問題讀后整理

看到有一篇寫前端面試中常見的算法文章,里面的例子很簡單,但也挺有趣。

重要的是,其實每個問題,都不止一個解答,我們可以從各個方面細想一下,拓展一下思路。

原文:前端面試中的常見的算法問題

判斷一個字符串是否回文

利用js數(shù)組實現(xiàn)

js的數(shù)組是一個很強大的數(shù)據結構,我們可以活用其已實現(xiàn)的原生方法做很多事,比如,這個例子中,判斷一個字符串是否是回文。

步驟:

將字符串拆分成數(shù)組

將字符串拆分成數(shù)組其實也也有多種方法:

split()方法

3letstr_to_array =function(str){

returnstr.split('');

}

Array.prototype.map()

3letstr_to_array =function(str){

returnArray.prototype.map.call(str,function(x){returnx});

}

數(shù)組反轉reverse()

拼接成字符串join()

letcheckPalindrom =function(str){

returnstr_to_array(str).reverse().join('');

}

活用數(shù)組的reduceRight()方法

我們可以直接在字符串上調用數(shù)組的reduceRight()方法將字符串逆轉

letrs =Array.prototype.reduceRight.apply('abc',[function(pre,current){

returnpre + current;

},'']);

letcheckPalindrom =function(str){

returnstr == rs(str);

}

使用棧數(shù)據結構

我們在學習棧這個數(shù)據結構的時候,老師講的最生動的一個例子就是,判斷回文有木有。

先將字符串中字符依次入棧,然后出棧組成新的字符串,即為逆轉的字符串,然后做比較。

去掉一些整型數(shù)組中重復的值

直接使用es6的Set

3letunique =function(array){

return[...newSet(array)];

}

使用Object

我們知道Object對象的鍵是唯一的,可以利用這個特性為數(shù)組去重。

letunique =function(array){

letro = {};

letra = [];

array.forEach(item=>{

if(!ro[item]){

ro[item] = item;

ra.push(item);

}

});

returnra;

}

統(tǒng)計一個字符串出現(xiàn)最多的字母

首先我們要先統(tǒng)計字符串中各個字符出現(xiàn)的次數(shù),我們可以使用最笨的遍歷方法進行統(tǒng)計:

letcountChar =functioncountChar(str){

letro = {};

for(letcofstr){

if(!ro[c]){

ro[c] =1;

}else{

ro[c] ++;

}

}

returnro;

}

當然,也使用數(shù)組的reduce()方法進行統(tǒng)計,因為這個方法就適合進行統(tǒng)計計算。

letcountChar =functioncountChar(str){

returnArray.prototype.reduce.call(str,function(pre,current){

if(pre[current]){

pre[current] ++;

}else{

pre[current ] =1;

}

returnpre;

},{});

}

然后,從剛才統(tǒng)計出的數(shù)中查找出出現(xiàn)次數(shù)最多的字符

letfindMaxDuplicateChar =function(str){

letchars = countChar(str);

letmax =0;

letchar =null;

for(letcinchars){

if(chars[c] > max){

max = chars[c];

char = c;

}

}

returnchar;

}

不用臨時變量,交換兩個變量的值

原文中呢,作者教大家要合理運用+,-運算,最后給出如下答案:

functionswap(a , b){

b = b - a;

a = a + b;

b = a - b;

return[a,b];

}

module.exports = swap;

很巧妙,對吧,確實是合理運用了+,-運算,但是為什么呢?合理運用*,/運算呢?

a = a * b;

b = a / b;

a = a / b;

合理運用*,/好像也可以啊,對吧。

其實解決問題,我們應該從根上去解決,不能簡單的說’合理運用’就敷衍過去了。

題目是,不用臨時變量,臨時變量是干嘛的呢?當然是存儲臨時值用的了,對吧。

那么,不用臨時變量,我們可以把臨時值存儲到當前現(xiàn)有的變量中,對吧。

就好像是創(chuàng)造了一個臨時變量一樣。上面兩個例子中,都是用兩個變量的差或兩個變量的積作為臨時值,然后存儲到其中一個變量,再由相應的運算交換兩個變量的值。

明白了這個道理后,我們再合理一下嘛,對吧,利用兩個變量的和作為臨時值:

a = a + b;

b = a - b;

a = a - b;

注意:這里慎用兩個變量的商作為臨時值,因為如果兩個變量除不盡,由于js中除法運算會舍掉余數(shù),則會發(fā)生問題。

我們除了使用+,-,*,/四則運算創(chuàng)造‘臨時變量’外,還可以使用位運算

a = a ^ b;

b = b ^ a;

a = a ^ b;

這個比上面的四則運算就要稍難理解了,這里運用了位運算中的異或運算。

對于異或運算的說明,還有不明白的可以回去翻翻大學的課本。

第一行 a = a ^ b;即創(chuàng)造了一個臨時值存儲在a中。

b = b ^ a

相當于

b = b ^ (a ^ b) = b ^ b ^ a = a

同理,

a = a ^ b

相當于

a = (a ^ b) ^ (b ^ (a ^ b)) = a^b^b^a^b = a^a^b^b^b = 0^0^b = b

找出數(shù)組中最大差值

可以直接遍歷數(shù)組,找出最大值和最小值,然后做差。但是呢,那樣就沒意思了,對吧,我們可以直接使用數(shù)組的reduce()方法找出最大值和最小值。

letgetMaxProfit =functiongetMaxProfit(arr){

letmax_min = arr.reduce(function(pre,current){

if(pre.min > current){

pre.min = current;

}

if(pre.max < current){

pre.max = current;

}

returnpre;

},{min:arr[0],max:arr[0]});

returnmax_min.max - max_min.min;

}

當然,使用reduce()貌似還是有點麻煩啊,js的Math對象不是有max()和min()方法嘛,直接用這兩個方法找出最大值和最小值就好了啊:

letgetMaxProfit =functiongetMaxProfit(arr){

letmax =Math.max.apply(Math,arr);

letmin =Math.min.apply(Math,arr);

returnmax - min;

}

這里使用了apply方法直接調用max()和min()來獲取最大值和最小值。

我們都知道js中apply和call兩個方法是功能相同的兩個方法,只是傳參方式不同。call方法傳遞參數(shù)列表,而apply傳遞參數(shù)對象或數(shù)組。

在es6中新添加了一個...操作符,用于將數(shù)組展開成列表,具體可參見MDN上的文檔。

因此,我們這里可以使用該操作符,直接調用max()和min()方法:

letgetMaxProfit =functiongetMaxProfit(arr){

letmax =Math.max(...arr);

letmin =Math.min(...arr);

returnmax - min;

}

位操作

20世紀70年代末到80年代末,Digital Equipment的VAX計算機是一種非常流行的機型。它沒有布爾運算AND和OR指令,只有bis(位設置)和bic(位清除)這兩個指令。兩種指令的輸入都是一個數(shù)據字x和一個掩碼字m。他們生成一個結果z,z是由根據掩碼m的位來修改x的位得到的。使用bis指令,就是在m為1的每個位置上,將z對應的位設置為1.使用bic指令,在m為1的每個位置,將z對應的位設置為0。

只使用bis和bic指令,完成按位|和^運算。

//bis和bic聲明

intbis(intx,intm);

intbic(intx,intm);

//完成如下 | 運算 和 ^ 運算

intbool_or(intx,inty){

intresult = ______ ;

returnresult;

}

intbool_xor(intx,inty){

intresult = ______ ;

returnresult;

}

這其實是一道邏輯題目,由已知的bis運算邏輯和bic運算邏輯,用這兩種運算去實現(xiàn)其他的運算。

bis運算就是在掩碼位為1的位設置為1,其他位不變。而bic運算是在掩碼位為1的位置設置為0,其他不變。

舉個例子:

x? 11010100

m? 10100101

bis --------

11110101

x? 11010100

m? 10100101

bic --------

01010000

好了,那怎么利用這兩種運算指令實現(xiàn)按位|和^運算呢?

仔細分析一下 bis 運算,所有掩碼位為1的位,結果都是1,其他為0的位,還是按照原來的位,這不就是按位|運算么?

于是,第一個有了:

intbool_or(intx,inty){

intresult = bis(x,y) ;

returnresult;

}

那^運算呢?

我們都知道,異或運算運算法則為:a⊕b=(?a∧b)∨(a∧?b),a⊕b=(?a∨b)∧(a∨?b)。至于為什么,可以列真值表驗證。

這里我們采用第一個運算法則:a⊕b=(?a∧b)∨(a∧?b)。

bic運算是怎么來的呢?bic(a,b)是將a上對應b為1的位變?yōu)?,其他不變。那么,不就是相當于先將b取反,然后和a進行按位與&運算么,就是:

bic(a,b) = a & (~b)

于是,再利用異或第一個運算法則:a⊕b=(?a∧b)∨(a∧?b)

我們可以得出:

intbool_xor(intx,inty){

intresult = bis(bic(x,y),bic(y,x));

returnresult;

}

js實現(xiàn)二叉搜索樹

啥也不說了,直接看我github上的代碼吧。

https://github.com/coolcao/dsa_js/blob/master/src/BSTree.js

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容