习题2-3改写二分搜索算法

设a[0:n-1]是已排好序的数组,请改写二分搜索算法,使得当x不在数组中时,返回小于x的最大元素位置i和大于x的最小元素位置j。当搜索元素在数组中时,i和j相同,均为x在数组中的位置。

template <class T>
int binarySearch(T a[],const T&x,int left,int right,int &i,int &j){
    int middle;
    while(left<=right){
        middle=(left+right)/2;
        if(x==a[middle]){i=j=middle;return 1;}
        if(x>a[middle]) left=middle+1;
        else right=middle-1;
        }
    i=right;
    j=left;
    return 0;
}
<think>好的,用户让我深入讲解动态规划,并且要通俗易懂,还要举例子。首先,我需要回顾一下动态规划的基本概念,确保自己理解正确。动态规划通常用于解决具有重叠子问题和最优子结构的问题,通过将问题分解为更小的子问题,并存储这些子问题的解来避免重复计算,从而提高效率。 接下来,我需要考虑如何通俗地解释这个概念。可能需要用日常生活中的例子,比如爬楼梯或者找零钱,这些都是常见的例子。用户可能对算法有一定了解,但需要更直观的理解,所以例子要简单明了。 然后,我需要确定用户的需求层次。用户可能在学习算法,遇到了动态规划的难点,或者在做题时遇到困难,想要一个清晰的解释。因此,除了基本概念,还要强调动态规划的应用场景和解决问题的步骤,比如如何定义状态、状态转移方程、初始条件和计算顺。 还要注意结构,分步骤讲解,这样用户更容易跟随。比如,先讲递归的缺点,再引入动态规划如何优化,通过存储中间结果来减少计算量。然后通过例子具体说明,比如斐波那契数列或者背包问题,但可能背包问题对初学者来说有点复杂,所以选择更简单的例子,比如爬楼梯问题。 在举例子时,要详细展示递归解法的问题,比如重复计算,然后展示动态规划如何通过数组存储中间结果来优化。可能需要对比两种方法的时间复杂度,说明动态规划的优势。 另外,用户可能希望了解动态规划的应用场景,所以在例子之后,可以列举几个典型的问题,如最短路径、最长公共子列等,帮助用户识别何时使用动态规划。 最后,总结动态规划的关键点,确保用户理解其核心思想:记住已解决的子问题,避免重复计算。同时提醒用户需要多练习,培养分解问题的能力。 现在,检查是否有遗漏的部分,比如动态规划与分治法的区别,或者是否提到了自底向上和自顶向下的方法(记忆化搜索)。可能需要在解释中提到这些,但保持简洁,避免让用户感到混乱。 确保语言口语化,避免专业术语堆砌,用比喻或类比帮助理解。比如,把动态规划比作做笔记,避免重复工作。整个过程需要逻辑清晰,逐步引导用户理解动态规划的思想和应用。</think>动态规划(Dynamic Programming)是一种通过 **将复杂问题分解为子问题** 并 **记录中间结果** 来优化计算的算法思想。我们可以用生活中的「记账本」来理解它:遇到重复计算时直接查账,而不是重新计算。 --- ### **核心思想三要素** 1. **重叠子问题**:大问题可拆解为多个重复出现的小问题 2. **最优子结构**:大问题的最优解包含子问题的最优解 3. **状态转移方程**:定义子问题之间的关系式 --- ### **经典案例:爬楼梯** **问题**:每次爬12阶台阶,求到达第n阶的不同方式总数 #### 传统递归的缺陷 ```python def climb(n): if n <= 2: return n return climb(n-1) + climb(n-2) # 产生指数级重复计算 ``` 当计算climb(5)时,climb(3)会被重复计算2次,climb(2)重复3次(如下图树状展开) #### 动态规划解法 ```python def climb_dp(n): if n <= 2: return n dp = [0]*(n+1) # 创建记账本 dp[1], dp[2] = 1, 2 # 初始条件 for i in range(3, n+1): dp[i] = dp[i-1] + dp[i-2] # 状态转移方程 return dp[n] ``` 通过数组存储中间结果,将时间复杂度从 **O(2ⁿ)** 降为 **O(n)**,空间复杂度保持O(n) #### 空间优化版(滚动数组) ```python def climb_dp_opt(n): if n <= 2: return n a, b = 1, 2 for _ in range(3, n+1): a, b = b, a+b # 仅保留前两个状态 return b ``` 将空间复杂度优化到 **O(1)** --- ### **动态规划四步法** 1. **定义状态**:明确dp数组的含义(如dp[i]表示第i阶的方案数) 2. **建立方程**:找出dp[i]与dp[i-1]等前项的关系 3. **定初值**:确定计算的起点(如dp[1]=1) 4. **计算顺**:确定遍历方向(如从低到高递推) --- ### **更多典型场景** 1. **背包问题**:物品价值最大化 - 状态转移:`dp[i][w] = max(选当前物品,不选当前物品)` 2. **最长公共子列** - 状态转移:字符相同时`dp[i][j]=dp[i-1][j-1]+1`,否则取`max(dp[i-1][j], dp[i][j-1])` 3. **股票买卖问题** - 定义多维状态:`dp[i][持有状态][交易次数]` --- ### **思维训练建议** - 从二维网格路径类问题入门(如机器人寻路) - 尝试将递归解法改写成动态规划版本 - 学习「剪枝」技巧优化空间复杂度 - 注意区分「自顶向下」(记忆化搜索)与「自底向上」(传统DP)的实现差异 通过这种「记账-查账」的模式,动态规划能有效解决很多看似复杂的优化问题,是算法计中的重要思想工具。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值