Dynamic programming (js version)

1. Introduction to dynamic programming algorithm

Understand dynamic programming ~ know a good article

LeetCode's simple dynamic programming problem:

Summary:

Dynamic programming is not so much an algorithm as a methodology.
The methodology is mainly committed to splitting the "appropriate" problem into three sub objectives, which can be broken at one time:

  • 1. Establish the state transition equation
  • 2. Cache and reuse previous results
  • 3. Calculate from small to large in order

2. "01 backpack" problem

Concept: there are N items and a backpack with a maximum weight of W. The weight of the ith article is weight[i], and the value is value[i]. Each item can only be used once to find out which items are loaded into the backpack and the total value of the items is the largest.

Video link of this case ~ Shang Silicon Valley

analysis:


Graphic analysis:

Case study:

1. If there were only guitars now(G) , At this time, no matter how large the backpack capacity is, only one guitar can be put(G) 
2. If there is a guitar and stereo, Validation formula:v[1][1] =1500
	(1). i = 1, j = 1 
	(2). w[i] = w[1] = 1 j = 1   
	v[i][j]=max{v[i-1][j], v[i]+v[i-1][j-w[i]]} : 
	v[1][1] = max {v[0][1], v[1] + v[0][1-1]} = max{0, 1500 + 0} = 1500
3. If there is a guitar/sound/computer, Validation formula:v[3][4] 
	(1). i = 3;j = 4
	(2). w[i] = w[3] =3  j = 4
	j = 4 >= w[i] = 3 => 4 >= 3
	v[3][4] = max {v[2][4], v[3] + v[2][1]} = max{3000, 2000+1500} = 2000+1500

induce:

Trace back from the lower right corner of the table. If the value of the best combination of the first n items is the same as that of the first n-1 items, it indicates that the nth item has not been loaded; Otherwise, the nth item is loaded.

Question: what is the maximum value when the backpack capacity is 4?

code:

const w = [1, 4, 3]; //Item weight
const value = [1500, 3000, 2000]; //Value of goods 
const m = 4; //Backpack Capacity
const n = 3; //Number of items

// Two dimensional array: v[i][j] represents the maximum value that can be loaded into the backpack with capacity of j in the first I items
let v = new Array(n + 1).fill(0).map(() => new Array(m + 1).fill(0));

for (let i = 1; i <= n; i++) { //i control line
    for (let j = 1; j <= m; j++) { //j control column
        if (w[i - 1] > j) {
            v[i][j] = v[i - 1][j];
        } else {
            v[i][j] = Math.max(v[i - 1][j], value[i - 1] + v[i - 1][j - w[i - 1]]);
        }
    }
}

// console.log(v[n][m]); //3500
console.log(v);
// The result of two-dimensional array v is as follows:
// [
//     [0, 0, 0, 0, 0],
//     [0, 1500, 1500, 1500, 1500],
//     [0, 1500, 1500, 1500, 3000],
//     [0, 1500, 1500, 2000, 3500]
// ]

Time complexity: O(m*n)
Space complexity: O(m*n)

Optimize the code: reduce the space complexity to O(n).

Two dimensional array becomes one-dimensional array: in one-dimensional dp array, dp[j] means that the value of the items carried by the backpack with capacity of j can be up to dp[j].

const w = [1, 3, 4];
const value = [15, 20, 30];
const n = 4; //Maximum capacity of backpack
const m = w.length; //Number of items
let dp = new Array(n + 1).fill(0);

for (var i = 1; i <= m; i++) {
    for (var j = n; j >= w[i - 1]; j--) {
        dp[j] = Math.max(dp[j], dp[j - w[i - 1]] + value[i - 1]);
        // dp[j]: the current item is not placed -- > because it is in reverse order, it is empty during initialization
        // dp[j - w[i - 1]: the maximum value of items that can be loaded in the remaining backpack capacity
    	// value[i - 1] the value of the current item
    }
}
console.log(dp);//[ 0, 15, 15, 20, 35 ]

Key points:

  1. Inner loop traversal in reverse order (and pay attention to the judgment condition: J > = w [I - 1])

Reason: flashback traversal is to ensure that item i is only put in once! Once it is traversed in positive order, the item will be added multiple times!

  1. Why can it become a one-dimensional array

Reason: in fact, the layer of dp[i - 1] is copied to dp[i].

Summary of "01 backpack" questions in LeetCode:

3. "Complete knapsack" problem

Concept: there are N items and a backpack with a maximum weight of W. the weight of the i-th item is weight[i] and the value is value[i]. Each item has an infinite number (that is, it can be put into the backpack many times). Find out which items are loaded into the backpack and the total value of the items is the largest.

The only difference between complete knapsack and 01 knapsack is that there are unlimited items of each kind.
code:

const w = [1, 3, 4];
const value = [15, 20, 30];
const n = 4; //Maximum capacity of backpack
const m = w.length; //Number of items
let dp = new Array(m + 1).fill(0).map(v => new Array(n + 1).fill(0));

for (var i = 1; i <= m; i++) {
    for (var j = 1; j <= n; j++) {
        for (var k = 0; k <= j / w[i - 1]; k++) {
            if (w[i - 1] > j) {
                dp[i][j] = dp[i - 1][j];
            } else {
                dp[i][j] = Math.max(dp[i - 1][j], k * value[i - 1] + dp[i][j - k * w[i - 1]]);
            }
        }

    }
}
console.log(dp);
// [
//     [0, 0, 0, 0, 0],
//     [0, 15, 30, 45, 60],
//     [0, 15, 30, 45, 60],
//     [0, 15, 30, 45, 60]
// ]

Optimization code: reduce the space complexity to O(n). Two dimensional array becomes one-dimensional array

Video link: Complete knapsack problem

  • The first way to write:
const w = [1, 3, 4];
const value = [15, 20, 30];
const n = 4; //Maximum capacity of backpack
const m = w.length; //Number of items
let dp = new Array(n + 1).fill(0);

for (var i = 1; i <= m; i++) {
    for (var j = n; j >= w[i - 1]; j--) {
        for (var k = 0; k <= j / w[i - 1]; k++) {
            dp[j] = Math.max(dp[j], dp[j - k * w[i - 1]] + k * value[i - 1]);
        }
    }
}
console.log(dp);
//[0, 15, 30, 45, 60]
  • The second way to write (recommended)
const w = [1, 3, 4];
const value = [15, 20, 30];
const n = 4; //Maximum capacity of backpack
const m = w.length; //Number of items
let dp = new Array(n + 1).fill(0);

for (var i = 1; i <= m; i++) {
    for (var j = w[i - 1]; j <= n; j++) {
        dp[j] = Math.max(dp[j], dp[j - w[i - 1]] + value[i - 1]);
    }
}
console.log(dp);
//[0, 15, 30, 45, 60]

Key points for the second writing method:

  • The inner loop becomes forward traversal
  • The recurrence equation is completely consistent with 01

Keywords: Javascript Algorithm leetcode Dynamic Programming

Added by tonbah on Sun, 24 Oct 2021 18:27:17 +0300