三分法 讲解

本文介绍了三分法在求解凸性或凹性函数极值时的应用,通过调整搜索区间缩小极值点的范围,进而准确求得函数的最大或最小值。以 LightBulb 问题为例,演示了如何将理论应用于实际编程解决,包括输入输出规范和代码模版。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二分法适用于求单调的时候用的,就比如说排序好的数组,那是递增的或者递减的。如果像出现了下图二次函数那样的怎么求他的最值呢?

        二分法早就失去了他的意义了。不过还是可以用三分法来实现的,就是二分中再来二分。比如我们定义了LRm = (L + R) / 2mm = (mid + R) / 2; 如果mid靠近极值点,则R = mm;否则就是mm靠近极值点,则L = m;这样的话,极值还是可以求的。具体的还是看看题目吧。

三分查找的算法,对于求凸性或凹性函数的极值非常方便

 

模版 :

 

 1 double  solve(double l,double r)
 2 {
 3 
 4         double mid,midmid;
 5         while(r - l > eps)
 6         {
 7               mid = (l + r)/2.0;
 8              midmid = (r + mid)/2.0;
 9 
10 
11             if(f(mid) <= f(midmid))// f 就算函数值
12                 r = midmid;
13             else  l = mid;
14         }
15     return f(l);
16 }

 

只要知道 函数怎么求 ,套模版就可以了 ;

zoj  3203    Light Bulb  

Light Bulb

Time Limit: 1 Second      Memory Limit: 32768 KB

Compared to wildleopard's wealthiness, his brother mildleopard is rather poor. His house is narrow and he has only one light bulb in his house. Every night, he is wandering in his incommodious house, thinking of how to earn more money. One day, he found that the length of his shadow was changing from time to time while walking between the light bulb and the wall of his house. A sudden thought ran through his mind and he wanted to know the maximum length of his shadow.

Input

The first line of the input contains an integer T (T <= 100), indicating the number of cases.

Each test case contains three real numbers H, h and D in one line. H is the height of the light bulb while h is the height of mildleopard. D is distance between the light bulb and the wall. All numbers are in range from 10-2 to 103, both inclusive, and H - h >= 10-2.

Output

For each test case, output the maximum length of mildleopard's shadow in one line, accurate up to three decimal places..

Sample Input

3
2 1 0.5
2 0.5 3
4 3 4

Sample Output

1.000
0.750
4.000

 

 

 

 

View Code
 1 #include<stdio.h>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<queue>
 7 #include<set>
 8 #include<map>
 9 #define Min(a,b)  a>b?b:a
10 #define Max(a,b)  a>b?a:b
11 #define CL(a,num)  memset(a,num,sizeof(a));
12 #define inf 9999999
13 #define maxn 50010
14 #define eps  1e-6
15 #define ll long long
16 using namespace std;
17 double a[maxn],w[maxn];
18 double   H,h,d;
19 double f(double pos)
20 {
21      return  ((d - pos)*h - (H - h)*pos)/(d - pos) + pos;
22 
23 }
24 double  solve(double l,double r)
25 {
26 
27         double mid,midmid;
28         int size = 100;
29         while(size--)
30         {
31               mid = (l + r)/2.0;
32              midmid = (r + mid)/2.0;
33 
34 
35             if(f(mid) >= f(midmid))// f 就算函数值
36                 r = midmid;
37             else  l = mid;
38         }
39     return f(l);
40 }
41 int main()
42 {
43     int t,i;
44     scanf("%d",&t);
45     int cas = 0;
46 
47     while(t--)
48     {
49         double ans = 0 ;
50        scanf("%lf %lf %lf",&H,&h,&d);
51 
52 
53        ans = solve(0,d*(h/(H*1.0)));
54        printf("%.3lf\n",ans );
55     }
56 }

 

 

 

 

转载于:https://www.cnblogs.com/acSzz/archive/2012/08/10/2631903.html

<think>我们被要求详细解释二分查找算法的原理和实现方式。根据引用内容,二分查找是一种在有序数组中查找特定元素的高效算法,时间复杂度为O(log n)。其基本思想是每次将搜索范围减半,直到找到目标元素或范围为空。 原理步骤: 1. 确定数组的中间位置mid 2. 比较中间元素与目标值: - 若相等,则找到目标,返回索引 - 若目标值小于中间元素,则在左半部分继续查找 - 若目标值大于中间元素,则在右半部分继续查找 3. 重复上述过程,直到找到目标或搜索区间为空 实现时需注意: - 循环终止条件:low <= high 还是 low < high? - 中间位置计算:mid = (low+high)//2 还是 mid = low + (high-low)//2(避免溢出)? - 边界更新:low = mid+1 或 high = mid-1,避免死循环 下面用Python实现一个基本的二分查找(查找一个数): ```python def binary_search(arr, target): low, high = 0, len(arr) - 1 while low <= high: mid = low + (high - low) // 2 # 避免溢出 if arr[mid] == target: return mid elif arr[mid] < target: low = mid + 1 else: high = mid - 1 return -1 # 未找到 ``` 对于查找边界(左边界或右边界)的情况,实现略有不同。例如,查找左边界(第一个等于目标的位置): ```python def left_bound(arr, target): low, high = 0, len(arr) - 1 while low <= high: mid = low + (high - low) // 2 if arr[mid] < target: low = mid + 1 else: # 当arr[mid]>=target时,收缩右边界 high = mid - 1 # 检查low是否越界,且low位置的值是否等于target if low < len(arr) and arr[low] == target: return low return -1 ``` 右边界(最后一个等于目标的位置): ```python def right_bound(arr, target): low, high = 0, len(arr) - 1 while low <= high: mid = low + (high - low) // 2 if arr[mid] <= target: low = mid + 1 else: high = mid - 1 # 检查high是否越界,且high位置的值是否等于target if high >= 0 and arr[high] == target: return high return -1 ``` 注意:边界查找的实现中,循环结束后需要额外检查索引的有效性。 二分查找的前提是数组有序。对于无序数组,需要先排序(时间复杂度O(n log n)),因此如果只进行一次查找,直接顺序查找可能更高效;但若多次查找,排序后使用二分查找更优。 二分查找的变体较多,需根据具体问题调整。例如,在旋转有序数组中查找、查找峰值等。 参考文献: [^1] 介绍了二分查找的原理和Python实现。 [^2] 提到二分查找的基本原理和高效性(O(log n))。 [^3] 强调了二分查找的细节问题,并区分了三种常用场景。 [^4] 展示了二分查找前需要排序的例子。 §§相关问题§§ 1. 二分查找算法在什么情况下会退化为线性时间复杂度? 2. 如何处理重复元素时的二分查找? 3. 二分查找算法有哪些常见的变体?</think>### 二分查找算法原理及实现详解 #### 算法原理 二分查找(Binary Search)是一种针对**有序数组**的高效搜索算法,核心思想是**分治策略**: 1. **比较中间元素**:取数组中间位置元素 $mid$ 与目标值比较 2. **缩小搜索范围**: - 若 $target = arr[mid]$,找到目标 - 若 $target < arr[mid]$,在左半区间 $[low, mid-1]$ 继续搜索 - 若 $target > arr[mid]$,在右半区间 $[mid+1, high]$ 继续搜索 3. **重复分治**:每次将搜索范围减半,直到找到目标或区间为空 **时间复杂度**:$O(\log n)$,空间复杂度:$O(1)$ **前提条件**:数组必须有序(升序或降序)[^1][^2] #### 关键实现细节 1. **循环条件**:`while low <= high`(确保区间有效) 2. **中间值计算**:`mid = low + (high - low) // 2`(避免整数溢出) 3. **边界更新**: - 目标较小时:`high = mid - 1` - 目标较大时:`low = mid + 1` #### Python 代码实现 ```python def binary_search(arr, target): low, high = 0, len(arr) - 1 while low <= high: mid = low + (high - low) // 2 # 防溢出计算 if arr[mid] == target: return mid # 找到目标,返回索引 elif arr[mid] < target: low = mid + 1 # 目标在右半区 else: high = mid - 1 # 目标在左半区 return -1 # 未找到 ``` #### 边界查找变体 1. **左边界查找**(第一个等于目标的元素): ```python def left_bound(arr, target): low, high = 0, len(arr) - 1 while low <= high: mid = low + (high - low) // 2 if arr[mid] >= target: high = mid - 1 else: low = mid + 1 return low if low < len(arr) and arr[low] == target else -1 ``` 2. **右边界查找**(最后一个等于目标的元素): ```python def right_bound(arr, target): low, high = 0, len(arr) - 1 while low <= high: mid = low + (high - low) // 2 if arr[mid] <= target: low = mid + 1 else: high = mid - 1 return high if high >= 0 and arr[high] == target else -1 ``` #### 算法特性对比 | **操作类型** | **循环条件** | **边界更新逻辑** | **返回值验证** | |--------------|--------------|---------------------------|-------------------------| | 基本查找 | `low <= high`| 严格大小比较 | 直接返回 mid | | 左边界查找 | `low <= high`| 使用 `>=` 收缩右边界 | 检查 low 位置 | | 右边界查找 | `low <= high`| 使用 `<=` 扩展左边界 | 检查 high 位置 | > 关键提示:二分查找的难点在于**边界条件处理**,需特别注意: > - 终止条件(避免死循环) > - 索引越界检查 > - 重复元素的边界处理[^3] #### 应用场景 1. 有序数组的快速检索 2. 数值范围查询(如IP地址定位) 3. 数学问题求解(如平方根近似计算) 4. 数据库索引优化(B+树底层机制)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值