多總結,才能更好地進步,分享下最近的刷題總結給大家吧
關於縮減代碼
1.善用js中的函數或者特性。
(迭代、解構、set等等)
// 使用箭頭函數縮減代碼 // 處理輸入,可以用.map,需要注意其所有參數 // 此外其他迭代方法也需要掌握。 let line = readline().split(' '); line = line.map((e) => parseInt(e)); // 去重 arr = [...new Set(arr)]; // 升序,排序可以用sort,默認是字典序,並且可以根據需要定制,需要深入掌握 arr.sort((a, b) => a - b); // 迭代輸出 arr.forEach((i) => console.log(i)); // 求最大值,使用擴展運算符... max = Math.max.call(...arr); // 復制數組 arr2 = [...arr1]; arr2 = arr.concat(); arr2 = arr.slice(); // 善用解構 // 變量賦值 let [a, b, c, d, e] = [1, 2, 3, 4, 5]; // a=1,b=2,c=3,d=4,e=5 // 交換變量值 [a, b] = [b, a]; // 題外話:字符串中的字符是無法交換的 let str = 'ab'; [str[0], str[1]] = [str[1], str[0]]; // 無效,"ab" // 不過可以將字符串拆成字符數組后就可以交換了 str = str.split(''); // ["a","b"] [str[0], str[1]] = [str[1], str[0]]; // ["b","a"]
2.善用位運算。
(相信我,能用位運算的就用位運算)
// 求數組一半長度 halfLen = a.length >> 1; // 不過需要注意右移運算符>>優先級別加號+還低,例如 console.log(3 + (5 - 3 >> 1)); // 2 console.log(3 + ~~((5 - 3) / 2)); // 4 // 因此在於其他操作符號想結合時候可以適當增加括號,例如求中位 mid = left + (right - left >> 1); mid = left + ~~((right - left) / 2); // 不建議使用mid = (left + right)>>1;,因為加號操作可能造成溢出 // ~~等價於Math.floor(),|0也等價於Math.floor() halfLen = ~~(a.length / 2); halfLen = a.length / 2 | 0; // 判斷奇偶 evenNum & 1 === 0; // 偶數 oddNum & 1 === 1; // 奇數 // 善用異或 5 ^ 5; // 0 5 ^ 5 ^ 6 ^ 6 ^ 7; // 7 // 判斷數是否是2的冪次方 num & num - 1 === 0; // 翻轉數的第K位 num ^= 1 << k; // 將第K位設為0 num &= ~(1 << k); // 將第K位設為1 num |= 1 << K; // 判斷第K位是否為0 num & 1 << k === 0;
3.善用正則表達式。
(只要關於字符串的題目都應該聯想到用正則表達式)
要會寫正則,可以用正則表達式的幾個函數也要掌握
正則中:exec,test
字符串中:search,match,replace,split
具體例子可以看我的:百詞斬春招筆試題解
4.少寫函數。
刷題不是寫業務代碼,沒有說要封裝重用,AC才是王道。
並且寫函數還要思考需要哪些參數,參數如何傳遞,會影響思考速度。
我們盡量做到的是,思考清楚后直接敲,越快越好,而不是一遍敲一邊思考。
5.遞歸函數。
前面情況有例外,比如要寫遞歸,就要寫函數。遞歸函數可以減少代碼。
不過還是建議用遞歸思想去想,用循環搭配數據結構(棧/隊列)去解答
關於刷題方法
1.審題先判斷陷阱。
看到題目第一先看是否有時間復雜度、空間復雜度的要求。(比如大數問題、遞歸多了棧溢出等問題)
根據自己猜測判斷使用簡單方法,還是復雜方法來做,畢竟我們沒有時間去做兩遍題目。
然后再順便看下是否需要判斷邊界條件(一般都需要出錯判斷)
有時間復雜度要求的,可以優化排序、動態規划、以空間換時間等
有空間復雜度要求的,可以用循環代替遞歸、動態規划代替遞歸等
這里講下為什么不說貪心,第一理論上所有貪心可以解決的問題都可以用動態規划來做,第二正因如此,許多公司難題也就只考到了動態規划。
所以請一定一定要掌握動態規划。
2.聯想。
我們遇到題目時要把題目和以前做過的題聯想下,通過類似點,找出突破點。
- 字符串問題====》正則
- 鏈表、數組問題====》雙指針
- 數組問題====》利用數組下標來做====》有時需要額外數組==》此外大部分要考慮二分法優化時間復雜度
- 多維數組問題====》降維來做。
- 復雜問題、優化問題====》動態規划
- 排列問題====》遞歸、回溯
- 數論問題====》找規律、動態規划
- 樹的問題====》遞歸、深度遍歷、廣度遍歷====》棧、隊列
- 次數問題====》哈希表存儲(js中建議使用{},而不要使用ES6中的Map)
- 大小值問題====》棧、隊列、哈希表做存儲
- 從前往后、從大到小比較復雜====》從后往前、從小到大思考。
- 動態規划重點了解
- 位運算也了解一下
3.必須掌握算法
快排和歸並排序、深度和廣度遍歷、二分查找(能手撕)
動態規划、回溯法。
要專門根據題目分類去刷這些算法。
4.多畫圖。
對於涉及數據結構的題目,如鏈表、二叉樹等一定要畫圖。
對於涉及概率的問題,可以畫圈圈來交、並、補。
對於點線的問題,可以畫坐標系。
5.多舉例
對於復雜問題可以舉不復雜的小例子來分析步驟。
對於數論問題可以舉例子來找規律。
退一萬步來說,假設你實在不會做,你也可以通過舉例,自己if-else生產很多測試用例去滿足題意。
這也是為什么我們刷題時,題目不會像劍指offer題目一樣,告訴你的答案和題目的測試用例有哪些不同的原因。
6.剩下的能淘汰你的只有智力題了。
有些忘記了,暫時想到的先寫這么多了,慢慢補充,有好的建議都可以發給我