算法设计-分而治之&动态规划

258 阅读2分钟

分而治之

  • 分而治之是算法设计中的一种方法;(分解合
  • 将一个问题分成多个和原来问题相似的小问题,递归解决小问题,再将结果合并以解决原来的问题。 应用场景: 归并排序 、递归排序 、二分搜索 、翻转二叉树
练习题

374. 猜数字大小

// 递归版
var guessNumber = function (n) {
  const rec = (left, right) => {
    if (left > right) return;
    let mid = Math.floor((left + right) / 2);
    const num = guess(mid);
    if (num === 1) {
      return rec(mid + 1, right);
    } else if (num === -1) {
      return rec(left, mid - 1);
    } else {
      return mid;
    }
  };
  return rec(1, n);
};

// while 版本
 var guessNumber = function (n) {
   let l = 1;
   let r = n;
   while (l <= r) {
     const mid = Math.floor((l + r) / 2);
     const num = guess(mid);
     if (num === 1) l = mid + 1;
     if (num === -1) r = mid - 1;
     if (num === 0) return mid;
   }
 };

226. 翻转二叉树

 // 分: 获取左右子树
 // 解: 递归地翻转左右子树
 // 合: 将翻转后的左右子树换个位置放到跟节点上
 var invertTree = function (root) {
   if (!root) return null;
   return {
     val: root.val,
     left: invertTree(root.right),
     right: invertTree(root.left),
   };
 };

100. 相同的树

// 分:获取两个树的左子树&右子树
// 解:递归判断两个树的左子树是否相同,右子树是否相同;
// 合:将上述结果合并,如果根节点的值也相同 树就相同
 var isSameTree = function (p, q) {
   if (!p && !q) return true;
   if (
     p &&
     q &&
     p.val === q.val &&
     isSameTree(p.left, q.left) &&
     isSameTree(p.right, q.right)
   ) {
     return true;
   }
   return false;
 };

101. 对称二叉树

// 左右子树是否镜像
// 树1的左子树 和 树2的右子树是否镜像,树1的右子树和树2的左子树是否镜像;
var isSymmetric = function (root) {
  if (!root) return true;
  const rec = (rootL, rootR) => {
    if (!rootL && !rootR) return true;
    if (
      rootL &&
      rootR &&
      rootL.val === rootR.val &&
      rec(rootL.left, rootR.right) &&
      rec(rootL.right, rootR.left)
    ) {
      return true;
    } else {
      return false;
    }
  };
  return rec(root.left, root.right);
};

动态规划

  • 将一个问题分解为相互重叠的子问题,通过反复求解子问题,来解决原来的问题。
  • 和动态规划的区别:子问题是否独立,独立的是动态规划,重复的是分而治之;
  • 公式:(1)定义子问题,Fn = F(n-1)+F(n-2); (2)反复执行:从2循环到N,执行上述公式;

70. 爬楼梯

// 爬到第n阶可以在n-1阶爬1个台阶,或者在n-2爬两个台阶;
//  Fn = F(n-1)+F(n-2);
  var climbStairs = function (n) {
    if (n < 2) return 1;
    let dp = [1, 1];
    for (let i = 2; i <= n; i++) {
      dp[i] = dp[i - 1] + dp[i - 2];
    }
    return dp[n];
  };
// 优化空间复杂度
var climbStairs = function(n) {
    if (n===1) return 1;
    let step1 = 1;
    let step2 = 1;
    for (let i = 2; i<=n; i++ ) {
        let temp = step1;
        step1 = step2;
        step2 += temp;
    }
    return step2;
};

198. 打家劫舍

// f(k) = 从前k个房屋中能偷窃到的最大的数额;
// AK =  第K个房屋的钱数
// f(k) = max(f(k-2)+AK,f(k-1))
var rob = function(nums) {
    if (nums.length===0) return 0;
    const dp = [0,nums[0]];
    for (let i = 2; i<=nums.length;i++){
        dp[i] = Math.max(dp[i-2]+nums[i-1],dp[i-1]);
    }
    return dp[dp.length-1];
};