zoukankan      html  css  js  c++  java
  • pat每日刷题计划--day70

    二分法

    • binarySearch找的是出现在a数组中的,数值等于num的数的下标。(有多个的时候是随机的输出了一个)
    • lowerbound找的是在a数组中出现的第一个,数值大于等于num的数的下标
    • upperbound找的是a数组中出现的第一个,数值大于num的数的下标

    找具体的某个数,是使用mid进行判断,而另外的两个是使用的left和right夹逼。

    也正是因此,根据定义可以判断,在binarySearch中,不是对应返回值的a[mid]里面一定不包含正确答案,所以在转移的过程中不需要带上mid

    在递增序列里面,binarySearch在a[mid]变迁:

    • a[mid]==num ----> return mid
    • a[mid]>num  ----> right=mid-1
    • a[mid]<num  ---->left=mid+1
    • 判定条件:left<=right,(只要mid,left,right都是合法的就有可能,因此需要带上等号)

    而在lowerbound中,最终的一个位置是left==right,然后返回left的下标,在走完数组之前,并不知道当前的位置是真正的第一个。

    • a[mid]>=num  ----> 结果一定在[left,mid]中,right=mid
    • a[mid]<num ---->可以确定mid处是不可能的,所以left=mid+1
    • 循环条件:left<right 因为这样最后一次出来的是left=right

    在upperbound中,最终也是left==right

    • a[mid]>num ---->结果一定在[left,mid]中,right=mid
    • a[mid]<=num ---->mid是不在范围内的,left=mid+1
    • 循环判定:left<=right,最终以left=right退出循环

    lowerbound和upperbound都可以被称为:寻找有序序列中第一个满足某条件元素的位置,只要设置好对应的边界判定就可以完成转换

    binarySearch对应的判断问题是:判断一个有序序列中是否存在某个元素,如存在找出位置

    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    using namespace std;
    int binarySearch(int a[],int left,int right,int num)//找出num在a数组的位置
    {
        int mid=(left+right)/2;
        while(left<=right)
        {
            mid=(left+right)/2;
            if(a[mid]==num)
                return mid;
            if(a[mid]>num)
                right=mid-1;
            else
                left=mid+1;
        }
        return -1;
    }
    int lowerbound(int a[],int left,int right,int num)//找出大于等于num的第一个数在a数组的位置
    {
        int mid=(left+right)/2;
        while(left<right)
        {
            mid=(left+right)/2;
            if(a[mid]>=num)
            {
                right=mid;
            }
            else
                left=mid+1;
        }
        return left;
    }
    int upperbound(int a[],int left,int right,int num)//找出第一个大于num的数在a数组中的位置
    {
        int mid=(left+right)/2;
        while(left<right)
        {
            mid=(left+right)/2;
            if(a[mid]>num)
                right=mid;
            else
                left=mid+1;
        }
        return left;
    }
    int main()
    {
        int n=5;
        int a[15]={1,3,3,3,6};
        /*for(int i=0;i<n;i++)
            scanf("%d",&a[i]);*/
        printf("%d
    ",binarySearch(a,0,n-1,3));
        printf("%d
    ",lowerbound(a,0,n-1,3));
        printf("%d
    ",upperbound(a,0,n-1,3));
        return 0;
    }
    View Code

     二分法求根号2近似(精确到1e-5)

    注意这里面具体数字,直接等于mid就行,不用加减

    left和right对应的是根号2的范围,然后mid*mid对应的是根号2平方以后的范围。

    (比如换成根号3,left和right还是1和2(根号三大于1小于2),mid*mid是对应的3)

    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    using namespace std;
    int main()
    {
        double left=1;
        double right=2;
        double eps=1e-5;
        double mid=(left+right)/2;
        while(right-left>eps)
        {
            mid=(right+left)/2;
            if(mid*mid==2)
            {
                printf("%f",mid);
            }
            if(mid*mid>2)
                right=mid;
            else
                left=mid;
        }
        printf("%f",mid);
        return 0;
    }
    View Code
    时间才能证明一切,选好了就尽力去做吧!
  • 相关阅读:
    2981 大整数加法
    1160 矩阵的最大值(指针专题)
    1159 最大的两个数(指针专题)
    1127 矩阵乘积
    1126 布尔矩阵的奇偶性
    1125 上三角矩阵的判断
    1124 两个有序数组合并
    1123 最佳校友
    1122 小明的调查作业
    1121 电梯
  • 原文地址:https://www.cnblogs.com/tingxilin/p/12241755.html
Copyright © 2011-2022 走看看