题目描述:

You are a given a unimodal array of n distinct elements, meaning that its entries are in increasing order up until its maximum element, after which its elements are in decreasing order. Give an algorithm to compute the maximum element that runs in O(log n) time.

输入格式:

An integer n in the first line, 1<= n <= 10000. N integers in the seconde line seperated by a space, which is a unimodal array.

输出格式:

A integer which is the maximum integer in the array

输入样例:

7
1 2 3 9 8 6 5
 
结尾无空行

输出样例:

9
 
结尾无空行
 
 
 

分析:

•此题关键词:单峰数组、峰值(最大值)、递增、递减  时间复杂度O(log n)

•题目要求找出单峰数组的最大值所在位置,并返回它的值

思路:

题目很简单,要求时间复杂度为O(log n),所以采用二分搜索的方法,一边判断mid下标所在的元素值是否比左边和右边都大,一边递归调用方法缩小查找范围,直到找到元素。

 


代码:

复制代码
#include <bits/stdc++.h>
using namespace std;


int binary_sort(int start, int end, int a[]){
    int mid = (start + end)/2;
    if(start > end) return -1;
    if(a[mid] >= a[mid - 1] && a[mid] >= a[mid + 1]) return mid;
    else if(a[mid] > a[mid - 1] && a[mid] < a[mid + 1])return binary_sort(mid + 1, end, a);
    else if(a[mid] < a[mid - 1] && a[mid] > a[mid + 1])return binary_sort(start, mid, a);
} 

int main()
{
    int n, a[10000];
    cin >> n;
    for(int i = 0; i < n; i++){
        cin >> a[i];
    }
  int flag = binary_sort(0, n - 1, a);
     cout << a[flag] << endl;
    return 0;
}
复制代码

时间复杂度:

问题的规模为n,二分搜索时间复杂都为O(log n),递归的每层仅作一次判,断时间复杂度O(1),所以总的 时间复杂度为O(log n)。

 

总结:

 

二分实质上是分治思想的体现,当然只有在相对有序的数组里才能用二分(一般是递增或是递减数组,本题为先递增后递减),在查找的同时逐步缩小查找范围(每次都减半)。
 

7-2 二分法求函数的零点 (30 分)

题目描述:

  • 有函数:f(x)=x5−15x4+85x3−225x2+274x−121 已知f(1.5)>0,f(2.4)<0 且方程f(x)=0 在区间[1.5,2.4] 有且只有一个根,请用二分法求出该根。
  • 提示:判断函数是否为0,使用表达式 fabs(f(x)) < 1e-7

输入格式:

无。

输出格式:

该方程在区间[1.5,2.4]中的根。要求四舍五入到小数点后6位。。

输入样例:

 
结尾无空行

输出样例:

 
结尾无空行

分析:

•此题关键词:f(1.5)>0,f(2.4)<0     有且只有一个根   二分法   fabs(f(x)) < 1e-7

•题目要求找到并输出根的值(注意小数点后几位)

思路:

题目不难,带入区间中值mid计算与0的差值是否在1e-7以内,如果是则跳出递归,返回mid值,若不在范围内则通过正负来判断mid在零点左侧还是在零点右侧,若为正则在零点左侧,向右侧递归,反之则向左侧递归。


 

代码:

 

复制代码
 1 #include <iostream>
 2 #include <cmath>
 3 #include <iomanip>
 4 using namespace std;
 5 
 6 double f(double x)
 7 {
 8     return (pow(x,5) - 15*pow(x,4) + 85*pow(x,3) - 225*pow(x,2) + 274*x - 121);
 9 }
10 
11 double binary_sort(double start, double end)
12 {
13 //    cout << start << " " << end << endl;
14 //    getchar();
15     double mid = (start + end)/2.000000;
16     if(fabs(f(mid)) < 1e-7) return mid;
17     else if(f(mid) > 0) binary_sort(mid, end);
18     else if(f(mid) < 0) binary_sort(start, mid);
19 } 
20 
21 int main()
22 {
23     double start = 1.5, end = 2.4;
24     double flag = binary_sort(start, end);
25     cout << fixed << setprecision(6) << flag << endl;
26     return 0;
27 }
复制代码

 

时间复杂度:

本题没有输入输出,时间复杂度为O(1)

总结:

分治思想,写递归函数的时候先写结束条件,有返回值的返回,不符合返回条件则返回递归函数本身(参数不一样)


 

心得体会:

不论是递归还是二分,都是在将原问题拆分成规模更小、更容易解决的子问题,这体现的就是分治思想,这对规模较大的问题和数据处理提供了一条省时间、省空间的解决方法。

 

分治法个人体会与思考:

 

实际上分治法就是类似于数学归纳法,找到解决本问题的求解方程公式,然后根据方程公式设计递归程序。

 

1、一定是先找到最小问题规模时的求解方法。

 

2、然后考虑随着问题规模增大时的求解方法。

 

3、找到求解的递归函数式后(各种规模或因子),设计递归程序。

 

有时候解决问题不是在于问题很难,而是在于问题的规模很大,让人难以判断从何处着手。如果能够让 数据以某种规律性质排列,找到 一个值将问题划分为几块,逐渐将问题化繁为简,最后在合并回到原来,问题就会迎刃而解。

posted on 2021-09-28 20:05  Aheador  阅读(83)  评论(0编辑  收藏  举报