算法 面试题

216 阅读3分钟

算法

时间复杂度和空间复杂度:衡量算法的优劣。 时间复杂度和空间复杂度是用来衡量算法的优劣的两个指标。时间复杂度表示算法执行时间与数据规模之间的关系,常用大O表示法来表示。空间复杂度表示算法在运行过程中临时占用存储空间大小的量度,也常用大O表示法来表示。

常见的算法类型包括:

  • 排序算法:快速排序、归并排序、计数排序。
  • 搜索算法:回溯、递归、剪枝技巧。
  • 图论:最短路、最小生成树、网络流建模。
  • 动态规划:背包问题、最长子序列、计数问题。
  • 基础技巧:分治、倍增、二分、贪心。

常见的考察内容包括:

  • 数组与链表:单/双向链表、跳舞链。
  • 栈与队列。
  • 树与图:最近公共祖先、并查集。
  • 哈希表。
  • 堆:大/小根堆、可并堆。
  • 字符串:字典树、后缀树。

例子:

  1. 爬楼梯:每次可以选择爬1个或2个台阶,问有多少种爬楼梯的方法。
var climbStairs = function(n) {
    if (n === 1) {
        return 1;
    }
    let dp = new Array(n + 1);
    dp[1] = 1;
    dp[2] = 2;
    for (let i = 3; i <= n; i++) {
        dp[i] = dp[i - 1] + dp[i - 2];
    }
    return dp[n];
};
  1. 有效的括号:判断括号是否正确闭合。
var isValid = function(s) {
    let stack = [];
    let map = {
        '(': ')',
        '[': ']',
        '{': '}'
    }
    for (let i = 0; i < s.length; i++) {
        if (map[s[i]]) {
            stack.push(s[i]);
        } else if (s[i] !== map[stack.pop()]) {
            return false;
        }
    }
    return stack.length === 0;
};
  1. 整数转化英文表示:将整数转化为英文表示。
const singles = ["", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"];
const teens = ["Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"];
const tens = ["", "Ten", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"];
const thousands = ["", "Thousand", "Million", "Billion"];

var numberToWords = function(num) {
    if (num === 0) {
        return 'Zero';
    }
    let sb = '';
    let unit = 1000000000;
    for (let i = 3; i >= 0; i--) {
        let curNum = Math.floor(num / unit);
        if (curNum !== 0) {
            num -= curNum * unit;
            sb += toEnglish(curNum) + thousands[i] + ' ';
        }
        unit /= 1000;
    }
    return sb.trim();
};

function toEnglish(num) {
    let curr = '';
    let hundred = Math.floor(num / 100);
    num %= 100;
    if (hundred !== 0 && num !== 0) {
        curr += singles[hundred] + ' Hundred ';
    } else if (hundred !== 0 && num === 0) {
        curr += singles[hundred] + ' Hundred';
    }
    
    let ten = Math.floor(num / 10);
    if (ten >= 2 && num % 10 !== 0) {
        curr += tens[ten] + ' ';
        num %= 10;
    } else if (ten >= 2 && num % 10 === 0) {
        curr += tens[ten];
        num %= 10;
    }

    if (num < 10 && num > 0) {
        curr += singles[num] + ' ';
    } else if (num >=10 && num <20) {
        curr += teens[num -10] + ' ';
    }

    return curr;
}
  1. Z 字形变换:将字符串按照Z字形排列后输出。
var convert = function(s, numRows) {
    if (numRows === 1 || s.length < numRows) return s;

    let rows = [];
    let converted = '';
    let reverse = false;
    let count = 0;

    for (let i=0; i<numRows; i++) rows[i] = [];
    
    for (let i=0; i<s.length; i++) {
        rows[count].push(s[i]);
        
        if (count === numRows-1 || count === 0) reverse=!reverse;
        
        reverse ? count++ : count--;
        
     }
    
     for(let row of rows){
         converted+=row.join('');
     }
    
     return converted;
};
  1. 两数之和:在数组中找出和为目标值的两个数。
var twoSum = function(nums, target) {
    let map = new Map();
    for (let i = 0; i < nums.length; i++) {
        let complement = target - nums[i];
        if (map.has(complement)) {
            return [map.get(complement), i];
        }
        map.set(nums[i], i);
    }
};
  1. 最长回文子串:找出字符串中最长的回文子串。
var longestPalindrome = function(s) {
    if (s.length < 2) return s;
    let start = 0;
    let maxLength = 1;

    function expandAroundCenter(left, right) {
        while (left >= 0 && right < s.length && s[left] === s[right]) {
            if (right - left + 1 > maxLength) {
                maxLength = right - left + 1;
                start = left;
            }
            left--;
            right++;
        }
    }

    for (let i = 0; i < s.length; i++) {
        expandAroundCenter(i - 1, i + 1);
        expandAroundCenter(i, i + 1);
    }

    return s.substring(start, start + maxLength);
};