上一篇文章,寫了一些出去面試會考到的筆試題,不是很全(哈哈哈,基本上都是靠腦子記的,有些都忘記了~)前端
傳送門在這裏:2018年6月前端面試經歷(上)~~~react
這篇我會寫出一些我碰到的算法題,解法不統一,但願你們能多多的提供本身的想法和代碼~面試
思路:
- 隨機選擇數組中的一個數 A,以這個數爲基準
- 其餘數字跟這個數進行比較,比這個數小的放在其左邊,大的放到其右邊
- 通過一次循環以後,A 左邊爲小於 A 的,右邊爲大於 A 的
- 這時候將左邊和右邊的數再遞歸上面的過程
const Arr = [85, 24, 63, 45, 17, 31, 96, 50];
function quickSort(arr) {
if (arr.length <= 1) {
return arr;
}
let pivotIndex = Math.floor(arr.length / 2);
let pivot = arr.splice(pivotIndex, 1)[0];
let left = [];
let right = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i] < pivot) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
// 遞歸
return quickSort(left).concat([pivot], quickSort(right));
}
console.log(quickSort(Arr));
ps:
這是阮老師的一個快排寫法,網上對於這個的爭論不少,第一說了阮老師不該該用splice去取值,應該用下標,還有就是不該該每次都重新開倆個新數組。
其實我以爲算法題重要的是思路,實現的方式有不少,不必定說誰對誰錯,效率越好的算法的確是咱們想要的,可是更多的理解一些不一樣的實現思路,我以爲也是能夠的~。
複製代碼
這裏是不一樣的聲音: 面試官:阮一峯版的快速排序徹底是錯的算法
二分查找法主要是解決「在一堆有序的數中找出指定的數」這類問題,無論這些數是一維數組仍是多維數組,只要有序,就能夠用二分查找來優化。數組
二分查找是一種「分治」思想的算法,大概流程以下:bash
題目:在一個二維數組中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數,輸入這樣的一個二維數組和一個整數,判斷數組中是否含有該整數。
function Find(target, array) {
let i = 0;
let j = array[i].length - 1;
while (i < array.length && j >= 0) {
if (array[i][j] < target) {
i++;
} else if (array[i][j] > target) {
j--;
} else {
return true;
}
}
return false;
}
//測試用例
console.log(Find(10, [
[1, 2, 3, 4],
[5, 9, 10, 11],
[13, 20, 21, 23]
])
);
複製代碼
function parseParam(url) {
let obj = {};
let arr = url.split("?");
if (arr.length == 1) { //判斷沒有問號
return "無參數"
}
let total = arr[1].split("&");
for (let i = 0; i < total.length; i++) {
let single = total[i].split("=");
if (single[0] == '') { //判斷有?可是沒有參數
return '無參數'
}
if (!single[1]) {
obj[single[0]] = true;
} else {
if (obj[single[0]]) {
let concat
if (!Array.isArray(obj[single[0]])) { //判斷是否數組
concat = [obj[single[0]]]
} else {
concat = obj[single[0]];
}
concat.push(single[1]);
concat = new Set(concat);
concat = Array.from(concat) //數組去重
obj[single[0]] = concat
} else {
obj[single[0]] = decodeURI(single[1]) //進行轉碼
}
}
}
return obj
}
var url = 'http://www.baidu.com/?user=huixin&id=123&id=456&city=%E5%8C%97%E4%BA%AC&enabled';
var params = parseParam(url)
console.log(params)
複製代碼
列:我叫a,年齡b,性別c; let data = { name: '小明', age: 18, } 沒有定義的返回undefined數據結構
let template = '我是{name},年齡{age},性別{sex}';
let data = {
name: '小明',
age: 18,
}
const reg= /({([a-zA-Z]+)})/g;
var r= '',regrounp={};
while( r = reg.exec(template) ){
Object.defineProperty(regrounp,r[2],{
enumerable:true,
value:r[2]
})
}
var render = (template,regrounp)=>{
var result='';
for( key in regrounp){
if(data[key] == undefined){
result = (result || template).replace(new RegExp(`{${regrounp[key]}}`,"g"),undefined);
}else{
result = (result || template).replace(new RegExp(`{${regrounp[key]}}`,"g"),data[key]);
}
}
return result
}
let newtemple = render(template, regrounp);
console.log(newtemple) // 結果: 我是小明,年齡18,性別undefined
複製代碼
這裏不試不知道,{}這樣聲明的對象,能夠直接枚舉,Object.defineProperty聲明出的對象,若是不定義enumerable:true的話,是不能用for-in 枚舉的。函數
這裏有一片很好的文章 推薦 編寫一個簡單的JavaScript模板引擎post
function exchange(num) {
num += ''; //轉成字符串
if (num.length <= 3) {
return num;
}
num = num.replace(/\d{1,3}(?=(\d{3})+$)/g, (v) => {
console.log(v)
return v + ',';
});
return num;
}
console.log(exchange(1234567));
複製代碼
深拷貝
就是在拷貝數據的時候,將數據的全部引用結構都拷貝一份。簡單的說就是,在內存中存在兩個數據結構徹底相同又相互獨立的數據,將引用型類型進行復制,而不是隻複製其引用關係。學習
分析下怎麼作 深拷貝
:
function deepClone(o1, o2) {
for (let k in o2) {
if (typeof o2[k] === 'object') {
o1[k] = {};
deepClone(o1[k], o2[k]);
} else {
o1[k] = o2[k];
}
}
}
// 測試用例
let obj = {
a: 1,
b: [1, 2, 3],
c: {}
};
let emptyObj = Object.create(null);
deepClone(emptyObj, obj);
console.log(emptyObj.a == obj.a);
console.log(emptyObj.b == obj.b);
複製代碼
遞歸容易形成爆棧,尾部調用能夠解決遞歸的這個問題,Chrome 的 V8 引擎作了尾部調用優化,咱們在寫代碼的時候也要注意尾部調用寫法。遞歸的爆棧問題能夠經過將遞歸改寫成枚舉的方式來解決,就是經過for
或者while
來代替遞歸。
下面的代碼中count記錄遞歸的次數,咱們看下兩種差別性的代碼中的count的值:
let count = 0;
function fn(n) {
let cache = {};
function _fn(n) {
if (cache[n]) {
return cache[n];
}
count++;
if (n == 1 || n == 2) {
return 1;
}
let prev = _fn(n - 1);
cache[n - 1] = prev;
let next = _fn(n - 2);
cache[n - 2] = next;
return prev + next;
}
return _fn(n);
}
let count2 = 0;
function fn2(n) {
count2++;
if (n == 1 || n == 2) {
return 1;
}
return fn2(n - 1) + fn2(n - 2);
}
console.log(fn(20), count); // 6765 20
console.log(fn2(20), count2); // 6765 13529
複製代碼
算法的好壞能夠經過算法複雜度來衡量,算法複雜度包括時間複雜度和空間複雜度兩個。時間複雜度因爲好估算、好評估等特色,是面試中考查的重點。空間複雜度在面試中考查得很少。
常見的時間複雜度有:
O(1)
O(logN)
O(n)
O(nlogN)
O(n^2)
O(n^3)
O(n^k)
O(2^n)
隨着問題規模 n 的不斷增大,上述時間複雜度不斷增大,算法的執行效率越低。
通常作算法複雜度分析的時候,遵循下面的技巧:
題目:分析下面代碼的算法複雜度
let i =0; // 語句執行一次
while (i < n) { // 語句執行 n 次
console.log(`Current i is ${i}`); //語句執行 n 次
i++; // 語句執行 n 次
}
根據註釋能夠獲得,算法複雜度爲1 + n + n + n = 1 + 3n,去除常數項,爲O(n)。
複製代碼
算法題其實還有不少,好比二叉樹的增刪改查等,推薦你們晚上空出時間都去看看~仍是挺有意思的~
延伸資源:
1)你以爲你是什麼樣的人?
2)爲何離職?
3)你最不滿意之前領導的什麼地方?
4)你平時週末都幹什麼?
5)你作的最喜歡的項目是什麼?爲何?
6)喜歡什麼樣的團隊?
預告:跟新完了這篇,下一篇是面試官的面試了,因爲個人技術棧是react,因此接下來的主題是圍繞着
react
~