分治&递归

递归

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

递归出口(边界条件)----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;
}
}
相关推荐
明志数科20 分钟前
具身智能数据工程全链路解析:从真实产线采集到LeRobot适配
网络·人工智能·算法
小O的算法实验室29 分钟前
AAAI-26,Lehmer编码搜索排列空间的理论与实证分析
算法
Capricorn198831 分钟前
科研引用无法溯源怎么排查?知芽 Notebook Skill 技术机制拆解
大数据·论文阅读·人工智能·笔记·论文笔记
lch2011_yb32 分钟前
CSP-S 2023 密码锁 题解
算法
牛油果子哥q1 小时前
C++ Socket精讲:TCP/UDP套接字、客户端服务端实现、字节序、粘包拆包、简单HTTP服务、网络踩坑与面试全解
网络·c++·tcp/ip
程与留1 小时前
12_常用控件速查(下):QSpinBox、QSlider、QProgressBar、QCheckBox
c++·qt
Capricorn19881 小时前
Agent 记忆层接入后引用仍不可信?知芽 Notebook Skill 排障指南
大数据·论文阅读·人工智能·笔记·架构
自小吃多1 小时前
PCB Editor放置元器件笔记
笔记·嵌入式硬件
OPEN-F1 小时前
C++进阶教程:运算符重载与类型转换
java·c++·算法