核心思路:
-
DP 方程
当前项最小路径和 = 当前项值 + 上项或左项中的最小值 grid[i][j] += Math.min( grid[i - 1][j], grid[i][j - 1] )
-
边界处理
grid 的第一行与第一列 分别没有上项与左项 故单独处理计算起项最小路径和 计算第一行
for (let j = 1; j < col; j++) grid[0][j] += grid[0][j - 1]
计算第一列
for (let i = 1; i < row; i++) grid[i][0] += grid[i - 1][0]
/**
* @param {number[][]} grid
* @return {number}
*/
var minPathSum = function (grid) {
let row = grid.length,
col = grid[0].length
// calc boundary
for (let i = 1; i < row; i++)
// calc first col
grid[i][0] += grid[i - 1][0]
for (let j = 1; j < col; j++)
// calc first row
grid[0][j] += grid[0][j - 1]
for (let i = 1; i < row; i++) for (let j = 1; j < col; j++) grid[i][j] += Math.min(grid[i - 1][j], grid[i][j - 1])
return grid[row - 1][col - 1]
}
let a = '9007199254740991'
let b = '1234567899999999999'
function add(a, b) {
//取两个数字的最大长度
let maxLength = Math.max(a.length, b.length)
//用0去补齐长度
a = a.padStart(maxLength, 0) //"0009007199254740991"
b = b.padStart(maxLength, 0) //"1234567899999999999"
//定义加法过程中需要用到的变量
let t = 0
let f = 0 //"进位"
let sum = ''
for (let i = maxLength - 1; i >= 0; i--) {
t = parseInt(a[i]) + parseInt(b[i]) + f
f = Math.floor(t / 10)
sum = (t % 10) + sum
}
if (f == 1) {
sum = '1' + sum
}
return sum
}
- 暴力解决
var maxProfit = function (prices) {
var maxprofit = 0
for (var i = 0; i < prices.length; i++) {
for (var j = i + 1; j < prices.length; j++) {
var profit = prices[j] - prices[i]
if (profit > maxprofit) maxprofit = profit
}
}
return maxprofit
}
只关心 i 前面元素里最小的 minprice 是多少,然后迭代当前 price[i] - minprice 得到最大值
let maxProfit = function (prices) {
let max = 0,
minprice = prices[0]
for (let i = 1; i < prices.length; i++) {
minprice = Math.min(prices[i], minprice)
max = Math.max(max, prices[i] - minprice)
}
return max
}
var maxProfit = function (prices) {
let money = 0
let buy = prices[0]
for (let price of prices) {
if (price > buy) {
money += price - buy
}
buy = price
}
return money
}
[1,1,3,3,2,2,4] 找出重复的数字
https://johnzhu12.github.io/easy/Array/只出现一次的数字.html
[0,0,0,1,1,1,2,2,3,3,4] 找出不重复的数字有多少个,并把数组前 N 项改成不重复的数字
var findSingle = function (arr) {
var len = arr.length,
sum = 0
if (!arr || len == 0) return 0
var sum = 0
var numMap = {}
for (var i = 0; i < len; i++) {
//有重复
if (numMap[arr[i]] !== undefined) {
numMap[arr[i]]++
} else {
//没有重复
numMap[arr[i]] = 1
}
}
for (var key in numMap) {
if (numMap[key] == 1) {
arr[sum] = key
sum++
}
}
//把数组前N个改成不重复的数字
console.log(arr)
return sum
}
var src = [0, 0, 0, 1, 1, 1, 2, 5, 2, 3, 3, 4]
var res = findSignle(src)
console.log(res)
数组可否分成和相等的三个数组
/**
* @param {number[]} arr
* @return {boolean}
*/
var canThreePartsEqualSum = function (arr) {
let sum = arr.reduce((a, b) => a + b)
let num = 3
let temp = 0
for (let a of arr) {
temp += a
if (temp === sum / 3) num--, (temp = 0)
}
return num <= 0
}
那两个就是把 num 改成 2
class Queen {
constructor(num) {
this.num = num
this.arr = []
this.result = []
this.initList()
this.buildList(this.arr, 0)
}
initList() {
let num = this.num
for (let i = 0; i < num; i++) {
this.arr[i] = []
for (let j = 0; j < num; j++) {
this.arr[i][j] = 0
}
}
console.log(this.arr)
}
buildList(list, row) {
// 递归中止条件,找到一个解缓存起来
if (row === list.length) {
this.result.push(JSON.parse(JSON.stringify(list)))
return
}
for (let col = 0, len = list.length; col < len; col++) {
if (this.isSafe(list, row, col)) {
list[row][col] = 1
this.buildList(list, row + 1)
// 走到这里,说明该次递归已经结束,不管找没找到,都需要重置
list[row][col] = 0
}
}
}
isSafe(list, row, col) {
const len = list.length
// 同一列
for (let i = 0; i < len; i++) {
if (list[i][col] === 1) return false
}
// 斜右上方
for (let i = row - 1, j = col + 1; i >= 0 && j < len; i--, j++) {
if (list[i][j] === 1) return false
}
// 斜左上方
for (let i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
if (list[i][j] === 1) return false
}
return true
}
}
const queen = new Queen(8)
console.log(queen.result)
-优化
其实解法跟之前一样,上面用了二维矩阵来记录位置,因为已经确定同一行不可能存在 2 个皇后实际上只用一维数组就表示:list[row] = col;减少空间消耗
isSafe 判断和之前不同
isSafe(row) {
for (let i = 0; i < row; i++) {
// 判断列
if (this.arr[i] === this.arr[row]) return false;
// 判断对角线
if (Math.abs(this.arr[row] - this.arr[i]) === row - i) return false;
}
return true;
}
完整代码
class Queen {
constructor(num) {
this.num = num
this.arr = []
this.result = []
this.initList()
this.buildList(0)
}
initList() {
let num = this.num
for (let i = 0; i < num; i++) {
this.arr[i] = 0
}
}
buildList(row) {
// 递归中止条件,找到一个解缓存起来
if (row === this.num) {
this.result.push(JSON.parse(JSON.stringify(this.arr)))
return
}
for (let col = 0; col < this.num; col++) {
this.arr[row] = col
if (this.isSafe(row)) {
this.buildList(row + 1)
}
}
}
isSafe(row) {
for (let i = 0; i < row; i++) {
// 判断列
if (this.arr[i] === this.arr[row]) return false
// 判断对角线
if (Math.abs(this.arr[row] - this.arr[i]) === row - i) return false
}
return true
}
}
const queen = new Queen(8)
console.log(queen.result)
var search = function (arr, low, high, key) {
if (high < low) {
return '无值'
}
var index = Math.floor((low + high) / 2)
//console.log(typeof index);
if (key == arr[index]) {
return index
} else if (key > arr[index]) {
return search(arr, index + 1, high, key)
} else if (key < arr[index]) {
return search(arr, low, index - 1, key)
}
}
function genArray(n) {
let a = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22] //生成的随机数的集合
let res = []
for (let i = 0; i < n; i++) {
let index = parseInt(Math.random() * a.length) //生成一个的随机索引,索引值的范围随数组a的长度而变化
res.push(a[index])
a.splice(index, 1) //已选用的数,从数组a中移除, 实现去重复
}
return res
}
改下:
function genArray(n) {
let arr = []
for (var i = 1; i <= n; i++) {
arr.push(i)
}
let res = []
for (let i = 0; i < n; i++) {
let index = parseInt(Math.random() * arr.length) //生成一个的随机索引,索引值的范围随数组a的长度而变化
res.push(arr[index])
arr.splice(index, 1) //已选用的数,从数组a中移除, 实现去重复
}
return res
}
function findSumEq(n, m) {
if (n == 0) return
let arr = []
for (var i = 1; i <= n; i++) {
arr.push(i)
}
// ??
}
var res = findSumEq(4, 5)
- 回溯法模板
var maxCoins = function (nums) {
let n = nums.length
// 添加两侧的虚拟气球
let points = [1, ...nums, 1]
let dp = Array.from(Array(n + 2), () => Array(n + 2).fill(0))
// 最后一行开始遍历,从下往上
for (let i = n; i >= 0; i--) {
// 从左往右
for (let j = i + 1; j < n + 2; j++) {
for (let k = i + 1; k < j; k++) {
dp[i][j] = Math.max(dp[i][j], points[j] * points[k] * points[i] + dp[i][k] + dp[k][j])
}
}
}
return dp[0][n + 1]
}