var coinChange = function(coins, amount) {
if(amount===0) return 0;
const dp = Array(amount+1).fill(Number.MAX_VALUE)
dp[0] = 0;
for (let i = 1; i < dp.length; i++) {
for (let j = 0; j < coins.length; j++) {
if (i-coins[j]>=0) {
dp[i] = Math.min(dp[i],dp[i-coins[j]]+1)
}
}
}
return dp[dp.length-1] ===Number.MAX_VALUE?-1:dp[dp.length-1]
};
var climbStairs = function(n) {
let step = [];
step[0] = 1;
step[1] = 1;
for(let i=2;i<=n;i++){
step[i] = step[i-1]+step[i-2]
}
return step[n]
};
var minimumTotal = function(triangle) {
let dp = triangle;
for (let i = dp.length-2; i >= 0 ; i--) {
for (let j = 0; j < dp[i].length; j++) {
dp[i][j] = Math.min(dp[i+1][j],dp[i+1][j+1]) + dp[i][j]
}
}
return dp[0][0]
};
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
};
var maxProduct = function (nums) {
if (!nums.length) return null;
let max = nums[0], state = [];
for (let i = 0; i < nums.length; i++) {
state[i] = []
}
state[0][0] = nums[0];
state[0][1] = nums[0];
for (let i = 1; i < nums.length; i++) {
state[i][0] = Math.max(state[i - 1][0] * nums[i], nums[i], state[i - 1][1] * nums[i])
state[i][1] = Math.min(state[i - 1][1] * nums[i], nums[i], state[i - 1][0] * nums[i])
if (max < state[i][0]) max = state[i][0]
}
return max
};
var change = function(amount, coins) {
let dp = new Array(amount+1).fill(0)
if(amount === 0) return 1;
dp[0] = 1;
for (let j = 0; j < coins.length; j++) {
for (let i = 1; i < amount+1; i++) {
if(i-coins[j]>=0){
dp[i] = dp[i]+dp[i-coins[j]]
}
}
}
return dp[dp.length-1]
};
var longestCommonSubsequence = function (text1, text2) {
let n = text1.length;
let m = text2.length;
let dp = Array.from(new Array(n + 1), () => new Array(m + 1).fill(0))
for (let i = 1; i <= n; i++) {
for (let j = 1; j <= m; j++) {
if (text1[i - 1] == text2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1
} else {
dp[i][j] = Math.max(dp[i][j - 1], dp[i - 1][j])
}
}
}
return dp[n][m]
};
var rob = function(nums) {
const len = nums.length;
const res = new Array(len+1);
res[0] = 0;
res[1] = nums[0];
for (let i = 2; i <= len; i++) {
res[i] = Math.max(res[i-1],res[i-2]+nums[i-1])
}
return res[len]
};
var rob = function(nums) {
let len = nums.length;
if(len===1) return nums[0]
if(len ===0) return 0;
function dpGo(nums) {
const dp = new Array(len-1);
dp[0] = 0;
dp[1] = nums[0];
for (let i = 2; i
// var maxProfit = function(prices) {
// let len = prices.length;
// let max = 0;
// for (let i = 0; i
// var maxProfit = function(prices) {
// let max = 0;
// const len = prices.length;
// for (let i = 1; i < len; i++) {
// max+=Math.max(prices[i]-prices[i-1],0)
// }
// return max;
// };
var maxProfit = function(prices) {
let profit = 0;
for (let i = 0; i < prices.length-1; i++) {
if(prices[i+1]>prices[i]) profit+=prices[i+1]-prices[i]
}
return profit;
}
var maxProfit = function(prices) {
let n = prices.length;
if(n===0) return 0;
let dpi10 = 0,dpi11=-Infinity,dpi20 = 0,dpi21 = -Infinity;
for (let i = 0; i < n; i++) {
dpi10 = Math.max(dpi10,dpi11+prices[i])
dpi11 = Math.max(dpi11,0-prices[i])
dpi20 = Math.max(dpi20,dpi21+prices[i])
dpi21 = Math.max(dpi21,dpi10-prices[i])
}
return dpi20
};
var maxProfit = function(k, prices) {
let len = prices.length;
if(len === 0) return 0;
if(k >= len/2) return maxProfit2(prices);
let dp = Array.from(new Array(len), () => new Array(k+1));
for (let i = 0; i < len; i++) {
for (let j = 0; j <= k; j++) {
dp[i][j] = new Array(2).fill(0);
}
}
for (let i = 0; i < len; i++) {
for (let j = k; j > 0; j--) {
if(i===0) {
dp[i][j][0] = 0;
dp[i][j][1] = -prices[i];
continue;
}
dp[i][j][0] = Math.max(dp[i-1][j][0], dp[i-1][j][1] + prices[i]);
dp[i][j][1] = Math.max(dp[i-1][j][1], dp[i-1][j-1][0] - prices[i]);
}
}
return dp[len-1][k][0];
};
function maxProfit2(prices) {
let profits = 0;
for (let i = 0; i < prices.length + 1; i++) {
if(prices[i + 1] - prices[i] > 0) {
profits += prices[i + 1] - prices[i]
}
}
return profits;
};
var maxProfit = function(prices) {
let n = prices.length;
if(n===0) return 0;
let dp_i_0 = 0,dp_i_1 = -Infinity,dp_pre = 0;
for (let i = 0; i < n; i++) {
let tmp = dp_i_0;
dp_i_0 = Math.max(dp_i_0,dp_i_1+prices[i])
dp_i_1 = Math.max(dp_i_1,dp_pre-prices[i])
dp_pre = tmp;
}
return dp_i_0
};
var maxProfit = function(prices, fee) {
let dp = new Array(prices.length);
for (let i = 0; i < dp.length; i++) {
dp[i] = new Array(2)
}
dp[0][0] = 0;
dp[0][1] = 0-fee-prices[0];
for (let i = 1; i < prices.length; i++) {
dp[i][0] = Math.max(dp[i-1][0],dp[i-1][1]+prices[i])
dp[i][1] = Math.max(dp[i-1][1],dp[i-1][0]-prices[i]-fee)
}
return dp[prices.length-1][0]
};
var numSquares = function(n) {
let dp = new Array(n+1).fill(0)
for (let i = 1; i <= n; i++) {
dp[i] = i;
for (let j = 1; j*j <= i; j++) {
dp[i] = Math.min(dp[i],dp[i-j*j]+1)
}
}
return dp[n]
};
var minDistance = function(word1, word2) {
let n = word1.length;
let m = word2.length;
let dp = [];
for (let i = 0; i <=n; i++) {
dp.push([])
for (let j = 0; j <= m; j++) {
if(i*j){
dp[i][j] = word1[i-1]===word2[j-1]?dp[i-1][j-1]:(Math.min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1])+1)
}else{
dp[i][j] = i+j
}
}
}
return dp[n][m]
};
var uniquePaths = function(m, n) {
let dp = new Array(n).fill(1);
for (let i = 1; i
var uniquePathsWithObstacles = function(obstacleGrid) {
let n = obstacleGrid.length;
let m = obstacleGrid[0].length;
let res = new Array(m).fill(0);
res[0] = 1;
for (let i = 0; i < n; i++) {
for (let j = 0; j < m; j++) {
if(obstacleGrid[i][j]==1){
res[j] = 0;
}else if(j>0){
res[j] += res[j-1]
}
}
}
return res[m-1]
};
var uniquePathsIII = function(grid) {
let init = {
grid:null,
start:[],
end:[],
path_num:0,
res:0
}
init_grid.call(init,grid);
get_paths(init)
return init.res
};
function get_paths(obj){
if(move(obj,1,0)===1){
get_paths(obj);
trace_back(obj,1,0)
}
if(move(obj,0,-1)===1){
get_paths(obj);
trace_back(obj,0,-1)
}
if(move(obj,-1,0)===1){
get_paths(obj);
trace_back(obj,-1,0)
}
if(move(obj,0,1)===1){
get_paths(obj);
trace_back(obj,0,1)
}
}
function trace_back(obj,up,left){
obj.grid[obj.start[0]][obj.start[1]] = 0;
obj.start[0] += up;
obj.start[1] += left;
obj.path_num++;
}
function move(obj,up,left){
if (obj.grid[obj.start[0]-up][obj.start[1]-left]===2&&obj.path_num===0) {
obj.res++;
return 2;
}else if(obj.grid[obj.start[0]-up][obj.start[1]-left] === 0){
obj.start[0] -= up;
obj.start[1] -= left;
obj.grid[obj.start[0]][obj.start[1]] = -1;
obj.path_num--
return 1
}else{
return -1
}
}
function init_grid(grid){
this.grid = new Array(grid.length+2);
for (let i = 0; i < this.grid.length; i++) {
this.grid[i] = new Array(grid[0].length+2).fill(-1)
}
for (let i = 0; i < grid.length; i++) {
for (let j = 0; j < grid[0].length; j++) {
if(grid[i][j] === 1) this.start = [i+1,j+1];
if(grid[i][j]===2) this.end = [i+1,j+1];
if(grid[i][j]===0) this.path_num++
this.grid[i+1][j+1] = grid[i][j]
}
}
}
var longestValidParentheses = function(s) {
var max = 0,n = s.length;
const dp = new Array(n).fill(0);
for (let i = 1; i < n; i++) {
if(s[i] === ')'){
if(s[i-1] === '('){
dp[i] = (i>=2?dp[i-2]:0)+2
}else if(i-dp[i-1]>0&&s[i-dp[i-1]-1]=='('){
dp[i] = dp[i-1]+((i-dp[i-1]>=2)?dp[i-dp[i-1]-2]:0)+2
}
max = Math.max(max,dp[i])
}
}
return max
};
/*
* @lc app=leetcode.cn id=64 lang=javascript
*
* [64] 最小路径和
*
* https://leetcode-cn.com/problems/minimum-path-sum/description/
*
* algorithms
* Medium (64.01%)
* Likes: 480
* Dislikes: 0
* Total Accepted: 89.6K
* Total Submissions: 136.6K
* Testcase Example: '[[1,3,1],[1,5,1],[4,2,1]]'
*
* 给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
*
* 说明:每次只能向下或者向右移动一步。
*
* 示例:
*
* 输入:
* [
* [1,3,1],
* [1,5,1],
* [4,2,1]
* ]
* 输出: 7
* 解释: 因为路径 1→3→1→1→1 的总和最小。
*
*
*/
// @lc code=start
/**
* @param {number[][]} grid
* @return {number}
*/
var minPathSum = function (grid) {
if (grid.length === 0) return 0;
const dp = [];
const rows = grid.length;
const cols = grid[0].length;
for (let i = 0; i < rows + 1; i++) {
dp[i] = [];
// 初始化第一列
dp[i][0] = Number.MAX_VALUE;
for (let j = 0; j < cols + 1; j++) {
// 初始化第一行
if (i === 0) {
dp[i][j] = Number.MAX_VALUE;
}
}
}
// tricky
dp[0][1] = 0;
for (let i = 1; i < rows + 1; i++) {
for (let j = 1; j < cols + 1; j++) {
// state transition
dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i - 1][j - 1];
}
}
return dp[rows][cols];
};
// @lc code=end
var maximalSquare = function(matrix) {
if(matrix.length === 0) return 0;
const dp = [];
const rows = matrix.length;
const cols = matrix[0].length;
let max = Number.MIN_VALUE;
for (let i = 0; i < rows+1; i++) {
if(i===0){
dp[i] = new Array(cols+1).fill(0)
}else{
dp[i] = [0]
}
}
for (let i = 1; i < rows+1; i++) {
for (let j = 1; j < cols+1; j++) {
if(matrix[i-1][j-1] === '1'){
dp[i][j] = Math.min(dp[i-1][j-1],dp[i-1][j],dp[i][j-1]) +1;
max = Math.max(max,dp[i][j])
}else{
dp[i][j] = 0;
}
}
}
return max*max
};
function maxSumSubmatrix (matrix, K) {
let max = -Infinity;
const m = matrix.length;
const n = matrix[0].length;
for (let i = 0; i < n; i++) {
const rowSum = Array(m).fill(0);
for (let j = i; j < n; j++) {
for (let k = 0; k < m; k++) {
rowSum[k] += matrix[k][j];
}
let sum = 0;
const arr = [0];
for (let r = 0; r < m; r++) {
sum += rowSum[r];
// js中的Set没有ceiling或者lowerbound方法,
// 所以实现一个方法查找应当插入值的位置
let idx = insertIndex(arr, sum - K);
idx = idx >= arr.length ? arr.length - 1 : idx;
const val = sum - arr[idx];
if (idx > -1 && val <= K) {
if (val === K) return K;
else max = Math.max(max, val);
}
const insertIdx = insertIndex(arr, sum);
if (arr[insertIdx] !== sum) {
// 在合适的index位置插入该值,保证arr是个有序数组
arr.splice(insertIdx, 0, sum);
}
}
}
}
return max;
}
function insertIndex(nums, target){
let low = 0;
let high = nums.length - 1;
let mid;
while (low <= high) {
mid = (low + high) >> 1;
if (nums[mid] === target) {
return mid;
} else if (nums[mid] > target) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return low;
}
var findCircleNum = function(M) {
let n = M.length;
if(n===0) return 0;
let count = n;
let find = (p)=>{
while(p!=parent[p]){
parent[p] = parent[parent[p]]
p=parent[p]
}
return p
}
let union = (p,q)=>{
let rootP = find(p)
let rootQ = find(q)
if(rootP === rootQ) return
parent[rootP] = rootQ;
count--
}
let parent = new Array(n);
for (let i = 0; i < n; i++) {
parent[i] = i;
}
for (let i = 0; i
最长子串、子序列(1143,72)
字符串+递归 or DP(115)
PS : 有些题目在不同的分类下重复,说明这个题可以有不同的解决方法。