一、最长递增子序

  1. var lengthOfLIS = function(nums) {
  2. let n = nums.length
  3. if(!n) {
  4. return 0
  5. }
  6. let dp = new Array(n).fill(1)
  7. for(let i = 1;i < n; i++) {
  8. for(let j = 0;j < i; j++) {
  9. if(nums[i] > nums[j]) {
  10. dp[i] = Math.max(dp[i], dp[j] + 1)
  11. }
  12. }
  13. }
  14. return Math.max(...dp)
  15. };

二、最小编辑距离

  1. var minDistance = function(word1, word2) {
  2. let n1 = word1.length;
  3. let n2 = word2.length;
  4. let dp = new Array(n1 + 1)
  5. for (let i = 0; i < n1 + 1; i++) {
  6. dp[i] = new Array(n2 + 1).fill(0)
  7. }
  8. for (let j = 1; j <= n2; j++) {
  9. dp[0][j] = dp[0][j - 1] + 1;
  10. }
  11. for (let i = 1; i <= n1; i++) {
  12. dp[i][0] = dp[i - 1][0] + 1;
  13. }
  14. for (let i = 1; i <= n1; i++) {
  15. for (let j = 1; j <= n2; j++) {
  16. if (word1[i - 1] == word2[j - 1]){
  17. dp[i][j] = dp[i - 1][j - 1];
  18. } else {
  19. dp[i][j] = Math.min(dp[i - 1][j - 1], dp[i][j - 1], dp[i - 1][j]) + 1;
  20. }
  21. }
  22. }
  23. return dp[n1][n2];
  24. };

三、高楼扔鸡蛋

  1. //递归+动态规划
  2. var superEggDrop = function(k, n) {
  3. var map = {}
  4. var dp = function(_k, _n) {
  5. if(_k === 1) {
  6. return n;
  7. }
  8. if(_n === 0) {
  9. return 0;
  10. }
  11. let res = 0
  12. if map(_k + ',' + _n) {
  13. return map(_k + ',' + _n)
  14. }
  15. for(let i = 0;i <= _n;i++) {
  16. res = Math.min(res, Math.max(dp(_k, _n-i), dp(_k-1, i-1)) + 1)
  17. }
  18. map(_k + ',' + _n) = res
  19. return res
  20. }
  21. return dp(k, n)
  22. };
  23. //动态规划+新的转移方程
  24. let superEggDrop = function(K, N) {
  25. const dp = Array(K+1).fill(0)
  26. let res = 0
  27. while(dp[K] < N) {
  28. res++
  29. for(let i = K;i > 0;i--) {
  30. dp[i] = dp[i-1] + dp[i] + 1
  31. }
  32. }
  33. return res
  34. }

四、最长公共子序

五、最长回文子序

  1. var longestPalindromeSubseq = function(s) {
  2. let len = s.length
  3. let dp = new Array(len)
  4. for(let i = 0;i < len;i++) {
  5. dp[i] = new Array(len).fill(0)
  6. }
  7. for(let i = len-1;i >= 0;i--) {
  8. dp[i][i] = 1
  9. for(let j = i+1;j < len;j++){
  10. if(s[i] === s[j]) {
  11. dp[i][j] = dp[i+1][j-1] + 2
  12. } else {
  13. dp[i][j] = Math.max(dp[i+1][j], dp[i][j-1])
  14. }
  15. }
  16. }
  17. return dp[0][len-1]
  18. };

八、打家劫舍I

  1. var rob = function (nums) {
  2. let n = nums.length;
  3. // 记录 dp[i+1] 和 dp[i+2]
  4. let dp_i_1 = 0, dp_i_2 = 0;
  5. // 记录 dp[i]
  6. let dp_i = 0;
  7. for (let i = n - 1; i >= 0; i--) {
  8. dp_i = Math.max(dp_i_1, nums[i] + dp_i_2);
  9. dp_i_2 = dp_i_1;
  10. dp_i_1 = dp_i;
  11. }
  12. return dp_i;
  13. };

九、打家劫舍II

  1. var rob = function (nums) {
  2. let n = nums.length;
  3. if (n === 1) return nums[0];
  4. // 仅计算闭区间 [start,end] 的最优结果
  5. let robRange = function (nums, start, end) {
  6. let dp_i_1 = 0, dp_i_2 = 0;
  7. let dp_i = 0;
  8. for (let i = end; i >= start; i--) {
  9. dp_i = Math.max(dp_i_1, nums[i] + dp_i_2);
  10. dp_i_2 = dp_i_1;
  11. dp_i_1 = dp_i;
  12. }
  13. return dp_i;
  14. }
  15. return Math.max(
  16. robRange(nums, 0, n - 2),
  17. robRange(nums, 1, n - 1)
  18. )
  19. };

九、打家劫舍III

  1. var rob = function (root) {
  2. let res = dp(root);
  3. return Math.max(res[0], res[1]);
  4. };
  5. var dp = function (root){
  6. if(root == null){
  7. return [0,0];
  8. }
  9. let left = dp(root.left);
  10. let right = dp(root.right);
  11. // 抢,下家就不能抢了
  12. let rob = root.val + left[0] + right[0];
  13. // 不抢,下家可抢可不抢,取决于收益大小
  14. let not_rob = Math.max(left[0], left[1]) + + Math.max(right[0], right[1]);
  15. return [not_rob, rob]
  16. }