分治&递归

递归

将一个大问题分解成多个和大问题逻辑相同的子问题

递归出口(边界条件)----TLE /RE 找全递归终止条件 ---经验

递归代码的理解:画递归调用图-带一个比较小的值进去,你手动画一下它的执行和返回过程

从哪个地方调用就返回到哪里

怎么写一个递归函数:确定递归函数是干什么的,在写代码的过程中,只考虑当前的问题

怎么解决,不分析下层的递归怎么展开

递归函数用来解决这些类似的小问题的----->确定递归函数能解决什么问题

在写递归函数时,当我们需要用到类似小问题的答案的时候,直接调用递归函数

汉诺塔问题:归纳,找规律

n时,可以把上面n-1个盘子看成一个整体

此时 一:把n-1个盘子从A移动到B,C当作媒介-----递归

二: n-1 B C A

递归函数:4个参数 (盘子数量x,起点柱子s,终点柱子e ,媒介柱子h) x个盘子---->s---h---->e

错误案例:

//错误:1.没有递归出口 2.start和end放着起不了任何作用,应该用个数n

3.引用传参,修改不了A,C

正确:

void move(int s,int e,int h,int n) A C B n

{ //递归出口 :当只有一个盘子时直接放到e

if(n==1) move n s---->e; return;

move(A,B,C,n-1);

move n s---->e ;

move(B,C,A,n-1);

}

递归和动态规划,分治的区别: 最优子结构(可以分解成若干个小问题)

1.递归不是算法,是一种编程技巧,很多算法(只要满足最优子结构)都可以用递归来写

2.动态规划和分治

动态规划具有最优子结构(可以分解成若干个小问题) 和 重叠子问题的特点 也就是说分成的每个小问题之间不是相互独立的,

求解小问题3需要用到小问题1和小问题2的答案

而分治:也具有最优子结构 但是小问题之间独立, 并且小问题之间的处理逻辑也不一定相同

总结:相同之处是都具有最优子结构特点

如果小问题存在重叠,或者处理逻辑都是一样的---->动态规划

如果小问题的处理逻辑不完全相同,那相同的可以写个递归代码,不同的单独给它写一个函数或代码

也就是说解决一个题目可能要你自己写三个函数

分治

例题1:53. 最大子数组和 - 力扣(LeetCode)

分治法来做:

cpp 复制代码
class Solution {
public:
 int tanxin(vector<int>& nums,int l,int r,int mid)
{
  //start = nums[mid];
  /*
  //找以mid为右边界,左边的最大值
  res = 0; p = 0;
  for (int i = mid - 1; i >= l; i--)
  {
    p += nums[i];
    res = max(res, p);
  }
  start += res;

  //找以mid为左边界,右边的最大值
  res = 0, p = 0;
  for (int i = mid+1; i<=r; i++)
  {
    p += nums[i];
    res = max(res, p);
  }
  start += res;

  */

  //错啦,懂什么叫做横跨吗?左边和右边至少要有一个数据...那么就不要start,直接求左右最大值
   int lval= INT_MIN; //保证至少能取到一个值
   int p = 0;

  for (int i = mid; i >= l; i--)
  {
    p += nums[i];
    lval = max(lval, p);
  }

  int rval = INT_MIN;
  p = 0;
  for (int i = mid+1; i<=r; i++)
  {
    p += nums[i];
    rval = max(rval, p);
  }
  return rval + lval;
}

int fenzhi(vector<int>& nums,int l,int r)
{
  if (l == r) return nums[l]; //递归出口

  int mid = (l + r) / 2;
   //拆分成l~mid,mid+1~r
  int lans = fenzhi(nums, l, mid);
  int rans = fenzhi(nums, mid + 1, r);

  //横跨的情况单独写个函数
  int mans = tanxin(nums,l,r,mid);
  return max(max(lans, rans), mans);
}

//返回连续子数组的最大值
int maxSubArray(vector<int>& nums) { //
  return fenzhi(nums, 0, nums.size() - 1);
}
};

动态规划来做:

cpp 复制代码
class Solution {
public:
int dp[100005]; //以下标i结尾的连续子数组的最大和是

//降维优化: dp[n]只与dp[n-1]有关
int dp;
//不论哪个序列都是以数组nums中的数结尾的
int maxSubArray(vector<int>& nums) {
   dp=nums[0];
   int ans=nums[0];
   for(int i=1;i<nums.size();i++)
   {
      dp=dp>0?dp+nums[i]:nums[i];
      ans=max(dp,ans);
   }
    return ans;
}
}
相关推荐
Ada's3 小时前
【计算机基础系列】003:Python数据结构
开发语言·数据结构·python
Nil2084 小时前
leetcode 118杨辉三角
算法·leetcode·职场和发展
NeilYuen6 小时前
【C++】STL源码仿写(二):vector
开发语言·c++
郝学胜_神的一滴6 小时前
游戏引擎原理与实践 04:拆解引擎基础系统与内存管理
c++·游戏
wanderist.7 小时前
线性筛法详解:从筛质数到欧拉函数、Möbius 函数与约数函数
java·数据结构·算法
All for pursuit.7 小时前
【设计-1】208.实现Trie (前缀树)
数据结构·c++·算法·leetcode
weixin_307779137 小时前
C++代码实现MATLAB中的crossval函数功能
开发语言·c++·算法·matlab
青少儿编程课堂7 小时前
背包问题(0/1 背包与完全背包)解题精讲——动态规划入门
c++·python·算法·bfs·信息学竞赛
倒头就睡的小比特7 小时前
C++多态
c++
光影少年8 小时前
为什么 JavaScript 中 0.1 + 0.2 !== 0.3,如何让其相等?
前端·javascript·算法