leetcode

195 阅读2分钟

1. 两数之和

思路

  1. 创建一个Map,for循环遍历nums数组;
  2. 用target减nums[i],得到符合要求的数字targetNum
  3. 检查map里有没有targetNum: 如果没有则将nums[i]当做key,i当做value存入map;如果有则返回结果;

code

  const twoSum = (nums, target) => {

  const prevNums = new Map();                    // 存储出现过的数字,和对应的索引               
  for (let i = 0; i < nums.length; i++) { // 遍历元素   
    const curNum = nums[i];               // 当前元素   
    const targetNum = target - curNum;    // 满足要求的目标元素   
    if (prevNums.has(targetNum)) {   // 如果存在,直接返回 [目标元素的索引,当前索引]
      return [prevNums.get(targetNum), i];
    } else {                              // 如果不存在,说明之前没出现过目标元素
      prevNums.set(curNum, i)
    }
  }
}

2. 两数相加

思路

code

3. 无重复字符的最长子串

思路

  1. 创建一个set和maxLength;
  2. 创建两个指针i和j,j指向字符串开头,i随着for循环遍历字符串s;
  3. 如果set里没有s[i],说明目前为止还没有重复的字符,把s[i]添加到set里,比较maxLength和set.size,maxLength取最大值;
  4. 如果set里有s[i],则从set里删除s[j],并且递增j,再检查set里有没有s[i];
  5. 重复步骤3和4,直到遍历完整个字符串;
  6. 返回set的长度;

code

 var lengthOfLongestSubstring = function (s) {

      if (s.length === 0) {
        return 0;
      }

      const temp = new Set();
      let maxLength = 1;

      let i = 0, j = 0;

      for (i; i < s.length; i++) {
        if (temp.has(s[i])) {
          while (temp.has(s[i])) {
            temp.delete(s[j]);
            j++;
          }
          temp.add(s[i])

        } else {
          temp.add(s[i])
          
        }

        maxLength = maxLength > temp.size ? maxLength : temp.size;

      }

      return maxLength;
    };

5. 最长回文子串

思路

  1. 如果字符串的长度小于2,直接返回愿字符串;
  2. 定义两个变量,一个start存储当前找到的最大字符串的位置,另一个maxLength记录字符串的长度(终止位置 = start + maxLength);
  3. 创建一个helper function,判断左边和右边是否越界,最左边的字符是否等于最右边的字符;如果以上三个条件都满足,则判断是否需要更新maxLenght和start,然后left--,right++,继续判断直到不满足以上三个条件之一;
  4. 遍历字符串,每个位置调用helper function两遍,第一次检查i-1,i+1,第二次检查i,i+1;

code

var longestPalindrome = function(s) {

  if (s.length < 2) {
    return s;
  }

  let start = 0, maxLength = 1;

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

      left--;
      right++;
    }
  }

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

  return s.substr(start, maxLength)
};

15. 三数之和

思路

  1. 给数组排序;
  2. 遍历数组,从0到target-2;
  3. 如果当前数字等于前一个数字,则跳过这个数字;
  4. 如果数字不同,则设置start = i + 1,end = length - 1,查看i、start和end三个数的和比零大还是比零小,如果比0小,start++,如果比0大,end--;
  5. 返回结果;

19. 删除链表的倒数第N个节点

思路

code

[20. 有效的括号

](leetcode-cn.com/problems/va…)

[21. 合并两个有序链表

](leetcode-cn.com/problems/me…)

[24. 两两交换链表中的节点

](leetcode-cn.com/problems/sw…)

39. 数组中出现次数超过一半的数字

/**
 * 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
 * 你可以假设数组是非空的,并且给定的数组总是存在多数元素
 * 
 * 输入: [1, 2, 3, 2, 2, 2, 5, 4, 2]
 * 输出: 2
 */

摩尔投票法

    var majorityElement = function (nums) {
      let count = 1;
      let result = nums[0];

      for (let i = 1; i < nums.length; i++){
        if (count === 0) {
          result = nums[i]
        }

        if (result === nums[i]) {
          count++;
        } else {
          count--;
        }
      }

      return result;
    };

算法复杂度

时间复杂度: 时间复杂度 O(n) 空间复杂度:O(1)

斐波那契数列/青蛙跳台阶

递归 + 动态规划

function fib(n) {

  var temp = {};

  function count(n) {
    let result;

    if (temp[n]) {
      return temp[n]
    }

    if (n <= 0) {
      result = 0;
    } else if (n === 1) {
      result = 1
    } else if (n === 2) {
      result = 1

    } else {

      result = count(n - 1) + count(n - 2);
    }

    temp[n] = result;

    return result;
  }

  return count(n);

};

硬币找零

/**
 * 给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。
 * 如果没有任何一种硬币组合能组成总金额,返回 -1。
 * 
 * 输入: coins = [1, 2, 5], amount = 11
 * 输出: 3
 * 解释: 11 = 5 + 5 + 1
 */

贪心算法

function coinChange(coins: number[], amount: number): number {
  function _coinChange(coins: number[], amount: number): number[] {
    if (amount <= 0) {
      return [];
    }

    // 数组里的最大值 && <= amount
    let temp = 0;
    for (let i = 0; i < coins.length; i++) {
      let coin = coins[i];
      if (temp < coin && coin <= amount) {
        temp = coin;
      }
    }

    let result = [temp];

    const next = _coinChange(coins, amount - temp);

    result = result.concat(next);

    return result;
  }

  const result = _coinChange(coins, amount);

  return result.length;
}

最长公共子序列

分治法 + 动态规划

var longestCommonSubsequence = function (text1, text2) {

  var temp = [];

  function _(text1, text2) {
    // num++;

    if (text1 === '' || text2 === '') {
      return '';
    }

    for(let item of temp) {
      if (item.str1 === text1 && item.str2 === text2) {
        return item.result;
      }
    }

    let result = '';

    if (text1[0] === text2[0]) {
      result = text1[0] + _(text1.substr(1), text2.substr(1));
    } else {
      let lcs1 = _(text1.substr(1), text2)
      let lcs2 = _(text1, text2.substr(1));

      result = lcs1.length > lcs2.length ? lcs1 : lcs2;
    }

    temp.push({
      str1: text1,
      str2: text2,
      result
    })

    return result;
  }

  return _(text1, text2).length;

};