【二分查找】求解单调方程的解 C++实现

文章介绍了如何利用二分查找算法解决寻找单调递增函数f(x)=ax(a>1)的正整数解x,当给定正整数N。首先提出将x=logaN作为初始猜测,然后通过二分查找在[0,N]范围内找到满足条件的解。文章提供了伪代码和C++实现,并包含递归与迭代两种二分查找形式。
摘要由CSDN通过智能技术生成

1 问题

  有函数 f ( x ) = a x ( a > 1 ) f(x)=a^x(a>1) f(x)=ax(a>1) ,单调递增,现在给一个正整数 N N N,求使得 f ( x ) = N f(x)=N f(x)=N的正整数解 x x x
  

2 想法

  1. x = l o g a N x=log_a^N x=logaN 很干净利索,但这样得到的是一个浮点数,需要判断 x x x是不是正整数。注意:例子特殊,并不是所有的递增函数都有直接解。
  2. 0 , 1 , 2 , 3 … … 0,1,2,3…… 0,1,2,3……开始试验,如果 a i < N < a i + 1 a^{i}<N<a^{i+1} ai<N<ai+1 ,说明无解,如果 a i = N a^{i}=N ai=N,那么 i i i就是解。
  3. 考虑单调性,从小到大去试验时,如果当前值i满足 a i > N a^{i}>N ai>N,后面一定都大于 N N N,说明无解。
  4. 考虑边界值,注意到 x x x 的值最小0,最大不超过N,即 x ∈ [ 0 , 1 , 2... , N ] x\in [0,1,2...,N] x[0,1,2...,N],逻辑等价于数组下标,可以使用二分查找。

3 二分查找

  最常见的,一个严格单调递增有序数列,查找是否存在某一个值。可以先找中间,每次放弃一半,效率 O ( l g N ) O(lgN) O(lgN)
  有两个明显特征:

  1. 有明显边界且是有限个数。
  2. 满足单调性。

  递归与迭代形式

function binary-search(x,A,l,r)
	if l>r then 
		not found error
	else
		m = l+floor((r-l)/2)  # (l+r)/2可能会溢出
		if A[m] = x then
			return m
		if A[m] > x then 
			return binary-search(x,A,l,m-1)
		else
			return binary-search(x,A,m+1,r)

# 递归修改边界
function binary-search(x,A,l,r)
	while(l<r)
		m = l+floor((r-l)/2)  # (l+r)/2可能会溢出
		if A[m] = x then
			return m
		if A[m] > x then 
			r=m-1
		else
			l=m+1
	return NIL

4 实现

   注意,为了一般化单调递增函数或者数列,我们把 f ( x ) f(x) f(x)作为参数传入。

4-1 伪代码说明

function bisearch(f,N,l,r):	
	if l<r then
		error
	else
		m = l+floor((r-l)/2)
		y = f(m)
		if y == N then
			return m
		if y > N then
			return bisearch(f,N,l,m-1)
		else
		 	return bisearch(f,N,m+1,r)

4-2 C++11

#include <iostream>
#include <vector>
#include <functional>//function 模板
#include <cmath> //floor()

using namespace std;
#define see(x) cout << x << endl
#define see2(x, y) cout << (x) <<"\t"<< (y) << endl

class Solution
{
    using T=size_t;
    using incFunc=function<size_t(size_t)>;
public:
    static T expA(T x){
        T ans=1;
        T a=5;
        while(x--){
            ans*=a;
        }
        return ans;
    }
    T biSearch(incFunc f,T N,T l,T r){
        if(l>r){
            cerr<<"error"<<endl;
            return 0;
        }else{
            T m=l+floor((r-l)/2);
            T y=f(m);
            if(y ==N) return m;
            if(y > N) return biSearch(f,N,l,m-1);
            else return biSearch(f,N,m+1,r);
        }
    }
    void test()
    {
        T ans=biSearch(expA,125,0,125);
        if(ans==3){
            see("accept!!!");
        }else{
            see("error....");
        }
    }      
};

int main()
{
    Solution sol;
    sol.test();
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值