leetCode常见基础题目记录

337 阅读3分钟

344.翻转字符串

leetcode-cn.com/problems/re…

描述:

编写一个函数,其作用是将输入的字符串反转过来。必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

输入: s = ["h","e","l","l","o"]
输出: ["o","l","l","e","h"]
输入: s = ["H","a","n","n","a","h"]
输出: ["h","a","n","n","a","H"]

思路:

解构赋值翻转第i和第str.length - 1 - i个元素

题解:

var reverseString = function (s) {
    const solution = (str) => {
        for (let i = 0; i < str.length / 2; i++) {
            [str[i], str[str.length - 1 - i]] = [str[str.length - 1 - i], str[i]]; // core
        }
    };

    return solution(s);
};

387.字符串中的第一个唯一字符

leetcode-cn.com/problems/fi…

描述:

给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。

s = "leetcode"
返回 0

s = "loveleetcode"
返回 2

思路:

方案1: indexOf === lastIndexOf

方案2: 两次循环 第一次循环建哈希表存字符 -> 出现次数的映射;第二次筛选第一个value为1的key

题解:

const solution = (str) => {
  for (let i = 0; i < str.length; i++) {
    if (str.indexOf(str[i]) === str.lastIndexOf(str[i])) {  // core
      return i;
    }
  }
  return -1;
};
const solution2 = (s) => {
  const hash = {};

  for (const item of s) {
    hash[item] = (hash[item] || 0) + 1;
  }

  for (let i = 0; i < s.length; i++) {
    if (hash[s[i]] === 1) {
      return i;
    }
  }
  return -1;
};

14.最长公共前缀

leetcode-cn.com/problems/lo…

描述:

编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串 ""

输入: strs = ["flower","flow","flight"]
输出: "fl"
输入: strs = ["dog","racecar","car"]
输出: ""
解释: 输入不存在公共前缀。

思路:

取第一个字符串作为初始最长公共子串,循环逐位对比,不断截断公共子串,得到最终结果

题解:

const solution = (strs) => {
  if (strs.length === 0) {
    return '';
  }

  let curCommonString = strs[0];

  for (const item of strs) {
    let i = 0;
    for (; i < item.length; i++) {
      if (curCommonString[i] !== item[i]) {
        break;
      }
    }

    curCommonString = curCommonString.slice(0, i);

    if (curCommonString === '') {
      return '';
    }
  }

  return curCommonString;
};

88.合并两个有序数组

leetcode-cn.com/problems/me…

描述:

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。

请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3][2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。
输入: nums1 = [1], m = 1, nums2 = [], n = 0
输出: [1]
解释: 需要合并 [1][] 。
合并结果是 [1]
输入:nums1 = [0], m = 0, nums2 = [1], n = 1
输出:[1]
解释:需要合并的数组是 [][1] 。
合并结果是 [1] 。
注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。

思路:

双指针倒推

题解:

// 回去等通知版
const solution = (nums1, m, nums2, n) => {
  nums1 = [...nums1.slice(0, m), ...nums2.slice(0, n)].sort();
};
const solution2 = function (nums1, m, nums2, n) {
  let i = nums1.length - 1;

  m--;
  n--;

  while (n >= 0) {
    nums1[m] > nums2[n] ? (nums1[i--] = nums1[m--]) : (nums1[i--] = nums2[n--]);
  }
};

剑指 Offer 03. 数组中重复的数字

leetcode-cn.com/problems/sh…

描述:

输入:
[2, 3, 1, 0, 2, 5, 3]
输出: 23 

思路:

hash

题解:

const solution = (nums) => {
  const hash = {};

  for (const item of nums) {
    if (hash[item]) {
      return item;
    } else {
      hash[item] = 1;
    }
  }
};

349. 两个数组的交集

leetcode-cn.com/problems/in…

描述:

输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2]
输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出: [9,4]

思路:

hash 两次遍历 空间换时间

题解:

const solution = (nums1, nums2) => {
  const hash = {};
  const result = new Set();

  for (const item of nums1) {
    hash[item] = 1;
  }

  for (const item of nums2) {
    if (hash[item]) {
      result.add(item);
    }
  }

  return [...result];
};

21. 合并两个有序链表

leetcode-cn.com/problems/me…

描述:

输入: l1 = [1,2,4], l2 = [1,3,4]
输出: [1,1,2,3,4,4]

思路:

递归

  1. 何时结束: 有任意一个链表遍历结束
  2. 本次递归要做什么: 将上一次比对的结果与本次较小的节点连接
  3. 本次递归要返回什么: 两个节点中较小的那个节点

题解:

const changeCurNode = (node1, node2) => {
    if (node1 === null) {
        return node2;
    } else if (node2 === null) {
        return node1;
    }

    if (node1.val > node2.val) {
        node2.next = changeCurNode(node1, node2.next);
        return node2;
    } else {
        node1.next = changeCurNode(node1.next, node2);

        return node1;
    }
};

面试题 02.03 删除中间节点

描述:删除传入的链表节点

leetcode-cn.com/problems/de…

思路:水题

题解:

var deleteNode = function(node) {
  node.val = node.next.val;
  node.next = node.next.next; 
};

203.移除链表元素

leetcode-cn.com/problems/re…

描述:

输入: head = [1,2,6,3,4,5,6], val = 6
输出: [1,2,3,4,5]

思路:递归

递归

  1. 何时结束: 当前节点为空
  2. 本次递归要做什么: 连接上一次的结果
  3. 本次递归要返回什么: 根据是否与目标值相等返回节点

题解:

var removeElements = function (head, val) {
    if (head === null) {
        return head;
    }

    head.next = removeElements(head.next, val);
    return head.val === val ? head.next : head;
};

203. 翻转链表

leetcode-cn.com/problems/re…

描述:

输入: head = [1,2,3,4,5]
输出: [5,4,3,2,1]

思路:

  1. 循环改变每个节点的指针指向
  2. 递归 用递归完成链表的遍历
    何时结束:当前节点为空
    本次递归返回什么:下一个节点
    本次递归做什么:使本节点head下一个节点head.next指向本节点,完成反转。

image.png 题解:

var reverseList = function (head) {
    let prev = null;
    let cur = head;

    while (cur) {
        const next = cur.next; // 暂存next

        cur.next = prev; // core 改变指针指向

        prev = cur;
        cur = next;
    }

    return prev; // 注意不是返回cur
};
const reverseList = function (head) {
  if (head === null || head.next === null) {
    return head;
  }

  const newHead = reverseList(head.next);

  head.next.next = head;
  head.next = null;

  return newHead;
};

template

描述:

思路:

题解: