前端面試必備-40道LeetCode經典面試演算法題

藍蘭蘭發表於2019-12-12

2019年馬上就要結束了,相信很多童鞋都開始蠢蠢欲動了,尋找新的機會了,但是工作太忙沒有時間刷演算法題,面試的時候好心虛。這裡雙手奉上40道LeetCode上經典面試演算法題,整理的內容有點長,建議先收藏,慢慢消化,在來年順利拿到滿意的offer。

內容較多,整理不易,希望大家關注公眾號【前端】,更多優質前端原創好文。

[LeetCode] 兩數之和

給定一個整數陣列和一個目標值,找出陣列中和為目標值的兩個數。 你可以假設每個輸入只對應一種答案,且同樣的元素不能被重複利用。 示例: 給定 nums = [2, 7, 11, 15], target = 9 因為 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1]

var twoSum = function(nums, target) {
    var len = nums.length;
    for(var i=0; i<len; i++){
        for(var j=i+1; j<len;j++){
            if(nums[i] + nums[j] == target){
                return [i, j];
            }
        }  
    }
    return [];
}; 
複製程式碼

[LeetCode]路徑總和

給定一個二叉樹和一個目標和,判斷該樹中是否存在根節點到葉子節點的路徑,這條路徑上所有節點值相加等於目標和。 說明: 葉子節點是指沒有子節點的節點。

var hasPathSum = function(root, sum) {
	    if (!root) return false;
	    var cur = sum-root.val;
	    if (!root.left&&!root.right&&cur==0) return true;
	    if (!root.left) return hasPathSum(root.right, cur);
	    if (!root.right) return hasPathSum(root.left, cur);
	    return hasPathSum(root.left, cur)||hasPathSum(root.right, cur);
	};
複製程式碼

[LeetCode]二叉樹的最小深度

給定一個二叉樹,找出其最小深度。 最小深度是從根節點到最近葉子節點的最短路徑上的節點數量。 說明: 葉子節點是指沒有子節點的節點。

var minDepth = function(root) {
	    if (!root) return 0;
	    if (!root.left&&!root.right) return 1;
	    if (!root.left) return minDepth(root.right)+1;
	    if (!root.right) return minDepth(root.left)+1;
	    return Math.min(minDepth(root.left), minDepth(root.right))+1;
	};
複製程式碼

[LeetCode] 二進位制求和

給定兩個二進位制字串,返回他們的和(用二進位制表示)。

	var addBinary = function(a, b) {
	    var res = [];
	    var num = 0;
	    var addOne = 0;//是否進位
	    //字串對其
	    while(a.length < b.length){
	        a = 0 + a;
	    }
	    while(b.length < a.length){
	        b = 0 + b;
	    }
	    for (var i=a.length-1; i>=0; i--){
	        num = parseInt(a[i])+parseInt(b[i])+addOne;
	        if(num>=2){
	            res[i] = num-2;
	            addOne = 1;
	        }else{
	            res[i] = num;
	            addOne = 0;
	        }
	    }
	    if(addOne>0){
	        res.unshift(1);
	    }
	    return res.join('');
	};
複製程式碼

[LeetCode]x的平方根

實現 int sqrt(int x) 函式。 計算並返回 x 的平方根,其中 x 是非負整數。 由於返回型別是整數,結果只保留整數的部分,小數部分將被捨去。

var mySqrt = function(x) {
	    var i = 1;
	    while(x>=i*i){
	        i++;
	    }
	    return i-1;
	}; 
	//方法2 ES6
	var mySqrt = function(x) {
	    return Math.floor(x ** 0.5);//向下取整 x^0.5
	}; 
複製程式碼

[LeetCode] 加一

給定一個由整陣列成的非空陣列所表示的非負整數,在該數的基礎上加一。最高位數字存放在陣列的首位, 陣列中每個元素只儲存一個數字。

var plusOne = function(digits) {
	    var len = digits.length;
	    for (var i=len-1; i>=0; i--){
	        if(digits[i]<9){
	            digits[i]++;
	            return digits;
	        }
	        digits[i] = 0;
	    }
	    digits.unshift(1);
	    return digits;
	};
複製程式碼

LeetCode 最後一個單詞的長度

給定一個僅包含大小寫字母和空格 ’ ’ 的字串,返回其最後一個單詞的長度。

var lengthOfLastWord = function(s) {
	    s = s.trim();
	    var arr = s.split(' ');
	    return arr[arr.length-1].length;
	};
複製程式碼

[LeetCode] 最大子序和

給定一個整數陣列 nums,找到一個具有最大和的連續子陣列(子陣列最少包含一個元素)返回其最大和。

var maxSubArray = function(nums) {
	    var max = nums[0];
	    var sum = 0;
	    for (let num of nums){
	        if (sum < 0){
	            sum = 0;
	        }
	        sum += num;
	        max = Math.max(sum, max);
	    }
	    return max;
	};
複製程式碼

[LeetCode]報數

報數序列是一個整數序列,按照其中的整數的順序進行報數,得到下一個數。

var countAndSay = function(n) {
	    var resultStr = '1';
	    for (var i=1; i<n; i++){
	        var repeatCount = 1;
	        var str = '';
	        for (var j=0; j<resultStr.length; j++) {
	            if (resultStr[j]===resultStr[j+1]){
	                repeatCount++;
	            } else {
	                str += repeatCount + resultStr[j];
	                repeatCount = 1;
	            }
	        }
	        resultStr = str;
	    }
	    return resultStr;
	}; 
複製程式碼

[LeetCode]楊輝三角

給定一個非負整數 numRows,生成楊輝三角的前 numRows 行。 在楊輝三角中,每個數是它左上方和右上方的數的和。 示例: 輸入: 5 輸出: [ [1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4,1] ]

var generate = function(numRows) {
	    var res = [];
	    for (var i=0; i<numRows; i++){
	        var arr = [1];
	        for (var j=1; j<i; j++){
	            arr[j] = res[i-1][j]+res[i-1][j-1];
	        }
	        arr[i] = 1;
	        res.push(arr);
	    }
	    return res;
	};
複製程式碼

[LeetCode]楊輝三角 II

給定一個非負索引 k,其中 k ≤ 33,返回楊輝三角的第 k 行。

var getRow = function(rowIndex) {
	    var res = [1];
	    if (rowIndex==0) return [1];
	    if (rowIndex==1) {
	        return [1,1];
	    }
	    var arr = getRow(rowIndex-1);
	    for (var i=1; i<rowIndex; i++){
	        res[i] = arr[i]+arr[i-1];
	    }
	    res.push(1);
	    return res;
	};
複製程式碼

[LeetCode]相交連結串列

編寫一個程式,找到兩個單連結串列相交的起始節點。 例如

思路: 遍歷 A 表,指標 l1 等於尾部 c3 時,讓它指向 B 表的 b1 遍歷 B 表,指標 l2 等於尾部 c3 時,讓它指向 A 表的 a1 如果兩連結串列有交點,則會同時指向 c1,因為: a1 → a2 → c1 → c2 → c3 → b1 → b2 → b3 → c1 與 b1 → b2 → b3 → c1 → c2 → c3 → a1 → a2 → c1 相等。

var getIntersectionNode = function(headA, headB) {
    if (!headA || !headB) return null;
    if (headA == headB) return headA;
    var l1 = headA;
    var l2 = headB;
    var count = 0;
    while(l1 != l2 && count < 3){
        if (!l1.next || !l2.next) count++;
        l1 = l1.next ? l1.next : headB;
        l2 = l2.next ? l2.next : headA;
    }
    return l1==l2 ? l1 : null;
};
複製程式碼

[LeetCode]打家劫舍

你是一個專業的小偷,計劃偷竊沿街的房屋。每間房內都藏有一定的現金,影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。 給定一個代表每個房屋存放金額的非負整數陣列,計算你在不觸動警報裝置的情況下,能夠偷竊到的最高金額。 思路: 偷取第 i 家時,有兩種選擇: 偷取第 i 家,此時金額為:res[i] = res[i-2]+nums[i]; 不偷,此時金額為:res[i] = res[i-1]; 所以最高金額為兩者取較大值。

var rob = function(nums) {
    var len = nums.length;
    if (len < 2) return nums[len-1]?nums[len-1]:0;
    var res = [nums[0], Math.max(nums[0], nums[1])];
    for (let i=2; i<len; i++){
        res[i] = Math.max(res[i-1], nums[i]+res[i-2]);
    }
    return res[len-1];
};
複製程式碼

[LeetCode]最小棧

設計一個支援 push,pop,top 操作,並能在常數時間內檢索到最小元素的棧。 push(x) – 將元素 x 推入棧中。 pop() – 刪除棧頂的元素。 top() – 獲取棧頂元素。 getMin() – 檢索棧中的最小元素。

var MinStack = function() {
	    this.stack = []
	};
	
	MinStack.prototype.push = function(x) {
	    this.stack[this.stack.length] = x;  
	};
	
	MinStack.prototype.pop = function() {
	    this.stack.length--;
	};
	
	MinStack.prototype.top = function() {
	    return this.stack[this.stack.length-1];
	};
	
	MinStack.prototype.getMin = function() {
	    var min = this.stack[0];
	    var len = this.stack.length;
	    for (var i=1; i<len; i++){
	        if (this.stack[i]<min){
	            min = this.stack[i];
	        }
	    }
	    return min;
	};
複製程式碼

[LeetCode]只出現一次的數字

給定一個非空整數陣列,除了某個元素只出現一次以外,其餘每個元素均出現兩次。找出那個只出現了一次的元素。

var singleNumber = function(nums) {
	    nums.sort(function(a, b){
	        return a-b;
	    });
	    var len = nums.length;
	    for (var i=0; i<len; i=i+2){
	        if(nums[i]!=nums[i+1]){
	            return nums[i];
	        }
	    }
	};
複製程式碼

[LeetCode]驗證迴文串

給定一個字串,驗證它是否是迴文串,只考慮字母和數字字元,可以忽略字母的大小寫。 說明:本題中,我們將空字串定義為有效的迴文串。

var isPalindrome = function(s) {
	    var str1 = s.toUpperCase().replace(/\W/g,'');
	    var str2 = str1.split('').reverse().join('');
	    return str1==str2;
	};
複製程式碼

[LeetCode]買賣股票的最佳時機 II

給定一個陣列,它的第 i 個元素是一支給定股票第 i 天的價格。 設計一個演算法來計算你所能獲取的最大利潤。你可以儘可能地完成更多的交易(多次買賣一支股票)。 注意:你不能同時參與多筆交易(你必須在再次購買前出售掉之前的股票)。

var maxProfit = function(prices) {
	    var max = 0;
	    var len = prices.length;
	    for (var i=0; i<len-1; i++){
	        if (prices[i+1]>prices[i]){
	            max += prices[i+1]-prices[i];
	        }
	    }
	    return max;
	};
複製程式碼

[LeetCode]移除元素

給定一個陣列 nums 和一個值 val,你需要原地移除所有數值等於 val 的元素,返回移除後陣列的新長度。 不要使用額外的陣列空間,你必須在原地修改輸入陣列並在使用 O(1) 額外空間的條件下完成。 元素的順序可以改變。你不需要考慮陣列中超出新長度後面的元素。

var removeElement = function(nums, val) {
	    var i = 0;
	    var len = nums.length;
	    for (var j = 0; j<len; j++){
	        if(nums[j]!==val){
	            nums[i] = nums[j]
	            i++;
	        }
	    }
	    return i;
	};

	//方法2
	var removeElement = function(nums, val) {
	    var i = 0;
	    var len = nums.length;
	    while (i < len){
	        if (nums[i] == val) {
	            nums[i] = nums[len-1];
	            len--;
	        } else {
	            i++;
	        }
	    }
	    return len;
	};
複製程式碼

[LeetCode]平衡二叉樹

給定一個二叉樹,判斷它是否是高度平衡的二叉樹。 本題中,一棵高度平衡二叉樹定義為: 一個二叉樹每個節點 的左右兩個子樹的高度差的絕對值不超過1。

var isBalanced = function(root) {
	    if (!root) return true;
	    if (Math.abs(depth(root.left)-depth(root.right))>1) return false; 
	    return isBalanced(root.left) && isBalanced(root.right);  
	    function depth(node){
	        if (!node) return 0;
	        var left = depth(node.left);
	        var right = depth(node.right);
	        return Math.max(left, right)+1;
	    }
	};
複製程式碼

[LeetCode]刪除排序陣列中的重複項

給定一個排序陣列,你需要在原地刪除重複出現的元素,使得每個元素只出現一次,返回移除後陣列的新長度。

var removeDuplicates = function(nums) {
	    var i = 0;
	    var len = nums.length;
	    for (var j=1; j<len; j++){
	        if (nums[i] !== nums[j]){
	            i++;
	            nums[i] = nums[j]
	        }
	    }
	    return i+1;
	};
複製程式碼

[LeetCode]合併兩個有序連結串列

將兩個有序連結串列合併為一個新的有序連結串列並返回。新連結串列是通過拼接給定的兩個連結串列的所有節點組成的。

var mergeTwoLists = function (l1, l2) {
	    var lHead = new ListNode(0);
	    var lCur = lHead;
	    while (l1 !== null && l2 !== null) {
	        if(l1.val < l2.val) {
	            lCur.next = l1;
	            lCur = lCur.next;
	            l1 = l1.next;
	        } else {
	            lCur.next = l2;
	            lCur = lCur.next;
	            l2 = l2.next; 
	        }
	    }
	    if (l1 === null) {
	        lCur.next = l2;
	    } 
	    if (l2 === null) {
	        lCur.next = l1;
	    }
	    return lHead.next;
	};
複製程式碼

[LeetCode]有效的括號

給定一個只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字串,判斷字串是否有效。 有效字串需滿足: 左括號必須用相同型別的右括號閉合。 左括號必須以正確的順序閉合。 注意空字串可被認為是有效字串。

var isValid = function(s) {
	    var stack = [];
	    var len = s.length;
	    for (var i=0; i<len; i++){
	        var char = s[i];
	        var stackLen = stack.length;
	        if(stackLen==0) {
	           stack.push(char); 
	        }else{
	            if(isMatch(stack[stackLen-1],char)){
	                stack.pop();
	            }else{
	                stack.push(char);
	            }
	        }     
	    }
	    return stack.length==0;
	    
	    function isMatch(char1, char2){
	        if (char1=='(' && char2==')'||
	            char1=='{' && char2=='}'||
	            char1=='[' && char2==']'
	           ){
	            return true;
	        }
	        return false;
	    }
	};
複製程式碼

[LeetCode]最長公共字首

編寫一個函式來查詢字串陣列中的最長公共字首。如果不存在公共字首,返回空字串 “”。

var longestCommonPrefix = function(strs) {
	    if (!strs.length) return '';
	    var str1 = strs[0];
	    var res = '';
	    var str1Len = str1.length;
	    var strsLen = strs.length;
	    for (var i=0; i<str1Len; i++) {
	        for (var j=1; j<strsLen; j++) {
	            if (str1[i] !== strs[j][i]) {
	                return res;
	            }
	        }
	        res += str1[i];
	    }
	    return res;
	 }; 
複製程式碼

[LeetCode]羅馬數字轉整數

羅馬數字包含以下七種字元: I, V, X, L,C,D 和 M。 字元 數值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如, 羅馬數字 2 寫做 II ,即為兩個並列的 1。12 寫做 XII ,即為 X + II 。 27 寫做 XXVII, 即為 XX + V + II 。

var romanToInt = function(s) {
	    var romanObj = {'I': 1,'V': 5,'X': 10,'L': 50,'C': 100,'D': 500,'M': 1000};
	    var num = 0;
	    var len = s.length;
	    for (var i=0; i<len-1; i++) {
	        var curNum = romanObj[s.charAt(i)];
	        var rightNum = romanObj[s.charAt(i+1)];
	        num += curNum>=rightNum?curNum:-curNum;
	    }
	    num += romanObj[s.charAt(i)]
	    return num;
	};
複製程式碼

[LeetCode]迴文數

判斷一個整數是否是迴文數。迴文數是指正序(從左向右)和倒序(從右向左)讀都是一樣的整數。

var isPalindrome = function(x) {
    	var num = x.toString();
    	return x == num.split('').reverse().join('');
	};  

	//方法2 找到中間位置,然後兩邊對比	
	var isPalindrome = function(x) {
	    var str = x.toString();
	    var len = str.length;
	    var halfLen = (len-1)/2;
	    for (var i=0; i<halfLen; i++){
	        if(str.charAt(i)!==str.charAt(len-1-i)){
	            return false;
	        }
	    }
	    return true;
	}; 
複製程式碼

[LeetCode]反轉整數

給定一個 32 位有符號整數,將整數中的數字進行反轉。

var reverse = function(x) {
	    var num = x.toString().split('').reverse();
	    var res = parseInt(num.join(''));
	    if(res>2**31) return 0;
	    return x>0?res:-res;
	};
複製程式碼

[LeetCode]實現 strStr() 函式

給定一個 haystack 字串和一個 needle 字串,在 haystack 字串中找出 needle 字串出現的第一個位置 (從0開始)。如果不存在,則返回 -1。

var strStr = function(haystack, needle) {
	    if (needle=='') return 0;
	    var len2 = needle.length;
	    var len = haystack.length - len2;
	    for (var i = 0; i<=len; i++) {
	        if (haystack.substring(i, i+len2) == needle) {
	            return i;
	        }
	    }
	    return -1;
	};
	
	//超簡做法
	var strStr = function(haystack, needle) {
	    return haystack.indexOf(needle);
	};
複製程式碼

[LeetCode]搜尋插入位置

給定一個排序陣列和一個目標值,在陣列中找到目標值,並返回其索引。如果目標值不存在於陣列中,返回它將會被按順序插入的位置。

var searchInsert = function(nums, target) {
	    var len = nums.length;
	    for(var i=0; i<len; i++){
	        if(target<=nums[i]){
	            return i;
	        }
	    }
	    return len;
	}; 
複製程式碼

[LeetCode]將有序陣列轉換為二叉搜尋樹

將一個按照升序排列的有序陣列,轉換為一棵高度平衡二叉搜尋樹。 本題中,一個高度平衡二叉樹是指一個二叉樹每個節點 的左右兩個子樹的高度差的絕對值不超過 1。

var sortedArrayToBST = function(nums) {
	    var len = nums.length;
	    if(!len) return null;
	    if(len===1) return new TreeNode(nums[0]);
	    var mid = parseInt(len/2);
	    var root = new TreeNode(nums[mid]);
	    root.left = sortedArrayToBST(nums.slice(0, mid));
	    root.right = sortedArrayToBST(nums.slice(mid+1));
	    return root;
	};
複製程式碼

[LeetCode]二叉樹的層次遍歷 II

給定一個二叉樹,返回其節點值自底向上的層次遍歷。 (即按從葉子節點所在層到根節點所在的層,逐層從左向右遍歷)

	var levelOrderBottom = function(root) {
	    var queue = [];
	    var result = [];
	    if(root) queue.push(root);
	    while(queue.length){
	        var arr = [];
	        var len = queue.length
	        for(var i=0; i<len; i++){
	            var curNode = queue.shift();
	            arr.push(curNode.val);
	            if(curNode.left) queue.push(curNode.left);
	            if(curNode.right) queue.push(curNode.right);
	        }
	        result.unshift(arr);
	    }
	    return result;
	};
複製程式碼

[LeetCode]二叉樹的最大深度

給定一個二叉樹,找出其最大深度。 二叉樹的深度為根節點到最遠葉子節點的最長路徑上的節點數。 說明: 葉子節點是指沒有子節點的節點。

var maxDepth = function(root) {
	    if(!root) return 0;
	    var left_depth = maxDepth(root.left);
	    var right_depth = maxDepth(root.right);
	    return Math.max(left_depth, right_depth)+1;
	};
複製程式碼

[LeetCode]爬樓梯

假設你正在爬樓梯。需要 n 階你才能到達樓頂。 每次你可以爬 1 或 2 個臺階。你有多少種不同的方法可以爬到樓頂呢? 思路: f(1) : 1 f(2) : 11 , 2 f(3) : 12, 111, 21 f(4) : 121, 1111, 211, 112, 22 f(n) = f(n-1) + f(n-2)

var climbStairs = function(n) {
	    let a = b = 1;
	    for (let i = 0; i < n; i++) {
	        [a, b] = [b, a + b];//ES6的遞迴寫法
	    }
	    return a;
	};
複製程式碼

[LeetCode]合併兩個有序陣列

給定兩個有序整數陣列 nums1 和 nums2,將 nums2 合併到 nums1 中,使得 num1 成為一個有序陣列。 說明: 初始化 nums1 和 nums2 的元素數量分別為 m 和 n。 你可以假設 nums1 有足夠的空間(空間大小大於或等於 m + n)來儲存 nums2 中的元素。 示例: 輸入: nums1 = [1,2,3,0,0,0], m = 3 nums2 = [2,5,6], n = 3 輸出: [1,2,2,3,5,6]

var merge = function(nums1, m, nums2, n) {
	    for (let i=0; i<n; i++){
	        nums1[m+i] = nums2[i]
	    }
	    nums1.sort(function(a, b){
	        return a-b;
	    })
	};
複製程式碼

[LeetCode]相同的樹

給定兩個二叉樹,編寫一個函式來檢驗它們是否相同。 如果兩個樹在結構上相同,並且節點具有相同的值,則認為它們是相同的。

var isSameTree = function(p, q) {
	    if (p===null && q===null) return true;
	    if (p===null || q===null) return false;
	    if (p.val != q.val) return false;
	    return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
	};
複製程式碼

[LeetCode]對稱二叉樹

給定一個二叉樹,檢查它是否是映象對稱的。

var isSymmetric = function(root) {
	    if (!root) return true;
	    var leftAndRight = function(left, right){
	        if (!left && !right) return true;
	        if (!left || !right) return false;
	        if (left.val != right.val) return false;
	        return leftAndRight(left.left, right.right) && leftAndRight(left.right, right.left);
	    }
	    return leftAndRight(root.left, root.right);
	};
複製程式碼

[LeetCode]刪除排序連結串列中的重複元素

刪除排序連結串列中的重複元素

var deleteDuplicates = function(head) {
	    var l = head;
	    if(l==null) return null
	    while(l.next){
	        if(l.val == l.next.val){
	            l.next = l.next.next;
	        }else{
	            l = l.next;
	        }
	    }
	    return head;
	};
複製程式碼

[LeetCode]Excel表列名稱

給定一個正整數,返回它在 Excel 表中相對應的列名稱。 例如, 1 -> A 2 -> B 3 -> C ... 26 -> Z 27 -> AA 28 -> AB ...

var convertToTitle = function(n) {
    var res='';
    while(n>0){
        var a = parseInt((n-1)%26);
        n = parseInt((n-1)/26);
        res = String.fromCharCode(a+65) + res;
    }
    return res;
};
複製程式碼

歡迎關注前端公眾號:前端,更多面試經驗及內推機會。

前端面試必備-40道LeetCode經典面試演算法題

相關文章