# leetcode 各种题

# 双指针

# 88.合并两个有序数组

给定两个有序整数数组  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]

/**
 * @param {number[]} nums1
 * @param {number} m
 * @param {number[]} nums2
 * @param {number} n
 * @return {void} Do not return anything, modify nums1 in-place instead.
 */
var merge = function(nums1, m, nums2, n) {
  let len1 = m - 1;
  let len2 = n - 1;
  let len = m + n - 1;
  while (len1 >= 0 && len2 >= 0) {
    // 注意--符号在后面,表示先进行计算再减1,这种缩写缩短了代码
    nums1[len--] = nums1[len1] > nums2[len2] ? nums1[len1--] : nums2[len2--];
  }
  function arrayCopy(src, srcIndex, dest, destIndex, length) {
    dest.splice(destIndex, length, ...src.slice(srcIndex, srcIndex + length));
  }
  // 表示将nums2数组从下标0位置开始,拷贝到nums1数组中,从下标0位置开始,长度为len2+1
  arrayCopy(nums2, 0, nums1, 0, len2 + 1);
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 350. 两个数组的交集 II

给定两个数组,编写一个函数来计算它们的交集。

示例 1:

输入: nums1 = [1,2,2,1], nums2 = [2,2] 输出: [2,2] 示例 2:

输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4] 输出: [4,9] 说明:

输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致。 我们可以不考虑输出结果的顺序。 进阶:

如果给定的数组已经排好序呢?你将如何优化你的算法? 如果  nums1  的大小比  nums2  小很多,哪种方法更优? 如果  nums2  的元素存储在磁盘上,磁盘内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?

方法一:哈希法

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
var intersect = function(nums1, nums2) {
  let hash = new Map();
  let res = [];
  for (let i = 0; i < nums1; i++) {
    if (hash.has(nums1[i])) {
      hash.set(nums1[i], hash.get(nums1[i]) + 1);
    } else {
      hash.set(nums1[i], 1);
    }
  }
  for (let j = 0; j < nums2.length; j++) {
    if (hash.has(nums2[j]) && hash.get(nums2[j]) > 0) {
      console.log(11);
      res.push(nums2[j]);
      hash.set(nums2[j], hash.get(nums2[j]) - 1);
    }
  }
  return res;
};

intersect([1, 2, 2, 1], [2, 2]);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

方法二:双指针法

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
var intersect = function(nums1, nums2) {
  nums1.sort((a, b) => a - b);
  nums2.sort((a, b) => a - b);
  let l = nums1.length - 1;
  let r = nums2.length - 1;
  let res = [];
  while (l > 0 && r > 0) {
    if (nums1[l] === nums2[r]) {
      res.push(nums1[l]);
      l--;
      r--;
    } else if (nums1[l] < nums2[r]) {
      r--;
    } else {
      l--;
    }
  }
  console.log(res);
  return res;
};

intersect([1, 2, 2, 1], [2, 2]);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 925. 长按键入

你的朋友正在使用键盘输入他的名字  name。偶尔,在键入字符  c  时,按键可能会被长按,而字符可能被输入 1 次或多次。

你将会检查键盘输入的字符  typed。如果它对应的可能是你的朋友的名字(其中一些字符可能被长按),那么就返回  True。

/**
 * @param {string} name
 * @param {string} typed
 * @return {boolean}
 */
var isLongPressedName = function(name, typed) {
  let l = 0;
  let r = 0;
  while (l < name.length) {
    if (name[l] === typed[r]) {
      l++;
      r++;
    } else if (name[l - 1] === typed[r]) {
      r++;
    } else {
      return false;
    }
  }
  return true;
};

isLongPressedName("alex", "aaleex");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 125. 验证回文串

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。

说明:本题中,我们将空字符串定义为有效的回文串。

/**
 * @param {string} s
 * @return {boolean}
 */
var isPalindrome = function(s) {
  s = s.replace(/[^0-9a-zA-Z]/g, "").toLowerCase();
  let l = 0;
  let r = s.length - 1;
  while (l < r) {
    if (s[l] !== s[r]) {
      return false;
    }
    l++;
    r--;
  }
  return true;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 234. 回文链表

暴力法

var isPalindrome = function(head) {
  let nums = [];
  while (head) {
    nums.push(head.val);
    head = head.next;
  }

  while (nums.length > 1) {
    if (nums.pop() != nums.shift()) return false;
  }
  return true;
};
1
2
3
4
5
6
7
8
9
10
11
12

双指针法

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @return {boolean}
 */
var isPalindrome = function(head) {
  // 首先找到链表的中点
  if (head === null) true;
  let middle = head,
    end = head;
  let num = 0; // 链表节点的总个数
  while (end !== null) {
    num++;
    end = end.next;
    if ((num & 1) === 0) {
      middle = middle.next;
    }
  }
  // 然后反转前一部分链表
  let pre = null,
    cur = head,
    next;
  while (cur !== middle) {
    next = cur.next;
    cur.next = pre;
    pre = cur;
    cur = next;
  }
  // 最后根绝链表总数的奇偶性不同选取左右部分的起始节点,然后开始遍历
  let leftStart = pre,
    rightStart;
  if (num & 1) {
    // 如果链表节点个数是奇数,那么middle指向的是链表的中点
    rightStart = middle.next;
  } else {
    // 如果链表节点个数是偶数,那么middle指向的是后半部第一个节点
    rightStart = middle;
  }
  while (leftStart !== null && rightStart !== null) {
    if (leftStart.val !== rightStart.val) {
      return false;
    }
    leftStart = leftStart.next;
    rightStart = rightStart.next;
  }
  return true;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

# 532. 数组中的 K-diff 数对

给定一个整数数组和一个整数  k, 你需要在数组里找到不同的  k-diff 数对。这里将  k-diff  数对定义为一个整数对 (i, j), 其中 i 和 j 都是数组中的数字,且两数之差的绝对值是  k.

示例 1:

输入: [3, 1, 4, 1, 5], k = 2 输出: 2 解释: 数组中有两个 2-diff 数对, (1, 3) 和 (3, 5)。 尽管数组中有两个 1,但我们只应返回不同的数对的数量。 示例  2:

输入:[1, 2, 3, 4, 5], k = 1 输出: 4 解释: 数组中有四个 1-diff 数对, (1, 2), (2, 3), (3, 4) 和 (4, 5)。 示例 3:

输入: [1, 3, 1, 5, 4], k = 0 输出: 1 解释: 数组中只有一个 0-diff 数对,(1, 1)。 注意:

数对 (i, j) 和数对  (j, i) 被算作同一数对。 数组的长度不超过 10,000。 所有输入的整数的范围在  [-1e7, 1e7]。

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var findPairs = function(nums, k) {
  if (k < 0 || nums.length < 2) {
    return 0;
  }
  const length = nums.length;
  let count = 0;
  let start = 0;
  let end = 1;
  nums = nums.sort((a, b) => a - b);
  while (start < length && end < length) {
    if (start > 0 && nums[start] === nums[start - 1]) {
      start++;
    }
    if (nums[end] - nums[start] > k) {
      start++;
    } else if (nums[end] - nums[start] < k || start == end) {
      end++;
    } else if (nums[end] - nums[start] == k) {
      count++;
      end++;
      while (end < length && nums[end] === nums[end - 1]) {
        end++;
      }
    }
  }
  return count;
};

findPairs([3, 1, 4, 1, 5], 2);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

# 287. 寻找重复数

给定一个包含  n + 1 个整数的数组  nums,其数字都在 1 到 n  之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。

示例 1:

输入: [1,3,4,2,2] 输出: 2 示例 2:

输入: [3,1,3,4,2] 输出: 3 说明:

不能更改原数组(假设数组是只读的)。 只能使用额外的 O(1) 的空间。 时间复杂度小于 O(n2) 。 数组中只有一个重复的数字,但它可能不止重复出现一次。

/**
 * @param {number[]} nums
 * @return {number}
 */
var findDuplicate = function(nums) {
  let slow = nums[0];
  let fast = nums[slow];
  while (slow != fast) {
    slow = nums[slow];
    fast = nums[nums[fast]];
  }
  fast = 0;
  while (fast != slow) {
    console.log(nums[slow]);
    slow = nums[slow];
    fast = nums[fast];
  }

  return nums[slow];
};

findDuplicate([1, 3, 4, 2, 2]);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 986. 区间列表的交集

给定两个由一些闭区间组成的列表,每个区间列表都是成对不相交的,并且已经排序。

返回这两个区间列表的交集。

(形式上,闭区间  [a, b](其中  a <= b)表示实数  x  的集合,而  a <= x <= b。两个闭区间的交集是一组实数,要么为空集,要么为闭区间。例如,[1, 3] 和 [2, 4] 的交集为 [2, 3]。)

输入:A = [[0,2],[5,10],[13,23],[24,25]], B = [[1,5],[8,12],[15,24],[25,26]] 输出:[[1,2],[5,5],[8,10],[15,23],[24,24],[25,25]] 注意:输入和所需的输出都是区间对象组成的列表,而不是数组或列表。

/**
 * @param {number[][]} A
 * @param {number[][]} B
 * @return {number[][]}
 */
var intervalIntersection = function(A, B) {
  if (A == [] || B == []) {
    return [];
  }
  var result = [];
  var a = A[0];
  var b = B[0];
  var m, n;
  var iA = 1;
  var iB = 1;
  while (iA <= A.length && iB <= B.length) {
    if (a[0] >= b[0]) {
      m = a[0];
      if (a[1] > b[1]) {
        n = b[1];
      } else {
        n = a[1];
      }
    } else {
      m = b[0];
      if (a[1] > b[1]) {
        n = b[1];
      } else {
        n = a[1];
      }
    }
    if (n >= m) {
      var tmp = [];
      tmp[0] = m;
      tmp[1] = n;
      result[result.length] = tmp;
    }
    if (b[1] >= a[1]) {
      a = A[iA];
      iA++;
    } else {
      b = B[iB];
      iB++;
    }
  }
  return result;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

# 11. 盛最多水的容器

给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点  (i, ai) 。在坐标内画 n 条垂直线,垂直线 i  的两个端点分别为  (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与  x  轴共同构成的容器可以容纳最多的水。

说明:你不能倾斜容器,且  n  的值至少为 2。 图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

/**
 * @param {number[]} height
 * @return {number}
 */
var maxArea = function(height) {
  let i = 0;
  let j = height.length - 1;
  let maxArea = 0;
  while (i < j) {
    maxArea = Math.max((j - i) * Math.min(height[i], height[j]), maxArea);
    if (height[i] <= height[j]) {
      i++;
    } else {
      j--;
    }
  }
  return maxArea;
};

maxArea([1, 8, 6, 2, 5, 4, 8, 3, 7]);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 75. 颜色分类

给定一个包含红色、白色和蓝色,一共  n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

注意: 不能使用代码库中的排序函数来解决这道题。

三指针法

var sortColors = function(nums) {
  if (nums.length > 1) {
    var p0 = 0,
      p2 = nums.length - 1,
      curr = 0;
  }
  while (curr <= p2) {
    if (nums[curr] == 0) {
      [nums[p0], nums[curr]] = [nums[curr], nums[p0]];
      p0++;
      curr++;
    } else if (nums[curr] == 2) {
      [nums[p2], nums[curr]] = [nums[curr], nums[p2]];
      p2--;
    } else {
      curr++;
    }
  }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 86. 分隔链表

给定一个链表和一个特定值 x,对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前。

你应当保留两个分区中每个节点的初始相对位置。

示例:

输入: head = 1->4->3->2->5->2, x = 3 输出: 1->2->2->4->3->5

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} x
 * @return {ListNode}
 */
var partition = function(head, x) {
  let before_head = new ListNode(null);
  let before = before_head;
  let after_head = new ListNode(null);
  let after = after_head;
  while (head !== null) {
    if (head.val < x) {
      before.next = head;
      before = before.next;
    } else {
      after.next = head;
      after = after.next;
    }
    head = head.next;
  }
  after.next = null;
  before.next = after_head.next;
  return before_head.next;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 1248. 统计「优美子数组」

给你一个整数数组  nums 和一个整数 k。

如果某个 连续 子数组中恰好有 k 个奇数数字,我们就认为这个子数组是「优美子数组」。

请返回这个数组中「优美子数组」的数目。

# 142. 环形链表 II

给定一个链表,返回链表开始入环的第一个节点。  如果链表无环,则返回  null。

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

说明:不允许修改给定的链表。

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
//  拆分逻辑 先获取首次相遇的时候的节点
var getCycleFistMeetNode = function(head) {
  if (!head || !head.next) {
    return false;
  }
  let slow = head.next;
  let fast = head.next.next;
  while (fast) {
    if (slow == fast) {
      return fast;
    }
    slow = slow.next;
    if (fast.next && fast.next.next) {
      fast = fast.next.next;
    } else {
      fast = null;
    }
  }
  return false;
};
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var detectCycle = function(head) {
  // 判断是否获取到了首次相遇的节点
  let firstNode = getCycleFistMeetNode(head)
    ? getCycleFistMeetNode(head)
    : false;
  let cur = head;
  if (firstNode) {
    while (firstNode) {
      if (cur === firstNode) {
        return cur;
      }
      cur = cur.next;
      firstNode = firstNode.next;
    }
  }
  return null;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
const test = head => {
  if (!head || !head.next) {
    return false;
  }
  let slow = head.next;
  let fast = head.next.next;
  while (fast) {
    if (slow == fast) {
      return fast;
    } else {
      slow = slow.next;
      if (fast.next && fast.next.next) {
        fast = fast.next.next;
      } else {
        fast = null;
      }
    }
  }
  return false;
};

var detectCycle = function(head) {
  let firstNode = test(head);
  let newNode = head;
  if (firstNode) {
    while (newNode) {
      if (newNode == firstNode) {
        return newNode;
      }
      newNode = newNode.next;
      firstNode = firstNode.next;
    }
  }
  return null;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

# 1004. 最大连续 1 的个数 III

给定一个由若干 0 和 1 组成的数组 A,我们最多可以将 K 个值从 0 变成 1 。

返回仅包含 1 的最长(连续)子数组的长度。

/**
 * @param {number[]} A
 * @param {number} K
 * @return {number}
 */
var longestOnes = function(A, K) {
  let i = 0;
  let j = 0;
  let left = K;
  let res = 0;
  while (j < A.length) {
    if (A[j] === 0) {
      if (left === 0) {
        if (A[i] === 0) {
          left++;
        }
        i++;
      } else {
        left--;
        j++;
      }
    } else {
      j++;
    }
    res = Math.max(res, j - i);
  }
  return res;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 424. 替换后的最长重复字符

给你一个仅由大写英文字母组成的字符串,你可以将任意位置上的字符替换成另外的字符,总共可最多替换 k 次。在执行上述操作后,找到包含重复字母的最长子串的长度。

/**
 * @param {string} s
 * @param {number} k
 * @return {number}
 */
var characterReplacement = function(s, k) {
  let start = 0;
  let hash = {};
  let charNum = 0;
  let longNum = 0;
  for (let i = 0, len = s.length; i < len; i++) {
    let c1 = s[i];
    hash[c1] = hash[c1] || 0;
    hash[c1] += 1;
    charNum = Math.max(charNum, hash[c1]);
    if (i - start + 1 - charNum > k) {
      hash[s[start]]--;
      start++;
    }
    longNum = Math.max(longNum, i - start + 1);
  }
  return longNum;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 524. 通过删除字母匹配到字典里最长单词

给定一个字符串和一个字符串字典,找到字典里面最长的字符串,该字符串可以通过删除给定字符串的某些字符来得到。如果答案不止一个,返回长度最长且字典顺序最小的字符串。如果答案不存在,则返回空字符串。

/**
 * @param {string} s
 * @param {string[]} d
 * @return {string}
 */
var findLongestWord = function(s, d) {
  const sl = s.length;
  const dl = d.length;
  if (sl === 0 || dl === 0) {
    return "";
  }
  let res = "";
  for (let i = 0; i < dl; i++) {
    let left = 0;
    let right = 0;
    const il = d[i].length;
    while (left < sl && right < il) {
      if (s[left] === d[i][right]) {
        right++;
      }
      left++;
    }
    if (right == il) {
      if (res.length > right) {
        res = res;
      } else if (res.length == right) {
        res = res <= d[i] ? res : d[i];
      } else {
        res = d[i];
      }
    }
  }
  return res;
};

var s = "bab",
  d = ["ba", "ab", "a", "b"];

findLongestWord(s, d);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

# (16. 最接近的三数之和)[https://leetcode-cn.com/problems/3sum-closest/]

给定一个包括  n 个整数的数组  nums  和 一个目标值  target。找出  nums  中的三个整数,使得它们的和与  target  最接近。返回这三个数的和。假定每组输入只存在唯一答案。

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var threeSumClosest = function(nums, target) {
  const len = nums.length;
  if (len < 3) {
    return null;
  }
  nums = nums.sort((a, b) => {
    return a - b;
  });

  let res = nums[0] + nums[1] + nums[2];
  for (let i = 0; i < len; i++) {
    let start = i + 1;
    let end = len - 1;
    while (start < end) {
      const num = nums[start] + nums[end] + nums[i];
      const diff = num - target;
      if (Math.abs(diff) < Math.abs(target - res)) {
        res = num;
      }
      if (diff > 0) {
        end--;
      } else if (diff < 0) {
        start++;
      } else {
        return res;
      }
    }
  }
  return res;
};

threeSumClosest([-1, 2, 1, -4], 1);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

# 61. 旋转链表

给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} k
 * @return {ListNode}
 */
var rotateRight = function(head, k) {
  if (!head) return null;
  let curr = head,
    tmp = null,
    n = 0;
  while (curr) {
    n++;
    if (!curr.next) {
      curr.next = head;
      break;
    }
    curr = curr.next;
  }
  k = k % n;
  while (k++ < n) {
    k === n && (tmp = head);
    head = head.next;
  }
  tmp.next = null;
  return head;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

# 881. 救生艇

第  i  个人的体重为  people[i],每艘船可以承载的最大重量为  limit。

每艘船最多可同时载两人,但条件是这些人的重量之和最多为  limit。

返回载到每一个人所需的最小船数。(保证每个人都能被船载)。

/**
 * @param {number[]} people
 * @param {number} limit
 * @return {number}
 */
var numRescueBoats = function(people, limit) {
  if (!people || people.length === 0) {
    return null;
  }
  let count = 0;
  people = people.sort((a, b) => {
    return a - b;
  });
  const len = people.length;
  let left = 0;
  let right = len - 1;
  let res = 0;
  while (left <= right) {
    count++;
    res = people[left] + people[right];
    if (res > limit) {
      right--;
    } else {
      left++;
      right--;
    }
  }
  return count;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

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

给定一个链表,删除链表的倒数第  n  个节点,并且返回链表的头结点。

示例:

给定一个链表: 1->2->3->4->5, 和 n = 2.

当删除了倒数第二个节点后,链表变为 1->2->3->5.

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} n
 * @return {ListNode}
 */
var removeNthFromEnd = function(head, n) {
  if (!head) {
    return null;
  }
  var _head = head;
  var current = head;
  var l = 1;
  while (current.next) {
    current = current.next;
    l++;
  }
  var len = l - n;
  if (len == 0) {
    var newHead = head.next;
    head.next = null;
    return newHead;
  }
  if (n == 0) {
    return head;
  }
  current = head;
  var pre = null;
  for (var i = 0; i < len; i++) {
    pre = current;
    current = current.next;
  }
  if (current.next) {
    pre.next = current.next;
    current.next = null;
    return head;
  } else {
    pre.next = null;
    current.next = null;
    return head;
  }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

# 42. 接雨水

/**
 * @param {number[]} height
 * @return {number}
 */
var trap = function(height) {
  if (!height || height.length < 3) {
    return null;
  }
  var len = height.length;
  var left = 0;
  var right = len - 1;
  var left_max = 0;
  var right_max = 0;
  var res = 0;
  while (left < right) {
    if (height[left] < height[right]) {
      if (height[left] <= left_max) {
        res += left_max - height[left];
      } else {
        left_max = height[left];
      }
      left++;
    } else {
      if (height[right] <= right_max) {
        res += right_max - height[right];
      } else {
        right_max = height[right];
      }
      right--;
    }
  }

  return res;
};

trap([4, 2, 3]);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

# 链表

# 138. 复制带随机指针的链表

/**
 * // Definition for a Node.
 * function Node(val, next, random) {
 *    this.val = val;
 *    this.next = next;
 *    this.random = random;
 * };
 */
/**
 * @param {Node} head
 * @return {Node}
 */
var copyRandomList = function(head) {
    if(!head) {
        return null;
    }
    let res = new Node();
    let _head = res, curr = head, hash = new Map();
    while(curr) {
        _head.val = curr.val;
        _head.next = curr.next ? new Node() : null;
        hash.set(curr, _head);
        _head = _head.next;
        curr = curr.next;
    }
    _head = res;
    while(head) {
        _head.random = head.random ? hash.get(head.random) : null;
        _head = _head.next;
        head = head.next;
    }
    return res;
    
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

# 相交链表

编写一个程序,找到两个单链表相交的起始节点。

暴力法

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */

/**
 * @param {ListNode} headA
 * @param {ListNode} headB
 * @return {ListNode}
 */
var getIntersectionNode = function(headA, headB) {
  var a = headA;
  var b = headB;
  while (a) {
    while (b) {
      if (a == b) {
        return a;
      }
      b = b.next;
    }
    a = a.next;
    b = headB;
  }
  return null;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

哈希法

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */

/**
 * @param {ListNode} headA
 * @param {ListNode} headB
 * @return {ListNode}
 */
var getIntersectionNode = function(headA, headB) {
  let a = headA;
  let b = headB;
  let hash = new Map();
  while (a) {
    hash.set(a, 1);
    a = a.next;
  }
  while (b) {
    if (hash.has(b)) {
      return b;
    }
    b = b.next;
  }
  return null;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

双指针法

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */

/**
 * @param {ListNode} headA
 * @param {ListNode} headB
 * @return {ListNode}
 */
var getIntersectionNode = function(headA, headB) {
  var pA = headA;
  var pB = headB;
  while (pA !== pB) {
    pB = pB ? pB.next : headA;
    pA = pA ? pA.next : headB;
  }
  return pA;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

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

给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} n
 * @return {ListNode}
 */
var removeNthFromEnd = function(head, n) {
  if (!head) {
    return null;
  }
  var _head = head;
  var current = head;
  var l = 1;
  while (current.next) {
    current = current.next;
    l++;
  }
  var len = l - n;
  if (len == 0) {
    var newHead = head.next;
    head.next = null;
    return newHead;
  }
  if (n == 0) {
    return head;
  }
  current = head;
  var pre = null;
  for (var i = 0; i < len; i++) {
    pre = current;
    current = current.next;
  }
  if (current.next) {
    pre.next = current.next;
    current.next = null;
    return head;
  } else {
    pre.next = null;
    current.next = null;
    return head;
  }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

# 206. 反转链表

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var reverseList = function(head) {
  if (!head) {
    return null;
  }
  var p = head;
  while (p.next) {
    var pre = p.next;
    p.next = p.next.next;
    pre.next = head;
    head = pre;
  }
  return head;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 203. 移除链表元素

删除链表中等于给定值 val 的所有节点。

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} val
 * @return {ListNode}
 */
var removeElements = function(head, val) {
  if (!head) {
    return null;
  }
  var p = head;
  while (p && p.next) {
    if (p.next.val === val) {
      var q = p.next;
      p.next = p.next.next;
      q.next = null;
      if (p.next == null) {
        break;
      }
    } else {
      p = p.next;
    }
  }
  if (head.val === val) {
    var _head = head;
    head = head.next;
    _head.next = null;
  }
  return head;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

# 328. 奇偶链表

给定一个单链表,把所有的奇数节点和偶数节点分别排在一起。请注意,这里的奇数节点和偶数节点指的是节点编号的奇偶性,而不是节点的值的奇偶性。

请尝试使用原地算法完成。你的算法的空间复杂度应为 O(1),时间复杂度应为 O(nodes),nodes 为节点总数。

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var oddEvenList = function(head) {
  if (!head) {
    return null;
  }
  if (!head.next) {
    return head;
  }
  var evenHead = head.next;
  var odd = head;
  var even = evenHead;
  head.next = null;
  while (even) {
    var oddNext = even.next;
    if (even.next) {
      even.next = even.next.next;
    }
    if (odd && oddNext) {
      odd.next = oddNext;
      odd = odd.next;
    }
    even = even.next;
  }
  odd.next = evenHead;
  return head;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

# 707. 设计链表

/**
 * Initialize your data structure here.
 */
var Node = function(val) {
  this.val = val;
  this.next = null;
};

var MyLinkedList = function() {
  this.head = new Node(null);
};

/**
 * Get the value of the index-th node in the linked list. If the index is invalid, return -1.
 * @param {number} index
 * @return {number}
 */
MyLinkedList.prototype.get = function(index) {
  if (!this.head) {
    return -1;
  }
  var p = this.head;
  var i = 0;
  while (p && p.next) {
    if (i == index) {
      return p;
    }
    i++;
    p = p.next;
  }
  return -1;
};

/**
 * Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list.
 * @param {number} val
 * @return {void}
 */
MyLinkedList.prototype.addAtHead = function(val) {
  var newList = new Node(val);
  if (!this.head) {
    this.head = newList;
    return;
  }
  newList.next = this.head;
  this.head = newList;
};

/**
 * Append a node of value val to the last element of the linked list.
 * @param {number} val
 * @return {void}
 */
MyLinkedList.prototype.addAtTail = function(val) {
  var newList = new Node(val);
  if (!this.head) {
    this.head = newList;
    return;
  }
  var p = this.head;
  while (p.next) {
    p = p.next;
  }
  p.next = newList;
};

/**
 * Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted.
 * @param {number} index
 * @param {number} val
 * @return {void}
 */
MyLinkedList.prototype.addAtIndex = function(index, val) {
  var newList = new Node(val);
  if (index <= 0) {
    newList.next = this.head;
    this.head = newList;
    console.log("3");
    return this.head;
  }
  var len = 0;
  var p = this.head;
  while (p && p.next) {
    if (len == index) {
      var pNext = p.next;
      p.next = newList;
      newList.next = pNext;
      console.log("5");
      return this.head;
    }
    p = p.next;
    len++;
  }
  console.log("2");
  if (len == index) {
    console.log("1");
    p.next = newList;
    return this.head;
  } else if (len < index) {
    console.log("4");
    return this.head;
  }
};

/**
 * Delete the index-th node in the linked list, if the index is valid.
 * @param {number} index
 * @return {void}
 */
MyLinkedList.prototype.deleteAtIndex = function(index) {};

/**
 * Your MyLinkedList object will be instantiated and called as such:
 * var obj = new MyLinkedList()
 * var param_1 = obj.get(index)
 * obj.addAtHead(val)
 * obj.addAtTail(val)
 * obj.addAtIndex(index,val)
 * obj.deleteAtIndex(index)
 */

var linkedList = new MyLinkedList();
linkedList.addAtHead(1);
linkedList.addAtHead(1);
linkedList.addAtTail(1);
linkedList.addAtIndex(3, 5);
console.log(linkedList);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

# 21. 合并两个有序链表

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} l1
 * @param {ListNode} l2
 * @return {ListNode}
 */
var mergeTwoLists = function(l1, l2) {
  if (!l1 && !l2) {
    return null;
  } else if (!l1 && l2) {
    return l2;
  } else if (l1 && !l2) {
    return l1;
  }
  var head;
  if (l1.val <= l2.val) {
    head = l1;
    l1 = l1.next;
  } else {
    head = l2;
    l2 = l2.next;
  }
  var _head = head;
  while (l1 && l2) {
    if (l1.val <= l2.val) {
      head.next = l1;
      head = head.next;
      l1 = l1.next;
    } else {
      head.next = l2;
      head = head.next;
      l2 = l2.next;
    }
  }
  if (l2) {
    head.next = l2;
  }
  if (l1) {
    head.next = l1;
  }
  return _head;
};

function ListNode(val) {
  this.val = val;
  this.next = null;
}

var l1 = new ListNode(1);
l1.next = new ListNode(2);
l1.next.next = new ListNode(4);
var l2 = new ListNode(1);
l2.next = new ListNode(3);
l2.next.next = new ListNode(4);
mergeTwoLists(l1, l2);
// [1,2,4]
// [1,3,4]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

# 2. 两数相加

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} l1
 * @param {ListNode} l2
 * @return {ListNode}
 */
var addTwoNumbers = function(l1, l2) {
  if (!l1 && !l2) {
    return null;
  }
  var a = 0;
  var num = l1.val + l2.val;
  if (num >= 10) {
    a = 1;
    num = num % 10;
  }
  var head = new ListNode(num);
  var _head = head;
  l1 = l1.next;
  l2 = l2.next;
  if (!l1 && !l2 && a == 1) {
    _head.next = new ListNode(1);
    return _head;
  }
  while (l1 && l2) {
    var l3 = l1.val + l2.val + a;
    a = 0;
    if (l3 >= 10) {
      a = 1;
      l3 = l3 % 10;
    }
    head.next = new ListNode(l3);
    head = head.next;
    l1 = l1.next;
    l2 = l2.next;
  }
  while (l1) {
    l1.val = l1.val + a;
    if (l1.val >= 10) {
      l1.val = l1.val % 10;
    } else {
      a = 0;
    }
    head.next = l1;
    head = head.next;
    l1 = l1.next;
  }
  while (l2) {
    l2.val = l2.val + a;
    if (l2.val >= 10) {
      l2.val = l2.val % 10;
    } else {
      a = 0;
    }
    head.next = l2;
    head = head.next;
    l2 = l2.next;
  }
  if (a == 1) {
    head.next = new ListNode(1);
  }
  return _head;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

# 430. 扁平化多级双向链表

const flatten = (head, next) => {
  let curr = head;
  while (curr && (curr.next || curr.child)) {
    if (curr.child) {
      let res = flatten(curr.child, curr.next);
      let tmp = curr.next;
      curr.next = res;
      curr.child = null;
      curr.next.prev = curr;
      curr = tmp;
    } else {
      curr = curr.next;
    }
  }
  if (next) {
    next.prev = curr;
    curr.next = next;
  }
  return head;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 二叉树

# 144. 二叉树的前序遍历

递归法

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var preorderTraversal = function(root) {
  return root
    ? [root, ...preorderTraversal(root.left), ...preorderTraversal(root.right)]
    : [];
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

迭代法

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var preorderTraversal = function(root) {
  var arr = [];
  var res = [];
  root && arr.push(root);
  while (arr.length > 0) {
    var cur = arr.pop();
    res.push(cur.val);
    cur.right && arr.push(cur.right);
    cur.left && arr.push(cur.left);
  }
  return res;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 94. 二叉树的中序遍历

递归法

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var inorderTraversal = function(root) {
  return root
    ? [...inorderTraversal(root.left), root, ...inorderTraversal(root.right)]
    : [];
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

迭代法

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var inorderTraversal = function(root) {
  var result = [];
  var tmpStack = [];
  var currNode = root;
  while (currNode != null || tmpStack.length != 0) {
    while (currNode != null) {
      tmpStack.push(currNode);
      currNode = currNode.left;
    }
    currNode = tmpStack.pop();
    result.push(currNode.val);
    currNode = currNode.right;
  }
  return result;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 145. 二叉树的后序遍历

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var postorderTraversal = function(root) {
  let res = [],
    stack = [];
  while (root || stack.length) {
    res.unshift(root.val);
    if (root.left) stack.push(root.left);
    if (root.right) stack.push(root.right);
    root = stack.pop();
  }
  return res;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 数组

# 1295. 统计位数为偶数的数字

给你一个整数数组 nums,请你返回其中位数为 偶数 的数字的个数。

/**
 * @param {number[]} nums
 * @return {number}
 */
var findNumbers = function(nums) {
  if (!nums || nums.length === 0) {
    return 0;
  }
  var res = 0;
  for (var i = nums.length - 1; i >= 0; i--) {
    if (nums[i].toString().length % 2 === 0) {
      res++;
    }
  }
  return res;
};

findNumbers([12, 345, 2, 6, 7896]);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# (1266. 访问所有点的最小时间)[https://leetcode-cn.com/problems/minimum-time-visiting-all-points/]

/**
 * @param {number[][]} points
 * @return {number}
 */
var minTimeToVisitAllPoints = function(points) {
  if (!points || points.length === (0 || 1)) {
    return 0;
  }
  var head = new Node(points[0]);
  var cur = head;
  for (var i = 1, len = points.length; i < len; i++) {
    cur.next = new Node(points[i]);
    cur = cur.next;
  }
  cur = head;
  var res = 0;
  while (cur && cur.next) {
    var nextP = cur.next.val;
    var curP = cur.val;
    var x = Math.abs(nextP[0] - curP[0]);
    var y = Math.abs(nextP[1] - curP[1]);
    var time = Math.abs(x - y) + Math.min(x, y);
    res += time;
    cur = cur.next;
  }
  return res;
};

var Node = function(val) {
  this.val = val;
  this.next = null;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# (226. 翻转二叉树)[https://leetcode-cn.com/problems/invert-binary-tree/submissions/]

递归法

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {TreeNode}
 */
var invertTree = function(root) {
  if (!root) {
    return null;
  }
  let left = invertTree(root.left);
  let right = invertTree(root.right);
  root.left = right;
  root.right = left;
  return root;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

迭代法

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {TreeNode}
 */
var invertTree = function(root) {
  if (!root) {
    return null;
  }
  let queue = [];
  queue.push(root);
  while (queue.length > 0) {
    let newRoot = queue.shift();
    [newRoot.left, newRoot.right] = [newRoot.right, newRoot.left];
    if (newRoot.left) {
      queue.push(newRoot.left);
    }
    if (newRoot.right) {
      queue.push(newRoot.right);
    }
  }
  return root;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# (892. 三维形体的表面积)[https://leetcode-cn.com/problems/surface-area-of-3d-shapes/submissions/]

var surfaceArea = function(grid) {
  let sum = 0;
  let len = grid.length;
  for (let i = 0; i < len; i++) {
    let s1 = 0;
    let s2 = 0;
    let s3 = 0;
    for (let k1 = 0; k1 < len - 1; k1++) {
      s1 += Math.min(grid[i][k1], grid[i][k1 + 1]) * 2;
    }
    for (let k2 = 0; k2 < len - 1; k2++) {
      s2 += Math.min(grid[k2][i], grid[k2 + 1][i]) * 2;
    }
    for (let k3 = 0; k3 < len; k3++) {
      sum += grid[i][k3] * 6;
      if (grid[i][k3] > 1) {
        s3 += (grid[i][k3] - 1) * 2;
      }
    }
    sum = sum - s1 - s2 - s3;
  }
  return sum;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 56. 合并区间

/**
 * @param {number[][]} intervals
 * @return {number[][]}
 */
var merge = function(intervals) {
  if (!intervals || intervals.length === 0) {
    return [];
  }
  let input = intervals.sort((a, b) => a[0] - b[0]);
  let res = [];
  res.push(input[0]);
  for (let i = 1, len = input.length; i < len; i++) {
    if (input[i][0] > res[res.length - 1][1]) {
      res.push(input[i]);
    } else if (input[i][1] > res[res.length - 1][1]) {
      res[res.length - 1][1] = input[i][1];
    }
  }
  return res;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 动态规划

# (121. 买卖股票的最佳时机)[https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/submissions/]

暴力法

/**
 * @param {number[]} prices
 * @return {number}
 */
var maxProfit = function(prices) {
  if (!prices || prices.length === 0) {
    return 0;
  }
  var max = 0;
  for (var i = 0, len = prices.length; i < len - 1; i++) {
    for (var j = i + 1; j < len; j++) {
      if (prices[i] < prices[j]) {
        max = Math.max(prices[j] - prices[i], max);
      }
    }
  }
  return max;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
 * @param {number[]} prices
 * @return {number}
 */
var maxProfit = function(prices) {
  if (!prices || prices.length === 0) {
    return 0;
  }
  var min = prices[0];
  var max = 0;
  for (var i = 0, len = prices.length; i < len; i++) {
    if (prices[i] < min) {
      min = prices[i];
    } else if (prices[i] - min > max) {
      max = prices[i] - min;
    }
  }
  return max;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# (122. 买卖股票的最佳时机 II)[https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/]

/**
 * @param {number[]} prices
 * @return {number}
 */
var maxProfit = function(prices) {
  var max = 0;
  for (var i = 1, len = prices.length; i < len; i++) {
    if (prices[i] > prices[i - 1]) {
      max += prices[i] - prices[i - 1];
    }
  }
  return max;
};
1
2
3
4
5
6
7
8
9
10
11
12
13

# 字节跳动

# 70. 爬楼梯

/**
 * @param {number} n
 * @return {number}
 */
var climbStairs = function(n) {
  if (n === 1) {
    return 1;
  }
  let dp = new Array(n);
  dp[0] = 1;
  dp[1] = 2;
  for (let i = 2; i < n; i++) {
    dp[i] = dp[i - 1] + dp[i - 2];
  }
  return dp[n - 1];
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

斐波那契

/**
 * @param {number} n
 * @return {number}
 */
var climbStairs = function(n) {
  const sqrt_5 = Math.sqrt(5);
  const fib_n =
    Math.pow((1 + sqrt_5) / 2, n + 1) - Math.pow((1 - sqrt_5) / 2, n + 1);
  return Math.round(fib_n / sqrt_5);
};
1
2
3
4
5
6
7
8
9
10

# 5. 最长回文子串

动态规划

var longestPalindrome = function(s) {
  let n = s.length;
  let res = "";
  let dp = Array.from(new Array(n), () => new Array(n).fill(0));
  for (let i = n - 1; i >= 0; i--) {
    for (let j = i; j < n; j++) {
      dp[i][j] = s[i] == s[j] && (j - i < 2 || dp[i + 1][j - 1]);
      if (dp[i][j] && j - i + 1 > res.length) {
        res = s.substring(i, j + 1);
      }
    }
  }
  return res;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14

Manacher 算法

var longestPalindrome = function(s) {
  if (!s || s.length < 2) {
    return s;
  }
  var s_f = "#" + s.split("").join("#") + "#";
  let c = 0,
    R = 0;
  var len = s.length;
  var t_len = s_f.length;
  var maxLen = 0;
  var maxIndex = 0;
  var originIndex = 0;
  var p = new Array(t_len);
  p[0] = 0;
  for (var i = 1; i < t_len - 1; i++) {
    var j = 2 * c - i;
    if (i < R) {
      p[i] = Math.min(p[j], R - i);
    } else {
      p[i] = 0;
    }
    var left = i - p[i] - 1;
    var right = i + p[i] + 1;
    while (left >= 0 && right < t_len && s_f[left] == s_f[right]) {
      left--;
      right++;
      p[i]++;
    }
    if (i + p[i] > R) {
      c = i;
      R = i + p[i];
    }
    if (p[i] > maxLen) {
      maxLen = p[i];
      maxIndex = i;
      originIndex = parseInt((i - p[i]) / 2);
    }
  }
  return s.substring(originIndex, originIndex + maxLen);
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

中心拓展法

/**
 * @param {string} s
 * @return {string}
 */
var longestPalindrome = function(s) {
  if (!s || s.length < 2) {
    return s;
  }
  let start = 0,
    end = 0;
  let n = s.length;
  // 中心扩展法
  let centerExpend = (left, right) => {
    while (left >= 0 && right < n && s[left] == s[right]) {
      left--;
      right++;
    }
    return right - left - 1;
  };
  for (let i = 0; i < n; i++) {
    let len1 = centerExpend(i, i);
    let len2 = centerExpend(i, i + 1);
    // 两种组合取最大回文串的长度
    let maxLen = Math.max(len1, len2);
    if (maxLen > end - start) {
      // 更新最大回文串的首尾字符索引
      start = i - ((maxLen - 1) >> 1);
      end = i + (maxLen >> 1);
    }
  }
  return s.substring(start, end + 1);
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# 146. LRU 缓存机制

var LRUCache = class {
  constructor(capacity) {
    this.cache = new Map();
    this.capacity = capacity;
  }

  /**
   * @param {number} key
   * @return {number}
   */
  get(key) {
    let cache = this.cache;
    if (cache.has(key)) {
      let temp = cache.get(key);
      cache.delete(key);
      cache.set(key, temp);
      return temp;
    } else {
      return -1;
    }
  }

  /**
   * @param {number} key
   * @param {number} value
   * @return {void}
   */
  put(key, value) {
    let cache = this.cache;
    if (cache.has(key)) {
      cache.delete(key);
    } else if (cache.size >= this.capacity) {
      cache.delete(cache.keys().next().value);
    }
    cache.set(key, value);
  }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

# 53. 最大子序和

暴力法

/**
 * @param {number[]} nums
 * @return {number}
 */
var maxSubArray = function(nums) {
  if (!nums || nums.length === 0) {
    return null;
  }
  let res = nums[0];
  let len = nums.length;
  let p1 = 0;
  while (p1 < len) {
    res = Math.max(res, nums[p1]);
    let p2 = p1 + 1;
    let _res = nums[p1];
    while (p2 < len) {
      _res += nums[p2];
      res = Math.max(res, _res);
      p2++;
    }
    p1++;
  }
  return res;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

动态规划

/**
 * @param {number[]} nums
 * @return {number}
 */
var maxSubArray = function(nums) {
  let ans = nums[0];
  let sum = 0;
  for (const num of nums) {
    if (sum > 0) {
      sum += num;
    } else {
      sum = num;
    }
    ans = Math.max(ans, sum);
  }
  return ans;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

贪心算法

/**
 * @param {number[]} nums
 * @return {number}
 */
var maxSubArray = function(nums) {
  let n = nums.length;
  let currSum = nums[0],
    maxSum = nums[0];

  for (let i = 1; i < n; ++i) {
    currSum = Math.max(nums[i], currSum + nums[i]);
    maxSum = Math.max(maxSum, currSum);
  }
  return maxSum;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 9. 回文数

无脑法

/**
 * @param {number} x
 * @return {boolean}
 */
var isPalindrome = function(x) {
  if ((!x && x !== 0) || x < 0) {
    return false;
  }
  let s = String(x)
    .split("")
    .reverse()
    .join("");
  return String(x) === s;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
 * @param {number} x
 * @return {boolean}
 */
var isPalindrome = function(x) {
  if ((!x && x !== 0) || x < 0) {
    return false;
  }
  let div = 1;
  while (x / div >= 10) {
    div = div * 10;
  }
  while (x > 0) {
    let left = ~~(x / div);
    let right = x % 10;
    if (left != right) return false;
    x = ~~((x % div) / 10);
    div = div / 100;
  }
  return true;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

双指针法

/**
 * @param {number} x
 * @return {boolean}
 */
var isPalindrome = function(x) {
  if ((!x && x !== 0) || x < 0) {
    return false;
  }
  let s = String(x);
  let left = 0;
  let right = s.length - 1;
  while (left < right) {
    if (s[left] !== s[right]) {
      return false;
    }
    left++;
    right--;
  }
  return true;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 7. 整数反转

/**
 * @param {number} x
 * @return {number}
 */
var reverse = function(x) {
  let a = x < 0 ? -1 : 1;
  let res = Math.abs(x)
    .toString()
    .split("")
    .reverse()
    .join("");
  if (res > 2 ** 31) {
    return 0;
  }
  return a * res;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 101. 对称二叉树

递归法

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {boolean}
 */
var isSymmetric = function(root) {
  return isMirro(root, root);
};

var isMirro = function(left, right) {
  if (left === null && right === null) {
    return true;
  } else if (left === null || right === null) {
    return false;
  }
  return (
    left.val === right.val &&
    isMirro(left.right, right.left) &&
    isMirro(left.left, right.right)
  );
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

迭代法

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {boolean}
 */
var isSymmetric = function(root) {
  let queue = [];
  queue.push(root);
  queue.push(root);
  while (queue.length !== 0) {
    let t1 = queue.shift();
    let t2 = queue.shift();
    if (t1 === null && t2 === null) {
      continue;
    } else if (t1 === null || t2 === null) {
      return false;
    } else if (t1.val !== t2.val) {
      return false;
    }
    queue.push(t1.left);
    queue.push(t2.right);
    queue.push(t1.right);
    queue.push(t2.left);
  }
  return true;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# 104. 二叉树的最大深度

递归法

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var maxDepth = function(root) {
  if (!root) {
    return 0;
  }
  let left = maxDepth(root.left);
  let right = maxDepth(root.right);
  return Math.max(left, right) + 1;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 112. 路径总和

递归法

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @param {number} sum
 * @return {boolean}
 */
var hasPathSum = function(root, sum) {
  if (!root) {
    return false;
  }
  sum -= root.val;
  if (root.left === null && root.right === null) {
    return sum === 0;
  }
  return hasPathSum(root.left, sum) || hasPathSum(root.right, sum);
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 46. 全排列

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var permute = function(nums) {
  let n = nums.length;
  let res = [];
  let tmpPath = [];
  let backtrack = tmpPath => {
    if (tmpPath.length == n) {
      res.push(tmpPath);
      return;
    }
    for (let i = 0; i < n; i++) {
      if (!tmpPath.includes(nums[i])) {
        tmpPath.push(nums[i]);
        backtrack(tmpPath.slice());
        tmpPath.pop();
      }
    }
  };
  backtrack(tmpPath);
  return res;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 31. 下一个排列

var nextPermutation = function(nums) {
  let len = nums.length;
  if (len <= 1) return;

  for (let i = len - 2; i >= 0; i--) {
    if (nums[i] < nums[i + 1]) {
      for (let j = len - 1; j > i; j--) {
        if (nums[i] < nums[j]) {
          swap(i, j, nums);
          break;
        }
      }
      let x = i + 1,
        y = len - 1;
      while (x < y) swap(x++, y--, nums);
      break;
    }
    if (i === 0) {
      let x = i,
        y = len - 1;
      while (x < y) swap(x++, y--, nums);
    }
  }
};

function swap(i, j, nums) {
  let t = nums[i];
  nums[i] = nums[j];
  nums[j] = t;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

# 199. 二叉树的右视图

var rightSideView = function(root) {
  // 声明arr,保存层序遍历结果, 声明res,保存该函数返回结果
  let arr = [],
    res = [];

  bst(root, 0);
  // 层序遍历二叉树,形参i的值是当前树的深度
  function bst(tree, i) {
    if (!tree) {
      // 如果该节点为null的时候,将null也保存起来
      arr[i] = arr[i] || [];
      arr[i].push(null);
      return;
    }

    arr[i] = arr[i] || [];
    arr[i].push(tree.val);

    bst(tree.left, i + 1);
    bst(tree.right, i + 1);
  }

  // 当前的arr的形式是:
  // [[1], [2, 3], [null, 5, null, 4], [null, null, null, null]]
  // for循环从0 到 length - 1遍历
  for (let k = 0; k < arr.length - 1; k++) {
    for (let i = arr[k].length - 1; i >= 0; i--) {
      // 从右到左遇到truly的元素添加到res数组中
      if (arr[k][i]) {
        res.push(arr[k][i]);
        break;
      }
    }
  }

  return res;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

# 103. 二叉树的锯齿形层次遍历

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var zigzagLevelOrder = function(root) {
  let res = [];
  bst(root, 0);
  function bst(tree, level) {
    if (!tree) {
      return;
    }
    res[level] = res[level] || [];
    if (level % 2 === 1) {
      res[level].push(tree.val);
      bst(tree.right, level + 1);
      bst(tree.left, level + 1);
    } else {
      res[level].unshift(tree.val);
      bst(tree.right, level + 1);
      bst(tree.left, level + 1);
    }
  }
  return res;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 8. 字符串转换整数 (atoi)

/**
 * @param {string} str
 * @return {number}
 */
var myAtoi = function(str) {
  let reg = /^(-|\+)?\d+/g;
  let res = str.trim().match(reg);
  return res ? Math.max(Math.min(res, 2 ** 31 - 1), -1 * 2 ** 31) : 0;
};
1
2
3
4
5
6
7
8
9

# 22. 括号生成

var generateParenthesis = function(n) {
  let res = [];
  function h(ps, l, r) {
    if (l == n && r == n) {
      res.push(ps);
      return;
    }
    if (l < n) {
      h(ps + "(", l + 1, r);
    }
    if (l > r) {
      h(ps + ")", l, r + 1);
    }
  }
  h("", 0, 0);
  return res;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 143. 重排链表

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @return {void} Do not return anything, modify head in-place instead.
 */
var reorderList = function(head) {
  if (!head) {
    return null;
  }
  let p = head;
  let len = 1;
  while (p.next) {
    p = p.next;
    len++;
  }
  p = head;
  let sec = null;
  for (let i = 0; i < Math.ceil(len / 2) - 1; i++) {
    p = p.next;
  }
  sec = p.next;
  p.next = null;
  p = sec;
  while (p && p.next) {
    let _next = p.next;
    p.next = p.next.next;
    _next.next = sec;
    sec = _next;
  }
  p = head;
  while (p.next && sec.next) {
    let _next = p.next;
    p.next = sec;
    let _sec = sec.next;
    sec.next = _next;
    sec = _sec;
    p = _next;
  }
  if (p.next) {
    let _next = p.next;
    p.next = sec;
    p.next.next = _next;
  } else {
    p.next = sec;
  }

  return head;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

# 79. 单词搜索

/**
 * @param {character[][]} board
 * @param {string} word
 * @return {boolean}
 */
var exist = function(board, word) {
  const bLen = board.length;
  const aLen = board[0].length;
  let isExist = false;
  // 存储当前所选字母在平面内上下左右四个方向字母
  const d = [[-1, 0], [0, 1], [1, 0], [0, -1]];
  // 维护递归过程中,平面中字母的使用状态,每个只能使用一次
  const used = [];
  // 判断所选字母是否在二维平面内
  const inArea = function(x, y) {
    return x >= 0 && x < board.length && y >= 0 && y < board[0].length;
  };
  // 递归函数,判断board[i][j]开始移动,是否可以找到word
  const _exist = function(board, i, j, word) {
    const wLen = word.length;
    if (wLen === 1 && board[i][j] === word[0]) {
      isExist = true;
    }
    if (board[i][j] === word[0]) {
      const newWord = word.substring(1);
      used[i][j] = true;
      for (let k = 0; k < 4; k++) {
        const newX = i + d[k][0];
        const newY = j + d[k][1];
        inArea(newX, newY) &&
          !used[newX][newY] &&
          _exist(board, newX, newY, newWord);
        if (isExist) {
          return true;
        }
      }
      used[i][j] = false;
    }
  };
  if (bLen) {
    for (let i = 0; i < bLen; i++) {
      used[i] = new Array(aLen).fill(false);
    }
    for (let i = 0; i < bLen; i++) {
      for (let j = 0; j < aLen; j++) {
        _exist(board, i, j, word);
      }
    }
  }
  return isExist;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

# 445. 两数相加 II

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} l1
 * @param {ListNode} l2
 * @return {ListNode}
 */
var addTwoNumbers = function(l1, l2) {
  const revers = function(list) {
    if (!list) {
      return null;
    }
    let head = list;
    while (list && list.next) {
      let _next = list.next;
      list.next = list.next.next;
      _next.next = head;
      head = _next;
    }
    return head;
  };
  const add = function(node1, node2) {
    let flag = 0;
    let _val = 0;
    if (node1 + node2 > 9) {
      flag = 1;
      _val = node1 + node2 - 10;
    } else {
      _val = node1 - 0 + node2;
    }
    return {
      flag,
      _val
    };
  };

  let _l1 = revers(l1);
  let _l2 = revers(l2);
  let res = new ListNode(0);
  let head = res;
  let _flag = 0;
  while (_l1 && _l2) {
    const middle = add(_l1.val, _l2.val);
    let _val = _flag === 1 ? middle._val + 1 : middle._val;
    _flag = middle.flag;
    if (_val > 9) {
      _flag = 1;
      _val = _val - 10;
    }
    res.next = new ListNode(_val);
    res = res.next;
    _l1 = _l1.next;
    _l2 = _l2.next;
  }
  if (_l1) {
    while (_l1) {
      let middle = add(_l1.val, _flag);
      _flag = middle.flag;
      res.next = new ListNode(middle._val);
      _l1 = _l1.next;
      res = res.next;
    }
  } else if (_l2) {
    while (_l2) {
      let middle = add(_l2.val, _flag);
      _flag = middle.flag;
      res.next = new ListNode(middle._val);
      _l2 = _l2.next;
      res = res.next;
    }
  }
  if (_flag === 1) {
    res.next = new ListNode(1);
  }
  let _res = head.next;
  head.next = null;
  return revers(_res);
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

# 35. 搜索插入位置

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var searchInsert = function(nums, target) {
  if (!nums) {
    return null;
  }
  for (let i = 0, len = nums.length; i < len; i++) {
    if (nums[i] >= target) {
      return i;
    }
  }
  return nums.length;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 92. 反转链表 II

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} m
 * @param {number} n
 * @return {ListNode}
 */
var reverseBetween = function(head, m, n) {
  let dummy = new ListNode(0);
  dummy.next = head;
  let tmpHead = dummy;
  // 找到第m-1个链表节点
  for (let i = 0; i < m - 1; i++) {
    tmpHead = tmpHead.next;
  }
  // 206题解法一
  let prev = null;
  let curr = tmpHead.next;
  for (let i = 0; i <= n - m; i++) {
    let next = curr.next;
    curr.next = prev;
    prev = curr;
    curr = next;
  }
  // 将翻转的部分链表 和 原链表拼接
  tmpHead.next.next = curr;
  tmpHead.next = prev;
  return dummy.next;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

# 91. 解码方法

var numDecodings = function(s) {
  if (s == null || s.length == 0) {
    return 0;
  }
  const dp = Array(s.length + 1).fill(0);
  dp[0] = 1;
  dp[1] = s[0] !== "0" ? 1 : 0;
  for (let i = 2; i < s.length + 1; i++) {
    const one = +s.slice(i - 1, i);
    const two = +s.slice(i - 2, i);

    if (two >= 10 && two <= 26) {
      dp[i] = dp[i - 2];
    }

    if (one >= 1 && one <= 9) {
      dp[i] += dp[i - 1];
    }
  }

  return dp[dp.length - 1];
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 4. 寻找两个有序数组的中位数

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number}
 */
var findMedianSortedArrays = function(nums1, nums2) {
  let nums = nums1.concat(nums2);
  nums.sort((a, b) => a - b);
  const len = nums.length;
  let res;
  if (len % 2 === 0) {
    res = (nums[len / 2] + nums[len / 2 - 1]) / 2;
  } else {
    res = nums[(len - 1) / 2];
  }
  return res;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

二分法

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number}
 */
var findMedianSortedArrays = function(nums1, nums2) {
  if (nums1.length > nums2.length) [nums1, nums2] = [nums2, nums1];

  const length1 = nums1.length;
  const length2 = nums2.length;
  let min = 0;
  let max = length1;
  let half = Math.floor((length1 + length2 + 1) / 2);
  while (max >= min) {
    const i = Math.floor((max + min) / 2);
    const j = half - i;
    if (i > min && nums1[i - 1] > nums2[j]) {
      max = i - 1;
    } else if (i < max && nums1[i] < nums2[j - 1]) {
      min = i + 1;
    } else {
      let left, right;
      if (i === 0) left = nums2[j - 1];
      else if (j === 0) left = nums1[i - 1];
      else left = Math.max(nums1[i - 1], nums2[j - 1]);

      if (i === length1) right = nums2[j];
      else if (j === length2) right = nums1[i];
      else right = Math.min(nums1[i], nums2[j]);

      return (length1 + length2) % 2 ? left : (left + right) / 2;
    }
  }
  return 0;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

# 62. 不同路径

/**
 * @param {number} m
 * @param {number} n
 * @return {number}
 */
var uniquePaths = function(m, n) {
  var cur = new Array(n).fill(1);
  for (var i = 1; i < m; i++) {
    for (var r = 1; r < n; r++) {
      cur[r] = cur[r - 1] + cur[r];
    }
  }
  return cur[n - 1];
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 148. 排序链表

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var sortList = function(head) {
  if (!head) {
    return null;
  }
  let temp = [];
  while (head) {
    temp.push(head.val);
    head = head.next;
  }
  temp.sort((a, b) => a - b);
  let res = new ListNode(temp[0]);
  let _head = res;
  for (let i = 1, len = temp.length; i < len; i++) {
    _head.next = new ListNode(temp[i]);
    _head = _head.next;
  }
  return res;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
var sortList = function(head) {
  let mergeList = (left, right) => {
    let res = new ListNode(0);
    let pre = res;
    while (left && right) {
      if (left.val <= right.val) {
        pre.next = left;
        left = left.next;
      } else {
        pre.next = right;
        right = right.next;
      }
      pre = pre.next;
    }
    pre.next = left ? left : right;
    return res.next;
  };
  let mergeSort = node => {
    if (!node || !node.next) return node;
    let mid = node;
    let fast = node.next;
    while (fast && fast.next) {
      mid = mid.next;
      fast = fast.next.next;
    }
    let rightList = mid.next;
    mid.next = null;
    let left = node;
    let right = rightList;
    return mergeList(mergeSort(left), mergeSort(right));
  };
  return mergeSort(head);
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

# 55. 跳跃游戏

/**
 * @param {number[]} nums
 * @return {boolean}
 */
var canJump = function(nums) {
  if (!nums || nums.length === 0) {
    return false;
  }
  let position = nums.length - 1;
  for (let i = nums.length - 1; i >= 0; i--) {
    if (i + nums[i] >= position) {
      position = i;
    }
  }
  return position === 0;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

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

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var swapPairs = function(head) {
  if (!head) {
    return null;
  }
  let _head = new ListNode(0);
  _head.next = head;
  let pre = _head;
  while (head && head.next) {
    let _next = head.next;
    head.next = head.next.next;
    pre.next = _next;
    _next.next = head;
    pre = head;
    head = head.next;
  }
  return _head.next;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 300. 最长上升子序列

/**
 * @param {number[]} nums
 * @return {number}
 */
var lengthOfLIS = function(nums) {
  if (!nums || nums.length === 0) {
    return null;
  }
  let dp = new Array(nums.length);
  dp[0] = 1;
  let maxnas = 1;
  for (let i = 0, len = nums.length; i < len; i++) {
    let maxval = 0;
    for (let j = 0; j < i; j++) {
      if (nums[i] > nums[j]) {
        maxval = Math.max(maxval, dp[j]);
      }
    }
    dp[i] = maxval + 1;
    maxnas = Math.max(maxnas, dp[i]);
  }
  return maxnas;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 129. 求根到叶子节点数字之和

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var sumNumbers = function(root) {
  var res = 0;
  var getPathSum = (node, str) => {
    if (!node) {
      return;
    }
    str += node.val;
    if (!node.left && !node.right) {
      res += Number(str);
      return;
    }
    getPathSum(node.left, str);
    getPathSum(node.right, str);
  };
  getPathSum(root, "");
  return res;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 25. K 个一组翻转链表

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} k
 * @return {ListNode}
 */
var reverseKGroup = function(head, k) {
  if (!head) {
    return null;
  }
  let len = 1;
  let p = head;
  while (p && p.next) {
    len++;
    p = p.next;
  }
  let temp = Math.floor(len / k);
  let res = new ListNode(null);
  res.next = head;
  let pre = res;
  let num = 0;
  while (num !== temp) {
    let _head = head;
    for (let i = 0; i < k - 1; i++) {
      let _next = head.next;
      head.next = head.next.next;
      _next.next = _head;
      _head = _next;
    }
    pre.next = _head;
    pre = head;
    head = head.next;
    num++;
  }
  return res.next;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

# 回溯算法

# 39. 组合总和

/**
 * @param {number[]} candidates
 * @param {number} target
 * @return {number[][]}
 */
var combinationSum = function(candidates, target) {
  const n = candidates.length;
  let res = [];
  let temp = [];
  candidates.sort((a, b) => a - b);
  const backtrack = function(tempPath, target, start) {
    if (target === 0) {
      res.push(tempPath);
      return;
    }
    for (let i = start; i < n; i++) {
      if (target < candidates[i]) break;
      tempPath.push(candidates[i]);
      backtrack(tempPath.slice(), target - candidates[i], i);
      tempPath.pop();
    }
  };
  backtrack(temp, target, 0);
  return res;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 784. 字母大小写全排列

/**
 * @param {string} S
 * @return {string[]}
 */
var letterCasePermutation = function(S) {
  let ans = [],
    letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

  function backtrack(str, i) {
    if (i >= S.length) {
      ans.push(str);
      return;
    }

    let curr = S[i];
    if (letters.indexOf(curr) > -1) {
      let low = str + curr.toLowerCase(),
        high = str + curr.toUpperCase();
      backtrack(low, i + 1);
      backtrack(high, i + 1);
    } else {
      backtrack(str + curr, i + 1);
    }
  }
  backtrack("", 0);

  return ans;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 1215. 步进数

/**
 * @param {number} low
 * @param {number} high
 * @return {number[]}
 */
var countSteppingNumbers = function(low, high) {
  let res = [];
  if (low === 0) {
    res.push(0);
  }
  const dsp = function(result, curr) {
    if (curr >= low && curr <= high) {
      result.push(curr);
    }
    if (curr > high / 10) {
      return;
    }
    let r = curr % 10;
    if (r != 9 && curr * 10 + r + 1 <= high) {
      dsp(result, curr * 10 + r + 1);
    }
    if (r != 0 && curr * 10 + r - 1 <= high) {
      dsp(result, curr * 10 + r - 1);
    }
  };
  for (let i = 1; i <= 9; i++) {
    dsp(res, i);
  }
  res.sort((a, b) => a - b);
  return res;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
更新时间: 11/8/2019, 4:51:43 PM