1
头图

One, and the problem

2020.09.21

No.1 The sum of two numbers

Given an integer array nums and a target value target, please find the two integers whose sum is the target value in the array and return their array subscripts.

You can assume that each input will only correspond to one answer. However, the same element in the array cannot be used twice.

 

Example:

Given nums = [2, 7, 11, 15], target = 9

Because nums[0] + nums[1] = 2 + 7 = 9
So return [0, 1]

Source: LeetCode
Link: https://leetcode-cn.com/problems/two-sum
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=1 lang=javascript
 *
 * [1] 两数之和
 */

// @lc code=start
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
    let p1 = 0;  
    while(p1<nums.length) {
        let p2 = nums.length - 1;
        while(p2>0) {
            if(nums[p1] + nums[p2] == target && p1 != p2) {
                return [p1,p2];
            } 
            p2--;
        }
        p1++;
    }
};
Option II:
/*
 * @lc app=leetcode.cn id=1 lang=javascript
 *
 * [1] 两数之和
 */

// @lc code=start
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
    let i = nums.length;
    while(i > 1) {
        let last = nums.pop();
        if (nums.indexOf(target - last) > -1) {
            return [nums.indexOf(target - last), nums.length]
        }
        i--
    }
};
third solution:
/*
 * @lc app=leetcode.cn id=1 lang=javascript
 *
 * [1] 两数之和
 */

// @lc code=start
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
  const map = new Map()
  for (let i = 0; i < nums.length; i ++) {
    const otherIndex = map.get(target - nums[i])
    if (otherIndex !== undefined) return [otherIndex, i]
    map.set(nums[i], i)
  }
};

The conventional idea of finding the sum of two numbers is to add and sum one by one to obtain whether the sum satisfies the conditions. Option 1: Explosive solution; Option 2: Use stack structure to optimize access; Option 3: Construct a hash table for access optimize


2020.09.22

No.15 The sum of three numbers

Given an array nums containing n integers, determine whether there are three elements a, b, c in nums, such that a + b + c = 0? Please find all the triples that meet the conditions and are not repeated.

Note: The answer cannot contain repeated triples.

 

Example:

Given the array nums = [-1, 0, 1, 2, -1, -4],

The set of triples that meet the requirements are:
[
 [-1, 0, 1],
 [-1, -1, 2]
]

Source: LeetCode
Link: https://leetcode-cn.com/problems/3sum
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=15 lang=javascript
 *
 * [15] 三数之和
 */

// @lc code=start
/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var threeSum = function(nums) {
    let r = [];
    // 从小到大排序
    nums.sort((a,b) => a-b);

    if(nums[0] > 0 || nums[nums.length-1] < 0 || nums.length < 3) {
        return [];
    } else {
        for(let i=0;i<nums.length;i++) {
            let pos = nums[i],
                left = i + 1,
                right = nums.length - 1;
            // 过滤到当前项和前一项相同的循环
            if(pos == nums[i-1] && i>0) continue;
            while(left < right) {
                let a = nums[left],
                    b = nums[right];
                if(pos + a + b == 0) {
                    r.push([pos,a,b]);
                    // 跳过中间重复的元素
                    while(left < right && nums[left]==a) left++;
                    while(left < right && nums[right]==b) right--;
                } else if(pos + a + b < 0) {
                    left++;
                } else {
                    right--;
                }
            }
        }
        return r;
    }
};
Option II:
/*
 * @lc app=leetcode.cn id=15 lang=javascript
 *
 * [15] 三数之和
 */

// @lc code=start
/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var threeSum = function(nums) {
  let arr = []
  if(nums == null || nums.length < 3) return arr;
  nums.sort((a, b) => a - b)
  for(var i =0; i<nums.length-2; i++){
    const hashMap = new Map()
    if(nums[i] > 0) break;
    // 去重处理
    if(i > 0 && nums[i] == nums[i-1]) continue
    for(var j =i+1; j<nums.length; j++){
      const dif = -(nums[i]+nums[j])
      // 去重处理
      // 因为hashMap是首次记录第二次才会push到数组,所以需要判断只有三次重复才能continue
      if(j>i+2 && nums[j]==nums[j-1] && nums[j]==nums[j-2])
        continue
      if(hashMap.has(dif)){
        arr.push([nums[i],nums[hashMap.get(dif)],nums[j]])
        hashMap.delete(dif)
      }
      hashMap.set(nums[j],j)
    }
  }
  return arr
};

There are two ideas for this question: 1. Use the quick sorting idea for reference, fix the pivot, and use the left and right pointers to traverse; 2. Convert the traditional form of a hash table to optimize efficiency, which is an extension of the sum of two numbers.


2020.09.23

No.16 The closest three-digit sum

Given an array of n integers nums and a target value target. Find the three integers in nums so that their sum is closest to target. Returns the sum of these three numbers. Assume that there is only a single answer for each set of inputs.

 

Example:

Input: nums = [-1,2,1,-4], target = 1
Output: 2
Explanation: The closest sum to target is 2 (-1 + 2 + 1 = 2).
 

hint:

3 <= nums.length <= 10^3
-10^3 <= nums[i] <= 10^3
-10^4 <= target <= 10^4

Source: LeetCode
Link: https://leetcode-cn.com/problems/3sum-closest
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Program:
/*
 * @lc app=leetcode.cn id=16 lang=javascript
 *
 * [16] 最接近的三数之和
 */

const { lexicographicSortSchema } = require("graphql");

// @lc code=start
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var threeSumClosest = function(nums, target) {
    // 从小到大排序
    nums.sort((a,b) => a-b);

    if(nums.length>=3) {
        let pivot = 0,
            sum = 0,
            // r = [],
            r = nums[0] + nums[1] + nums[2];

        for(;pivot<nums.length-2;pivot++) {
            let left = pivot + 1,
                right = nums.length - 1;
            while(left < right) {
                sum = nums[pivot] + nums[left] + nums[right];
                // 可以收到一个对象数组里,后续进行排序
                // r.push({
                //     value: sum,
                //     gap: Math.abs(sum-target)
                // })
                if(Math.abs(sum-target)<Math.abs(r-target)) r = sum;

                if(sum == target){
                    return sum;
                } else if (sum < target) {
                    left++;
                } else if (sum > target) {
                    right--;
                }
            }
            
        }
        // return r.sort((a,b) => a.gap-b.gap)[0].value;
        return r;
    }
};

It’s still an extended application of fast sorting, a deformation of the sum of three numbers.


2020.09.24

No.18 Sum of Four Numbers

Given an array nums containing n integers and a target value target, judge whether there are four elements a, b, c, and d in nums so that the value of a + b + c + d is equal to target? Find all four-tuples that meet the conditions and are not repeated.

Notice:

The answer cannot contain repeated quadruples.

Example:

Given the array nums = [1, 0, -1, 0, -2, 2], and target = 0.

The four-tuple set that meets the requirements is:
[
 [-1,  0, 0, 1],
 [-2, -1, 1, 2],
 [-2,  0, 0, 2]
]

Source: LeetCode
Link: https://leetcode-cn.com/problems/4sum
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=18 lang=javascript
 *
 * [18] 四数之和
 */

// @lc code=start
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[][]}
 */
var fourSum = function(nums, target) {
    // 排序
    nums.sort((a,b) => a-b);

    let r = [];
    
    for(let i = 0; i < nums.length-3;i++ ) {
        // 除去重复情况
        if(i>0 && nums[i-1] == nums[i]) continue;

        for(let j = i+1; j< nums.length - 2; j++ ) {
            // 除去重复情况
            if(j>i+1 && nums[j-1] == nums[j]) continue;
            
            let left = j + 1,
                right = nums.length - 1;
            while(left < right) {
                let a = nums[left],
                    b = nums[right];
                if (a+b+nums[i]+nums[j] < target) {
                    left++;
                } else if (a+b+nums[i]+nums[j] > target) {
                    right--;
                } else {
                    r.push([ nums[i], nums[j], nums[left], nums[right] ]);
                    while(left < right && nums[left] == a) {
                        left++
                    };
                    while(left < right && nums[right] == b) {
                        right--;
                    };
                }
            };
        }
    }
    return r;
};
Option II:
/*
 * @lc app=leetcode.cn id=18 lang=javascript
 *
 * [18] 四数之和
 */

// @lc code=start
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[][]}
 */
var fourSum = function (nums, target) {
  let len = nums.length;
  if (len < 4) return [];
  let ans = [];
  for (let i = 0; i < len - 2; i++) {
    for (let j = i + 1; j < len - 1; j++) {
      let map = {};
      for (let x = j + 1; x < len; x++) {
        let key = target - nums[i] - nums[j] - nums[x];
        if (map[nums[x]]) {
          let temp = [nums[x], ...map[nums[x]]].sort((a, b) => a - b)
          if (removeDup(ans, temp)) {
            ans.push(temp);
          }
        } else {
          map[key] = [nums[i], nums[j], nums[x]]
        }
      }
    }
  }
  return ans;
}

An enhanced version of the sum of three numbers, with an extra layer of loop


2020.09.25

No. 39 Combination Sum

Given an array candidates with no duplicate elements and a target number target, find out all combinations of candidates that can make the number sum target.

The numbers in candidates can be repeatedly selected without limitation.

instruction:

All numbers (including target) are positive integers.
The solution set cannot contain repeated combinations.
Example 1:

Input: candidates = [2,3,6,7], target = 7,
The solved set is:
[
 [7],
 [2,2,3]
]
Example 2:

Input: candidates = [2,3,5], target = 8,
The solved set is:
[
 [2,2,2,2],
 [2,3,3],
 [3,5]
]
 

hint:

1 <= candidates.length <= 30
1 <= candidates[i] <= 200
Each element in the candidate is unique.
1 <= target <= 500

Source: LeetCode
Link: https://leetcode-cn.com/problems/combination-sum
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Program:
/*
 * @lc app=leetcode.cn id=39 lang=javascript
 *
 * [39] 组合总和
 */

// @lc code=start
/**
 * @param {number[]} candidates
 * @param {number} target
 * @return {number[][]}
 */
var combinationSum = function(candidates, target) {
    // 对数组排序
    candidates.sort((a,b) => a-b);
    // 简化无效元素
    candidates.splice(targetIdx(candidates,target));

    let r = [];

    // 递归
    function targetDfs(temp ,sum) {
        // 剪枝 
        if(sum > target) {
            return;
        } else if (sum == target) {
            r.push(temp.concat())
        }

        for(let i= 0;i<candidates.length;i++) {
            // 最后一位锚点
            const p = temp[temp.length-1] || 0;
            // 如果比最后一位小则仍在这一层树中遍历,如果比最后一位大,则需要向下一层查找,知道终止回溯
            if(candidates[i] >= p) {
                temp.push(candidates[i]);
                targetDfs(temp, sum + candidates[i]);
                temp.pop()
            }
        }r
    }

    targetDfs([],0);

    return r;
    

    function targetIdx(candidates, target) {
        let index = 0;
        for(let i=0;i<candidates.length;i++) {
            if(candidates[i] > target) {
                return i;
            } else {
                index = i;
            }
        }
        return index + 1;
    }
};

The idea is more consistent, backtracking, dfs depth-first traversal search, you need to prune at the right position, and use an array to implement the tree structure


2020.09.27

No.40 Combination Sum-ii

Given an array of candidates and a target number target, find out all combinations of candidates that can make the number sum target.

Each number in candidates can only be used once in each combination.

instruction:

All numbers (including the target number) are positive integers.
The solution set cannot contain repeated combinations.
Example 1:

Input: candidates = [10,1,2,7,6,1,5], target = 8,
The solution set is:
[
 [1, 7],
 [1, 2, 5],
 [2, 6],
 [1, 1, 6]
]
Example 2:

Input: candidates = [2,5,2,1,2], target = 5,
The solution set is:
[
 [1,2,2],
 [5]
]

Source: LeetCode
Link: https://leetcode-cn.com/problems/combination-sum-ii
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=40 lang=javascript
 *
 * [40] 组合总和 II
 */

// @lc code=start
/**
 * @param {number[]} candidates
 * @param {number} target
 * @return {number[][]}
 */
var combinationSum2 = function(candidates, target) {
    // 对数组从小到大排序
    candidates.sort((a,b) => a-b);
    // 简化数组
    candidates.splice(targetIdx(candidates, target));

    console.log(candidates);

    let r = [];

    function targetDfs(start,temp,sum) {
        if(sum > target) {
            return;
        } else if(sum == target) {
            r.push(temp.concat());
        }

        for(let i = start;i<candidates.length;i++) {
            if(candidates[i] == candidates[i-1] && i-1>=start) continue;
            temp.push(candidates[i]);
            targetDfs(i+1,temp,sum+candidates[i]);
            temp.pop();
        }
    };

    targetDfs(0, [], 0);

    return r;

    function targetIdx(candidates, target) {
        let index = 0;
        for(let i=0; i< candidates.length; i++) {
            if(candidates[i] > target) {
                return i;
            } else {
                index = i;
            }
        }
        return index+1;
    }
};
Option II:
/*
 * @lc app=leetcode.cn id=40 lang=javascript
 *
 * [40] 组合总和 II
 */

// @lc code=start
/**
 * @param {number[]} candidates
 * @param {number} target
 * @return {number[][]}
 */
var combinationSum2 = function (candidates, target) {
  var dp = []
  //先排序解决顺序问题 例 (1,2)(2,1)
  candidates.sort((a, b) => a - b)
  for (let i = 0; i <= target; i++) {
    dp[i] = new Set()
  }
  dp[0].add('')
  for (let c of candidates) {
    for (let i = target; i >= c; i--) {
      for (item of dp[i - c]) {
        //使用Set去重, 子项要转化成 String
        dp[i].add(item + ',' + c)
      }
    }
  }
  //最后把Set 转成 Array 
  return Array.from(dp[target]).map(item => item.slice(1).split(','))
};

The first idea is similar to the previous one. There needs to be a previous location record, and the same element cannot be recursively repeated; the second idea is to use dynamic programming.


2020.09.28

No.53 Maximum Subsequence Sum

Given an integer array nums, find a continuous sub-array with the largest sum (the sub-array contains at least one element), and return its largest sum.

Example:

Input: [-2,1,-3,4,-1,2,1,-5,4]
Output: 6
Explanation: The sum of consecutive sub-arrays [4,-1,2,1] is the largest, which is 6.
Advanced:

If you have implemented a solution with O(n) complexity, try to use a more subtle divide-and-conquer solution.

Source: LeetCode
Link: https://leetcode-cn.com/problems/maximum-subarray
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=53 lang=javascript
 *
 * [53] 最大子序和
 */

// @lc code=start
/**
 * @param {number[]} nums
 * @return {number}
 */
var maxSubArray = function(nums) {
    let max = nums[0], 
        cache = 0;
    for(let i=0; i< nums.length; i++) {
        cache = Math.max(cache+nums[i],nums[i]);
        max = Math.max(cache,max);
    }
    return max;
};
Option II:
/*
 * @lc app=leetcode.cn id=53 lang=javascript
 *
 * [53] 最大子序和
 */

// @lc code=start
/**
 * @param {number[]} nums
 * @return {number}
 */
function Status(l, r, m, i) {
    this.lSum = l;
    this.rSum = r;
    this.mSum = m;
    this.iSum = i;
}

const pushUp = (l, r) => {
    const iSum = l.iSum + r.iSum;
    const lSum = Math.max(l.lSum, l.iSum + r.lSum);
    const rSum = Math.max(r.rSum, r.iSum + l.rSum);
    const mSum = Math.max(Math.max(l.mSum, r.mSum), l.rSum + r.lSum);
    return new Status(lSum, rSum, mSum, iSum);
}

const getInfo = (a, l, r) => {
    if (l === r) {
        return new Status(a[l], a[l], a[l], a[l]);
    }
    const m = (l + r) >> 1;
    const lSub = getInfo(a, l, m);
    const rSub = getInfo(a, m + 1, r);
    return pushUp(lSub, rSub);
}

var maxSubArray = function(nums) {
    return getInfo(nums, 0, nums.length - 1).mSum;
};

The first idea is to use dynamic programming, the key is to find the recurrence formula, that is, the cycle invariant, this question is f(n)=max{f(n-1)+ai,ai}; the second idea is to use divide and conquer to divide the array into Two paragraphs, as long as the largest of each paragraph is the largest, when it reaches the last one, it will be rolled back, and the final sum is the maximum


2020.09.29

No. 64 minimum path sum

Given an m x n grid containing non-negative integers, find a path from the upper left corner to the lower right corner so that the sum of the numbers on the path is the smallest.

Note: You can only move one step down or right at a time.

Example:

enter:
[
 [1,3,1],
 [1,5,1],
 [4,2,1]
]
Output: 7
Explanation: Because the total of the path 1→3→1→1→1 is the smallest.

Source: LeetCode
Link: https://leetcode-cn.com/problems/minimum-path-sum
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Program:
/*
 * @lc app=leetcode.cn id=64 lang=javascript
 *
 * [64] 最小路径和
 */

// @lc code=start
/**
 * @param {number[][]} grid
 * @return {number}
 */
var minPathSum = function(grid) {
    for (let i = 0; i < grid.length; i++) {
        for (let j = 0; j < grid[i].length; j++) {
            if (i == 0 && j == 0) {
                // 入口不做处理
                grid[i][j] = grid[i][j];
            } else if (i == 0 && j > 0) {
                // 第一行元素
                grid[i][j] += grid[i][j - 1];
            } else if (i > 0 && j === 0) {
                // 第一列元素
                grid[i][j] += grid[i - 1][j];
            } else {
                // 递推公式 grid[i][j] = min{grid[i][j-1], grid[i-1][j]}
                grid[i][j] += Math.min(grid[i - 1][j], grid[i][j - 1]);
            }
        }
    }
    return grid[grid.length - 1][grid[0].length - 1];
};

In classic dynamic programming, the recursive loop invariant is gridi = min{ gridi, gridi-1 }, and attention should be paid to the detailed processing of the boundary


2020.09.30

No.167 Sum of Two Numbers II-Input an ordered array

Given an ordered array that has been arranged in ascending order, find two numbers so that their sum is equal to the target number.

The function should return these two subscript values index1 and index2, where index1 must be less than index2.

instruction:

The returned subscript values (index1 and index2) are not zero-based.
You can assume that each input only corresponds to a unique answer, and you cannot reuse the same elements.
Example:

Input: numbers = [2, 7, 11, 15], target = 9
Output: [1,2]
Explanation: The sum of 2 and 7 is equal to the target number 9. Therefore index1 = 1, index2 = 2.

Source: LeetCode
Link: https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=167 lang=javascript
 *
 * [167] 两数之和 II - 输入有序数组
 */

// @lc code=start
/**
 * @param {number[]} numbers
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(numbers, target) {
    let p1 = 0,
        p2 = numbers.length -1;
    while(p1<p2) {
        if(numbers[p1]+numbers[p2]<target) {
            p1++;
        } else if(numbers[p1]+numbers[p2]>target) {
            p2--;
        } else {
            return [p1+1,p2+1]
        }
    }
};
Option II:
/*
 * @lc app=leetcode.cn id=167 lang=javascript
 *
 * [167] 两数之和 II - 输入有序数组
 */

// @lc code=start
/**
 * @param {number[]} numbers
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(numbers, target) {
    let map = {}
    for(let i = 0; i < numbers.length; i ++) {
        const dim = target - numbers[i]
        if(map[dim] === undefined) {
            map[numbers[i]] = i
        }else {
            return [map[dim] + 1,i + 1]
        }
    }
};
third solution:
/*
 * @lc app=leetcode.cn id=167 lang=javascript
 *
 * [167] 两数之和 II - 输入有序数组
 */

// @lc code=start
/**
 * @param {number[]} numbers
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function (numbers, target) {
  let len = numbers.length,
    left = 0,
    right = len - 1,
    mid = 0
  for (let i = 0; i < len; ++i) {
    left = i + 1
    while (left <= right) {
      mid = parseInt((right - left) / 2) + left
      if (numbers[mid] == target - numbers[i]) {
        return [i + 1, mid + 1]
      } else if (numbers[mid] > target - numbers[i]) {
        right = mid - 1
      } else {
        left = mid + 1
      }
    }
  }
  return [-1, -1]
}

Three solutions: 1. Double pointers gather in the middle; 2. Construct a map data structure; 3. Binary search


2020.10.01

No.216 Combination Total III

Find all the combinations of k numbers that add up to n. Only positive integers from 1 to 9 are allowed in the combination, and there are no repeated numbers in each combination.

instruction:

All numbers are positive integers.
The solution set cannot contain repeated combinations.
Example 1:

Input: k = 3, n = 7
Output: [[1,2,4]]
Example 2:

Input: k = 3, n = 9
Output: [[1,2,6], [1,3,5], [2,3,4]]

Source: LeetCode
Link: https://leetcode-cn.com/problems/combination-sum-iii
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=216 lang=javascript
 *
 * [216] 组合总和 III
 */

// @lc code=start
/**
 * @param {number} k
 * @param {number} n
 * @return {number[][]}
 */
var combinationSum3 = function(k, n) {
    let r = [];

    function sumDfs(start, temp, sum) {
        if(temp.length == k) {
            if(sum == n) {
                r.push(temp.concat());
            };
            return;
        }
        for(let i=start;i<=9;i++) {
            temp.push(i);
            sumDfs(i+1,temp,sum+i);
            temp.pop();
        }
    };

    sumDfs(1, [], 0);
    
    return r;
    
};
Option II:
/*
 * @lc app=leetcode.cn id=216 lang=javascript
 *
 * [216] 组合总和 III
 */

// @lc code=start
/**
 * @param {number} k
 * @param {number} n
 * @return {number[][]}
 */
var combinationSum3 = function(k, n) {
    let temp = [];
    const ans = [];
    const check = (mask, k, n) => {
        temp = [];
        for (let i = 0; i < 9; ++i) {
            if ((1 << i) & mask) {
                temp.push(i + 1);
            }
        }
        return temp.length === k && temp.reduce((previous, value) => previous + value, 0) === n;
    }

    for (let mask = 0; mask < (1 << 9); ++mask) {
        if (check(mask, k, n)) {
            ans.push(temp);
        }
    }
    return ans;
};
third solution:
/*
 * @lc app=leetcode.cn id=216 lang=javascript
 *
 * [216] 组合总和 III
 */

// @lc code=start
/**
 * @param {number} k
 * @param {number} n
 * @return {number[][]}
 */
var combinationSum3 = function(k, n) {
    let number = [[]];
    let a = []
    let numbers = [1,2,3,4,5,6,7,8,9];
    for(let i = 0; i < 9; i++){
        let turn = number.map(v => [...v,numbers[i]])
        // console.log(turn)
        number = number.concat(turn);
    }
    for(let i = 0; i < number.length; i++){
        if(number[i].length != k){
            continue;
        }else{
            if(sum(number[i])!==n){

                continue;
            }else{
                a.push(number[i])
            }
        }
    }
    return a;
};
function sum(arr){
    let sum = 0;
    for(let i = 0; i < arr.length; i++){
        sum+=arr[i];
    }
    return sum;
}

Three solutions: 1. Classic backtracking algorithm, construct dfs query; 2. Sao operation, use binary mask for shift enumeration; 3. Construct a map data structure


2020.10.04

No.689 Maximum sum of three non-overlapping sub-arrays

Given the array nums consists of positive integers, find the maximum sum of three non-overlapping sub-arrays.

The length of each sub-array is k, and we want to maximize the sum of these 3*k items.

Return a list of the starting index of each interval (the index starts at 0). If there are multiple results, the one with the smallest lexicographic order is returned.

Example:

Input: [1,2,1,2,6,7,5,1], 2
Output: [0, 3, 5]
Explanation: The starting index of the sub-array [1, 2], [2, 6], [7, 5] is [0, 3, 5].
We can also take [2, 1], but the result [1, 3, 5] is lexicographically larger.
Notice:

The range of nums.length is between [1, 20000].
The range of nums[i] is between [1, 65535].
The range of k is between [1, floor(nums.length / 3)].

Source: LeetCode
Link: https://leetcode-cn.com/problems/maximum-sum-of-3-non-overlapping-subarrays
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=689 lang=javascript
 *
 * [689] 三个无重叠子数组的最大和
 */

// @lc code=start
/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
var maxSumOfThreeSubarrays = function(nums, k) {
    const dp = new Array(nums.length).fill(0).map( _ => new Array(4).fill(0) );
    // 计算前缀和
    const prefixSums=[nums[0]];
    for(let i=1;i<nums.length;i++) {
      prefixSums[i] = prefixSums[i-1] + nums[i];
    }
    // 填充dp数组
    for(let n=1;n<=3;n++) {
      for(let i=k*n-1;i<nums.length;i++) {
        const prev1 = i-1 >= 0 ? dp[i-1][n] : 0;
        const prevK = i-k >= 0 ? dp[i-k][n-1] : 0;
        const tailSum = i-k >= 0 ? prefixSums[i] - prefixSums[i-k] : prefixSums[i];
        dp[i][n] = Math.max(prev1, prevK + tailSum);
      }
    };
    // 根据dp数组找字典序最小的解
    const result = [];
    let n = 3;
    let current = dp.length-1;
    while(result.length < 3) {
      const v = dp[current][n];
      let i = current;
      while( i-1 >= 0 && dp[i-1][n] == v) {
        i--;
      }
      current = i - k + 1;
      result.push(current);
      current--;
      n--;
    }
    
    return result.reverse();
};
Option II:
/*
 * @lc app=leetcode.cn id=689 lang=javascript
 *
 * [689] 三个无重叠子数组的最大和
 */

// @lc code=start
/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
var maxSumOfThreeSubarrays = function(nums, k) {
    let n = nums.length
    let l = n - k + 1
    let sums = Array(l).fill(0)
    let s = nums.slice(0,k).reduce((x,y) => x+y)
    sums[0] = s
    for (let i=1;i<l;i++){
        s = s + nums[i-1+k] - nums[i-1]
        sums[i] = s
    }
    let j,m
    let mid = new Map()
    for (let i=k-1;i<l;i++){
        mid.set(i,0)
    }
    for (let i=k;i<l;i++){
        j = mid.get(i-1)
        if (sums[i-k] > sums[j]){
            j = i-k
        }
        mid.set(i,j)
    }
    let right = new Map()
    for (let i=2*k-1;i<l;i++){
        right.set(i,k)
    }
    let res = [0,k,2*k]
    for (let r=2*k;r<l;r++){
        m = right.get(r-1)
        if (sums[r-k]+sums[mid.get(r-k)] > sums[m]+sums[mid.get(m)]){
            m = r-k
        }
        right.set(r,m)
        if (sums[r]+sums[m]+sums[mid.get(m)] > sums[res[0]]+sums[res[1]]+sums[res[2]]){
            res = [mid.get(m),m,r]
        }
    }
    return res
};

Two solutions: 1. General solution of dynamic programming, constructing the recursive loop invariant dpi=max{dpi-1, dpi-k+sumRange(i-k+1,i)}, where the meaning of dpi is from [0, In the range of i], select the maximum sum of n numbers, and the adjacent interval of n numbers is k; 2. Using segmentation, divide the array to the left, middle, and right and then move to get the maximum value


2020.10.05

No.1031 Maximum sum of two non-overlapping sub-arrays

Given a non-negative integer array A, return the maximum sum of the elements in two non-overlapping (contiguous) sub-arrays. The lengths of the sub-arrays are L and M respectively. (It needs to be clarified here that the sub-array of length L can appear before or after the sub-array of length M.)

Formally, it returns the largest V, and V = (A[i] + A[i+1] + ... + A[i+L-1]) + (A[j] + A[j+ 1] + ... + A[j+M-1]) and meet one of the following conditions:

 

0 <= i <i + L-1 <j <j + M-1 <A.length, or
0 <= j < j + M - 1 < i < i + L - 1 < A.length.
 

Example 1:

Input: A = [0,6,5,2,2,5,1,9,4], L = 1, M = 2
Output: 20
Explanation: In a selection of sub-arrays, [9] has a length of 1, and [6,5] has a length of 2.
Example 2:

Input: A = [3,8,1,3,2,1,8,9,0], L = 3, M = 2
Output: 29
Explanation: In a selection of sub-arrays, [3,8,1] has a length of 3, and [8,9] has a length of 2.
Example 3:

Input: A = [2,1,5,6,0,9,5,0,3,8], L = 4, M = 3
Output: 31
Explanation: In a selection of sub-arrays, [5,6,0,9] has a length of 4, and [0,3,8] has a length of 3.
 

hint:

L >= 1
M >= 1
L + M <= A.length <= 1000
0 <= A[i] <= 1000

Source: LeetCode
Link: https://leetcode-cn.com/problems/maximum-sum-of-two-non-overlapping-subarrays
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=1031 lang=javascript
 *
 * [1031] 两个非重叠子数组的最大和
 */

// @lc code=start
/**
 * @param {number[]} A
 * @param {number} L
 * @param {number} M
 * @return {number}
 */
var maxSumTwoNoOverlap = function(A, L, M) {
    let max = -Infinity,
        lArr = sum(L), // 获取L的和数组
        mArr = sum(M); // 获取M的和数组

    for(let i=0;i<lArr.length;i++) {
        for(let j=0;j<mArr.length;j++) {
            if( j > i+L-1 || i> j+M-1 ) {
                max = Math.max(max, lArr[i]+mArr[j]);
            }
        }
    }

    return max;

    function sum(n) {
        let s = [];
        for(let i=0;i+n<=A.length;i++) {
            s.push(A.slice(i,i+n).reduce((prev,curr)=>prev+curr))
        }
        return s;
    }
};
Option II:
/*
 * @lc app=leetcode.cn id=1031 lang=javascript
 *
 * [1031] 两个非重叠子数组的最大和
 */

// @lc code=start
/**
 * @param {number[]} A
 * @param {number} L
 * @param {number} M
 * @return {number}
 */
var ListNode = function (val, start, end) {
    this.val = val;
    this.start = start;
    this.end = end;
    this.prev = null;
    this.next = null;
}

var List = function () {
    this.head = null; 
    this.tail = null;
}
var maxSumTwoNoOverlap = function(A, L, M) {
    let l = [], m = [];
    let lList = new List();
    for (let i = 0; i <= A.length-L; i++) {
        let sum = 0;
        for (let j = 0; j < L; j++) {
            sum+= A[i+j];
        }
        let node = new ListNode(sum, i, i+L-1);   
        addToList(lList,node);
    }
    
    let mList = new List();
    for (let i = 0; i <= A.length-M; i++) {
        let sum = 0;
        for (let j = 0; j < M; j++) {
            sum+= A[i+j];
        }
        let node = new ListNode(sum, i, i+M-1); 
        addToList(mList, node);
    }
    
    let mPtr = mList.head;
    let lPtr = lList.head;
    let max = 0;
   
    mPtr = mList.head;
    while (mPtr) {
        while (lPtr) {
           if (Math.max(mPtr.start, lPtr.start) <= Math.min(mPtr.end, lPtr.end)) {
                lPtr = lPtr.next;
            } else {
                max = Math.max(max, mPtr.val+ lPtr.val);
                lPtr = lPtr.next;
            } 
        }
        mPtr = mPtr.next;
        lPtr= lList.head;
    }
  return max;
  
};

function addToList(list, node) {
    if (!list.head) {
        list.head= node;
        list.tail = node;
    } else {
        if (list.head.val <= node.val) {
            list.head.prev = node;
            node.next = list.head;
            list.head = node;
        } else if (list.tail.val >= node.val) {
            list.tail.next = node;
            node.prev = list.tail;
            list.tail = node;
        } else {
            let ptr = list.head;
            while(ptr && ptr.val > node.val) {
                ptr= ptr.next;
            }
            if (!ptr) {
                list.tail = node;
                list.head.next = list.tail;
                node.prev = list.tail;
            }
            else {
                let prev = ptr.prev;
                prev.next = node;
                node.prev = prev;
                node.next = ptr;
                ptr.prev = node;
            }
            
        }
    }
}
third solution:
/*
 * @lc app=leetcode.cn id=1031 lang=javascript
 *
 * [1031] 两个非重叠子数组的最大和
 */

// @lc code=start
/**
 * @param {number[]} A
 * @param {number} L
 * @param {number} M
 * @return {number}
 */
var maxSumTwoNoOverlap = function(A, L, M) {
    return Math.max(traverse(L,M), traverse(M,L));
    
    function traverse(a, b) {
        let res = 0;
        for (let i = 0; i <= A.length-a-b; i++) {
            let sum = A.slice(i,i+a+b).reduce((acc,cur) => acc+cur);
            let l = i+a, r = l+b;
            res = Math.max(res, sum);
            while (r < A.length) {
                sum = sum-A[l]+A[r];
                res = Math.max(res, sum)
                l++, r++;
            }
        }
        return res;
    }
};
Option Four:
/*
 * @lc app=leetcode.cn id=1031 lang=javascript
 *
 * [1031] 两个非重叠子数组的最大和
 */

// @lc code=start
/**
 * @param {number[]} A
 * @param {number} L
 * @param {number} M
 * @return {number}
 */
var maxSumTwoNoOverlap = function(A, L, M) {
    let len = A.length;
    for(let i = 1; i < len; i++) {
        A[i] += A[i - 1];
    }
    
    let LMax = A[L - 1], MMax = A[M-1];
    let res = A[M + L - 1];
    for(let i = M + L ; i< len ; i++) {
        // update LMax to i - M; 
        LMax = Math.max(LMax, A[i - M ] - A[i - M - L]);
        MMax = Math.max(MMax, A[i - L ] - A[i - M - L]);
        res = Math.max(res,
            LMax + A[i] - A[i - M],
            MMax + A[i] - A[i - L]
        )
    }
    return res;
};

Three solutions: 1. Get all the prefix sums of the previous M and L, filter and add the sum to obtain the maximum value; 2. Construct a doubly linked list data structure; 3. Use a moving window to select; 4. Dynamic programming, recursive Approximate res = max{res, the maximum sum of M, the maximum sum of L}


2020.10.16

No.1013 Divide the array into three equal parts

Give you an integer array A, and only return true if it can be divided into three equal non-empty parts, otherwise it returns false.

Formally, if it can be found that the index i+1 <j and satisfies A[0] + A[1] + ... + A[i] == A[i+1] + A[i+2] +. .. + A[j-1] == A[j] + A[j-1] + ... + A[A.length-1] You can divide the array into three equal parts.

 

Example 1:

Input: [0,2,1,-6,6,-7,9,1,2,0,1]
Output: true
Explanation: 0 + 2 + 1 = -6 + 6-7 + 9 + 1 = 2 + 0 + 1
Example 2:

Input: [0,2,1,-6,6,7,9,-1,2,0,1]
Output: false
Example 3:

Input: [3,3,6,5,-2,2,5,1,-9,4]
Output: true
Explanation: 3 + 3 = 6 = 5-2 + 2 + 5 + 1-9 + 4
 

hint:

3 <= A.length <= 50000
-10^4 <= A[i] <= 10^4

Source: LeetCode
Link: https://leetcode-cn.com/problems/partition-array-into-three-parts-with-equal-sum
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=1013 lang=javascript
 *
 * [1013] 将数组分成和相等的三个部分
 */

// @lc code=start
/**
 * @param {number[]} A
 * @return {boolean}
 */
var canThreePartsEqualSum = function(A) {
    const sum = A.reduce((prev, memo) => prev + memo);
    if( sum % 3 != 0 ) {
        return false;
    } else {
        const s = sum / 3;
        // 左右指针
        let p1 = 0,
            l = 0,
            p2 = A.length - 1,
            r = 0;
        
        while( p1 < A.length ) {
            l += A[p1];

            if(l != s) {
                p1++;
            } else {
                break;
            }
        }

        while( p2 > 0 ) {
            r += A[p2];
            if(r != s) {
                p2--;
            } else {
                break;
            }
        }

        if( p1 + 1 < p2 ) {
            return true;
        } else {
            return false;
        }
    }
};
Option II:
/*
 * @lc app=leetcode.cn id=1013 lang=javascript
 *
 * [1013] 将数组分成和相等的三个部分
 */

// @lc code=start
/**
 * @param {number[]} A
 * @return {boolean}
 */
var canThreePartsEqualSum = function(A) {
    const sum = A.reduce((prev, memo) => prev+memo);
    if(sum % 3 != 0) {
        return false;
    } else {
        const s = sum / 3;
        let temp = 0, // 用于记录前i项的和
            n = 0; // 用于记录切割点的个数
        for(let i=0; i< A.length; i++) {
            temp += A[i];
            if(temp == s) {
                n++;
                temp = 0;
            };

            if(n == 3) return true;
        };

        return false;
    }
};

Two solutions: 1. Comparing the position of the left and right pointers, it can be combined into a loop, but it is not easy to expand. For the problem of dividing into more parts, it can be transformed into comparing the position of the pointer to return the result; 2. Recording the split position The number of questions can be better expanded for the problem divided into more parts, and the result is returned by judging the number of sites


Summarize:
  1. The common approach to the problem is mainly to use map, hash, stack and other data structures for optimization, and then to use the reduction of the left and right pointers to carry out the number of loops;
  2. The common solution to sub-problems is to use dynamic programming and backtracking pruning to deal with optimization

Second, the position index problem

2020.10.09

No.34 Find the first and last position of an element in a sorted array

Given an integer array nums arranged in ascending order, and a target value target. Find the start and end positions of the given target value in the array.

The time complexity of your algorithm must be O(log n) level.

If the target value does not exist in the array, [-1, -1] is returned.

Example 1:

Input: nums = [5,7,7,8,8,10], target = 8
Output: [3,4]
Example 2:

Input: nums = [5,7,7,8,8,10], target = 6
Output: [-1,-1]

Source: LeetCode
Link: https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=34 lang=javascript
 *
 * [34] 在排序数组中查找元素的第一个和最后一个位置
 */

// @lc code=start
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var searchRange = function(nums, target) {
    let p1 = 0,
        p2 = nums.length - 1;
    
    // 二分查找
    while(p1 <= p2) {
        let mid = Math.floor((p1 + p2) / 2);
        
        if( target < nums[mid] ) {
            p2 = mid - 1;
        } else if( target > nums[mid] ) {
            p1 = mid + 1;
        } else {
            p1 = mid;
            p2 = mid;
            break;
        }
    };

    // 判断
    if( p1 > p2 ) {
        return [-1,-1];
    } else {
        // 从中心向两边推,推到最远的两个target的位置
        while(nums[p1-1] == target) p1--;
        while(nums[p2+1] == target) p2++;
        return [p1,p2];
    }
};
Option II:
/*
 * @lc app=leetcode.cn id=34 lang=javascript
 *
 * [34] 在排序数组中查找元素的第一个和最后一个位置
 */

// @lc code=start
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var searchRange = function(nums, target) {
    // console.log(nums.indexOf(target),nums.lastIndexOf(target))
    return [nums.indexOf(target),nums.lastIndexOf(target)]
};
third solution:
/*
 * @lc app=leetcode.cn id=34 lang=javascript
 *
 * [34] 在排序数组中查找元素的第一个和最后一个位置
 */

// @lc code=start
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var searchRange = function(nums, target) {
  return nums.map(n => n - target).reduce((p, n, i) => {
    if (n === 0) {
       if (p[0] === -1) {
         p[0] = i
         p[1] = i
       }
       p[1] = i
    }
    return p
  }, [-1, -1])
};

There are three solutions: 1. Binary search: After receiving the middle, expand to the farthest position on both sides, which is the first and last search position; 2. Use indexOf and lastIndexOf API; 3. Problem conversion, convert the position to the target value and traverse position The difference of the value, use the reduce function to find the difference


2020.10.10

No.35 Search for insertion position

Given a sorted array and a target value, find the target value in the array and return its index. If the target value does not exist in the array, return the position where it will be inserted in order.

You can assume that there are no duplicate elements in the array.

Example 1:

Input: [1,3,5,6], 5
Output: 2
Example 2:

Input: [1,3,5,6], 2
Output: 1
Example 3:

Input: [1,3,5,6], 7
Output: 4
Example 4:

Input: [1,3,5,6], 0
Output: 0

Source: LeetCode
Link: https://leetcode-cn.com/problems/search-insert-position
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=35 lang=javascript
 *
 * [35] 搜索插入位置
 */

// @lc code=start
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var searchInsert = function(nums, target) {
    for(let i=0; i<nums.length; i++) {
        if(nums[i] == target) {
            return i;
        } else {
            if(nums[i] < target && nums[i+1] > target) {
                return i+1;
            };
            if(nums[nums.length - 1] < target) return nums.length;
            if(nums[0] > target) return 0;
        }
    }
};
Option II:
/*
 * @lc app=leetcode.cn id=35 lang=javascript
 *
 * [35] 搜索插入位置
 */

// @lc code=start
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var searchInsert = function(nums, target) {
    const n = nums.length;
    let left = 0, right = n - 1, ans = n;
    while (left <= right) {
        let mid = ((right - left) >> 1) + left;
        if (target <= nums[mid]) {
            ans = mid;
            right = mid - 1;
        } else {
            left = mid + 1;
        }
    }
    return ans;
};
third solution:
/*
 * @lc app=leetcode.cn id=35 lang=javascript
 *
 * [35] 搜索插入位置
 */

// @lc code=start
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var searchInsert = function(nums, target) {
    return nums.concat(Infinity).findIndex(n => n >= target);
};

There are three solutions: 1. Conventional solution: directly traverse and compare, return the position according to the condition, the time complexity is O(N); 2. Binary search, the optimization of the first solution, use binary search to reduce the space-time complexity to O (logN); 3. Use js's findIndex and sort APIs to search


2020.10.12

No.162 Finding the peak

The peak element refers to the element whose value is greater than the adjacent value on the left and right.

Given an input array nums, where nums[i] ≠ nums[i+1], find the peak element and return its index.

The array may contain multiple peaks. In this case, just return the location of any peak.

You can assume that nums[-1] = nums[n] = -∞.

Example 1:

Input: nums = [1,2,3,1]
Output: 2
Explanation: 3 is the peak element, and your function should return its index 2.
Example 2:

Input: nums = [1,2,1,3,5,6,4]
Output: 1 or 5
Explanation: Your function can return index 1, and its peak element is 2;
Or return to index 5, and its peak element is 6.
instruction:

Your solution should be O(logN) time complexity.

Source: LeetCode
Link: https://leetcode-cn.com/problems/find-peak-element
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=162 lang=javascript
 *
 * [162] 寻找峰值
 */

// @lc code=start
/**
 * @param {number[]} nums
 * @return {number}
 */
var findPeakElement = function(nums) {
    let p1 = 0,
        p2 = nums.length - 1;

    // 二分查找
    while( p1 < p2 ) {
        let mid = Math.floor( (p1 + p2) / 2 );
        if( nums[mid] > nums[mid+1] ) {
            p2 = mid;
        } else {
            p1 = mid + 1;
        }
    };

    return p2;
};
Option II:
/*
 * @lc app=leetcode.cn id=162 lang=javascript
 *
 * [162] 寻找峰值
 */

// @lc code=start
/**
 * @param {number[]} nums
 * @return {number}
 */
var findPeakElement = function(nums) {
    return nums.indexOf(Math.max(...nums));
};

There are two solutions: 1. Binary search. If you see the requirement of O(logN), you must consider binary search; 2. Use indexOf and Math.max's api


2020.10.13

No.724 Find the center index of an array

Given an array nums of integer type, write a method that returns the "center index" of the array.

We define the center index of the array like this: the sum of all the elements on the left of the center index of the array is equal to the sum of all the elements on the right.

If the array does not have a central index, then we should return -1. If the array has multiple center indexes, then we should return the one closest to the left.

 

Example 1:

enter:
nums = [1, 7, 3, 6, 5, 6]
Output: 3
explain:
The sum of the numbers on the left of index 3 (nums[3] = 6) (1 + 7 + 3 = 11) is equal to the sum of numbers on the right (5 + 6 = 11).
At the same time, 3 is also the first center index that meets the requirements.
Example 2:

enter:
nums = [1, 2, 3]
Output: -1
explain:
There is no center index that satisfies this condition in the array.
 

instruction:

The length range of nums is [0, 10000].
Any nums[i] will be an integer in the range [-1000, 1000].

Source: LeetCode
Link: https://leetcode-cn.com/problems/find-pivot-index
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=724 lang=javascript
 *
 * [724] 寻找数组的中心索引
 */

// @lc code=start
/**
 * @param {number[]} nums
 * @return {number}
 */
var pivotIndex = function(nums) {
    // 为空直接返回-1
    if(nums.length == 0) return -1;

    // 第一个
    if(aSum(nums.slice(1)) == 0) return 0;
    
    // 中间
    for(let i=1;i<= nums.length-2;i++) {
        if(aSum(nums.slice(0,i)) == aSum(nums.slice(i+1))) return i
    };

    // 最后一个
    if(aSum(nums.slice(0,nums.length-1)) == 0) return nums.length - 1;

    return -1;

    function aSum(arr) {
        return arr.reduce((prev, memo) => prev + memo, 0);
    }
};
Option II:
/*
 * @lc app=leetcode.cn id=724 lang=javascript
 *
 * [724] 寻找数组的中心索引
 */

// @lc code=start
/**
 * @param {number[]} nums
 * @return {number}
 */
var pivotIndex = function(nums) {
    let sum = nums.reduce((prev, memo) => prev+memo,0),
        leftsum = 0;
    
    for(let i=0;i<nums.length;i++) {
        if(sum - nums[i] == 2* leftsum) {
            return i;
        } else {
            leftsum += nums[i];
        }
    }

    return -1;

};

There are two solutions: 1. Use the reduce API to find the left and right sums respectively, and then compare them. Here you need to process the beginning and the end. Since reduce is based on a generator, the time complexity here is O(N^2 ), the efficiency is extremely poor; 2. For 1, we find that the sum = the left side sum + nums[i] + the right side sum, and when the left side sum is equal to the right side sum, the sum-nums[i] = 2*left side sum Yes, you don’t need to find the sum at this time, which simplifies the traversal of the middle layer, so the space-time complexity is O(N)


2020.10.14

No.747 is the largest number that is at least twice the other number

In a given array nums, there is always a largest element.

Find if the largest element in the array is at least twice as large as every other number in the array.

If it is, it returns the index of the largest element, otherwise it returns -1.

Example 1:

Input: nums = [3, 6, 1, 0]
Output: 1
Explanation: 6 is the largest integer, for other integers in the array,
6 is greater than twice the other elements in the array. The index of 6 is 1, so we return 1.
 

Example 2:

Input: nums = [1, 2, 3, 4]
Output: -1
Explanation: 4 is not more than twice as large as 3, so we return -1.
 

hint:

The length of nums ranges from [1, 50].
The integer range of each nums[i] is [0, 100].

Source: LeetCode
Link: https://leetcode-cn.com/problems/largest-number-at-least-twice-of-others
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=747 lang=javascript
 *
 * [747] 至少是其他数字两倍的最大数
 */

// @lc code=start
/**
 * @param {number[]} nums
 * @return {number}
 */
var dominantIndex = function(nums) {
    let max = -Infinity, pos = 0;
    for(let i=0; i< nums.length; i++) {
        if( nums[i] > max) {
            max = nums[i];
            pos = i;
        }
    }
    for(let i=0; i< nums.length; i++) {
        if( i != pos && ( 2*nums[i] ) > max) return -1;
    }
    return pos;
};
Option II:
/*
 * @lc app=leetcode.cn id=747 lang=javascript
 *
 * [747] 至少是其他数字两倍的最大数
 */

// @lc code=start
/**
 * @param {number[]} nums
 * @return {number}
 */
var dominantIndex = function(nums) {
    let max = 0, max2 = 0, pos = 0;
    for(let i = 0; i< nums.length; i++) {
        if(nums[i] > max) {
            max2 = max;
            max = nums[i];
            pos = i
        } else if (nums[i] > max2) {
            max2 = nums[i];
        }
    };

    if(2*max2 > max) return -1;

    return pos;
};

There are two schemes: 1. Two loops, the first loop gets the largest value, and the second loop compares whether it meets the conditions. The time complexity is O(N)+O(N) ~ O(N); 2. One loop, To get the first and second largest, the return result only needs to compare whether the second largest meets the conditions, and the time complexity is O(N)


2020.10.15

No.852 Peak Index of Mountain Range Array

We call the array A that meets the following properties a mountain range:

A.length >= 3
There is 0 <i <A.length-1 such that A[0] <A[1] <... A[i-1] <A[i]> A[i+1]> ...> A[A .length-1]
Given an array determined to be a mountain range, return anything that satisfies A[0] <A[1] <... A[i-1] <A[i]> A[i+1]> ...> A[ A.length-1] the value of i.

 

Example 1:

Input: [0,1,0]
Output: 1
Example 2:

Input: [0,2,1,0]
Output: 1
 

hint:

3 <= A.length <= 10000
0 <= A[i] <= 10^6
A is the mountain defined above

Source: LeetCode
Link: https://leetcode-cn.com/problems/peak-index-in-a-mountain-array
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=852 lang=javascript
 *
 * [852] 山脉数组的峰顶索引
 */

// @lc code=start
/**
 * @param {number[]} arr
 * @return {number}
 */
var peakIndexInMountainArray = function(arr) {
    return arr.indexOf(Math.max(...arr));
};
Option II:
/*
 * @lc app=leetcode.cn id=852 lang=javascript
 *
 * [852] 山脉数组的峰顶索引
 */

// @lc code=start
/**
 * @param {number[]} arr
 * @return {number}
 */
var peakIndexInMountainArray = function(arr) {
    let max = -Infinity, pos = 0;
    for(let i=0; i<arr.length; i++) {
        if(arr[i] > max) {
            max = arr[i];
            pos = i;
        }
    };
    return pos;
};
third solution:
/*
 * @lc app=leetcode.cn id=852 lang=javascript
 *
 * [852] 山脉数组的峰顶索引
 */

// @lc code=start
/**
 * @param {number[]} arr
 * @return {number}
 */
var peakIndexInMountainArray = function(arr) {
    let l = 0, r = arr.length - 1;
    // 二分查找
    while( l < r ) {
        let m = Math.floor( ( l + r ) / 2 );
        if( arr[m] < arr[m+1] ) {
            l = m + 1;
        } else {
            r = m;
        }
    };

    return l;
};

There are three solutions: 1. Use indexOf and Math.max's api; 2. Recycle to get the maximum value and position information; 3. Use binary search to reduce the time complexity to O(logN)


Summarize:
  1. The common method of location indexing problem is mainly to use indexOf, lastIndexOf API to find the location, and different requirements in the middle can be converted into different formulas for processing;
  2. The location index problem is essentially a search problem. For the search problem, common search algorithms can be used to transform it, but the mutual exclusion of time and space complexity needs to be considered. The most common search algorithm is the binary search algorithm.

Three, the path problem

2020.10.19

No. 62 Different paths

A robot is located in the upper left corner of an mxn grid (the starting point is marked as "Start" in the figure below).

The robot can only move one step down or to the right at a time. The robot tries to reach the bottom right corner of the grid (labeled "Finish" in the image below).

How many different paths are there in total?

For example, the image above is a 7 x 3 grid. How many possible paths are there?

 

Example 1:

Input: m = 3, n = 2
Output: 3
explain:
Starting from the upper left corner, there are a total of 3 paths to the lower right corner.

  1. Right -> Right -> Down
  2. Right -> Down -> Right
  3. Down -> right -> right
    Example 2:

Input: m = 7, n = 3
Output: 28
 

hint:

1 <= m, n <= 100
Question data guarantee that the answer is less than or equal to 2 * 10 ^ 9

Source: LeetCode
Link: https://leetcode-cn.com/problems/unique-paths
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=62 lang=javascript
 *
 * [62] 不同路径
 */

// @lc code=start
/**
 * @param {number} m
 * @param {number} n
 * @return {number}
 */
var uniquePaths = function(m, n) {
    // 用矩阵表来记录所有路径数
    /**
     * 如对于 3 x 2 的矩阵可用如下表示:
     * 1 1 1
     * 1 2 3
     * 无剪枝,将所有信息录入矩阵表,最后一位数就是路径和
     */
    let dp = new Array(n);
    // 对于第一行所有算元素和第一列所有元素置为1
    for(let row=0;row<n;row++) {
        dp[row] = new Array(m);
        dp[row][0] = 1;
    }
    for(let col=0;col<m;col++) {
        dp[0][col] = 1;
    }
    // 动态规划
    for(let i=1;i<n;i++) {
        for(let j=1;j<m;j++) {
            dp[i][j] = dp[i-1][j] + dp[i][j-1]
        }
    }

    return dp[n-1][m-1];
};
Option II:
/*
 * @lc app=leetcode.cn id=62 lang=javascript
 *
 * [62] 不同路径
 */

// @lc code=start
/**
 * @param {number} m
 * @param {number} n
 * @return {number}
 */
var uniquePaths = function(m, n) {
    // 阶乘函数
    const fac = (n) => {
        if(n<=1) return 1;
        return fac(n-1)*n;
    }

    return fac(n-1+m-1) / ( fac(m-1) * fac(n-1) );
};

There are two solutions: 1. Dynamic programming: The problem of finding a path usually thinks of dynamic programming. The matrix table is used to record the sum of the paths, and the last addition result is returned. The recursive loop invariant is dpi=dpi-1+dpi, here You can also use a one-dimensional array to directly replace the data of the previous layer, but the scalability is not good, and it is only applicable to the ontology; 2. Permutation and combination: You can convert the problem to 1 to the right and 0 to the down, and there are two each time. The choice of different results, and then the permutation and combination of 1 or 0 among the m-1+n-1 choices, namely Cm-1+n-1n-1=Cm-1+n-1m-1


2020.10.20

No.63 Different Path-ii

A robot is located in the upper left corner of an mxn grid (the starting point is marked as "Start" in the figure below).

The robot can only move one step down or to the right at a time. The robot tries to reach the bottom right corner of the grid (labeled "Finish" in the image below).

Now consider that there are obstacles in the grid. So how many different paths will there be from the upper left corn


维李设论
1.1k 声望4k 粉丝

专注大前端领域发展