分治法--二分查找、乘方、斐波那契数

1、二分查找


常见错误:

  • 死循环:循环体外的初始化条件,与循环体内的迭代步骤,
    都必须遵守一致的区间规则,也就是说,如果循环体初始化时,是以左闭右开区间为边界的,那么循环体内部的迭代也应该如此.如果两者不一致,会造成程序的错误.

  • 溢出:middle = left + (right - left) / 2

  • 终止条件:一般来说,如果左闭右闭,则left<=right; 如果一开一闭,则left<right;
    关键看left能不能等于right,而且要考虑实际情况,有时不能这样简单终结,会出现死循环,如下面的binarySearch_better()。

running time analysis:T(n) = T(n/2) +
 Θ(1) ---> T(n)
= Θ(lgn)

正确算法:

 1 //normal binarySearch without optimization, closed interval, return value is mid(maybe mid=left=right)
2 int binarySearch(int a[], int n, int k){
3 if(n<1) return -1;
4
5 int left,right,mid;
6 left = 0; //closed left
7 right = n-1; //closed right
8
9 while( left<=right ){
10 mid = left+(right-left)/2;
11
12 if( a[mid]<k ) left = mid+1;
13 else if( a[mid]>k ) right = mid-1;
14 else return mid;
15 }
16 return -1;
17 }

减少比较次数为1次

//more efficient way, left closed right away interval, return value is mid=left
int binarySearch_better(int a[], int n, int k){
if( n<1 ) return -1;

int left,right, mid;
left = 0; //closed left
right = n; //open right

while( left+1!=right ){
mid = left+(right-left)/2;

if( a[mid]>k ) right = mid;
else left = mid;
}

if( a[left]!=k || left<0 ) return -1;
return left;
}

//find the location that k first showed
int binarySearch_firstShow(int a[],int n, int k){
if( n<1 ) return -1;

int left,right,mid,last;
left=0; //closed left
right=n-1; //closed right
last=-1; //record the first place k showed

while( left<=right ){
mid = left+(right-left)/2;

if( a[mid]>k ) right = mid-1;
else if( a[mid]<k ) left = mid+1;
else{
right = mid-1;
last = mid;
}
}

return last;
}

//find the first location that a[location]>k
int binarySearch_firstBig(int a[],int n, int k){
if( n<1 ) return -1;

int left,right,mid,last;
left=0; //closed left
right=n-1; //closed right
last=-1; //record the first place k showed

while( left<=right ){
mid = left+(right-left)/2;

if( a[mid]>k ){
right = mid-1;
last = mid;
}
else
left = mid+1;
}

return last;
}

2、斐波那契数

running time analysis:

  • 采用递归,f(n) =
    f(n-1)+f(n-2),没有减少问题规模,反而扩大了,因为f(n-1)和f(n-2)的计算有重复的部分。

  • 从f1一个一个加过来计算,时间为Θ(n);

  • 缩减为非线性时间,采用规律:{f(n+1),f(n),f(n),f(n-1)}
    <==> a{1,1,1,0}^n,利用分治法,T(n) = T(n/2) + Θ(1)
    = Θ(lgn);


//{f(n+1),f(n),f(n),f(n-1)} <==> a{1,1,1,0}^n, return value is f(n)
long long fibonacci( long long a[2][2],int n){
if(n==1){
a[0][0] = a[0][1] = a[1][0] = 1;
a[1][1] = 0;
return a[0][1];
}
long long b[2][2];
fibonacci(b,n/2);
for( int i=0; i<2; i++ )
for( int j=0; j<2; j++ ){
a[i][j] = 0;
for( int k=0; k<2; k++ )
a[i][j] += b[i][k]*b[k][j];
}
if( n%2==0 ) return a[0][1];
//n is odd, then a = a*{1,1,1,0};
int t1,t2;
t1 = a[0][0];
t2 = a[0][1];
a[0][0] = t1+t2;
a[0][1] = a[1][0] = t1;
a[1][1] = t2;
return a[0][1];
}

3、乘方

running time analysis: T(n) = T(n/2) + Θ(1)
= Θ(lgn)


//compute x^n.
long long power(int x, int n){
if( n==1 ) return (long long)x;

long long half = power(x,n/2);
if( n/2*2 == n ) return half*half;
return half*half*x;
}

  

分治法--二分查找、乘方、斐波那契数,布布扣,bubuko.com

时间: 2024-10-06 23:55:45

分治法--二分查找、乘方、斐波那契数的相关文章

看数据结构写代码(53) 静态查找表(线性查找,二分查找,斐波那契查找,插值查找)

查找定义:根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素(或记录). 查找表分类:静态查找表和动态查找表. 静态查找表:只查找,而不进行插入,删除. 动态查找表:在查找过程中同时插入查找表中不存在的数据元素,或者从查找表中删除已经存在的某个数据元素. 静态表的 查找 大致 四种 算法: 线性查找,二分查找,斐波那契查找和插值查找. 其中 在线性查找之前,对表 无要求.对于 其余三种 需要 在查找之前 排序.插值查找 除了 需要 排序,还需要 均匀分布. 下面 给出代码: 线性查

二分查找和斐波那契查找

二分查找 说明:查找的数组或列表必须是有序的,若无序,先进行排序 复杂度:时间复杂度 O(log2n),空间复杂度O(n) C++源码(递归和非递归两个版本) #include <iostream> using namespace std; int a[] = { 1, 2, 3, 4, 5, 6, 8 }; int BinarySearch1(int l, int r, int value) { int mid = (l + r) / 2; if (l == r && a[l

斐波那契数与二分法的递归与非递归算法及其复杂度分析

1. 什么是斐波那契数? 这里我借用百度百科上的解释:斐波那契数,亦称之为斐波那契数列(意大利语: Successione di Fibonacci),又称黄金分割数列.费波那西数列.费波拿契数.费氏数列,指的是这样一个数列:0.1.1.2.3.5.8.13.21.--在数学上,斐波纳契数列以如下被以递归的方法定义:F0=0,F1=1,Fn=Fn-1+Fn-2(n>=2,n∈N*),用文字来说,就是斐波那契数列列由 0 和 1 开始,之后的斐波那契数列系数就由之前的两数相加.特别指出:0不是第一

用安卓实现斐波那契数和最近点对问题

目录 1 运行效果展示 2 具体编码 2.1 斐波那契数问题 2.2 最近点对问题 1 运行效果展示 2 具体编码 2.1 斐波那契数问题 具体问题即解决方案请参考本人另一篇博客:算法笔记_001:斐波那契数的多种解法 功能界面布局main_one.xml文件对应界面图: 其源码: <?xml version="1.0" encoding="utf-8" ?> <GridLayout xmlns:android="http://schem

斐波纳契数之组合

斐波纳契数之组合 Time Limit: 1000 MS Memory Limit: 65535 K Total Submit: 145(66 users) Total Accepted: 83(65 users) Rating: Special Judge: No Description 斐波那契数列是这么定义的:F0 = 1, F1 = 1, F2 = F1 + F0,··· Fn = Fn-1 + Fn-2(n>=2),对于每一项,它们都是斐波那契数. 现在给出一个整数d,求一个组合使得a

求斐波那契数的python语言实现---递归和迭代

迭代实现如下: def fab(n): n1 = 1 n2 = 1 if n<1: print("输入有误!") return -1 while (n-2)>0: n3 = n2+n1 n1 = n2 n2 = n3 n-=1 return n3 number = int(input("请输入要求的斐波那契数的第几个数:")) result = fab(number) print(result) 递归实现如下: def fab(n): if n==1 o

Project Euler 104:Pandigital Fibonacci ends 两端为全数字的斐波那契数

Pandigital Fibonacci ends The Fibonacci sequence is defined by the recurrence relation: F[n] = F[n-1] + F[n-2], where F[1] = 1 and F[2] = 1. It turns out that F541, which contains 113 digits, is the first Fibonacci number for which the last nine digi

UVA 11582 Colossal Fibonacci Numbers! 大斐波那契数

大致题意:输入两个非负整数a,b和正整数n.计算f(a^b)%n.其中f[0]=f[1]=1, f[i+2]=f[i+1]+f[i]. 即计算大斐波那契数再取模. 一开始看到大斐波那契数,就想到了矩阵快速幂,输出等了几秒钟才输出完,肯定会超时.因为所有计算都是要取模的,设F[i]=f[i] mod n.F[0]=F[1]=1.只要出现F[i]=F[i+1]=1,那么整个序列就会重复.例如n=3,则序列为1,1,2,0,2,2,1,0,1,1……第九项和第十项都等于1,所以之后的序列都会重复. 至

算法笔记_001:斐波那契数的多种解法

本篇文章解决的问题来源于算法设计与分析课程的课堂作业,主要是运用多种方法来计算斐波那契数.具体问题及解法如下: 一.问题1: 问题描述:利用迭代算法寻找不超过编程环境能够支持的最大整数的斐波那契数是第几个斐波那契数.(Java: 231-1 for int, 263-1 for long) 解决方案:针对问题1,此处要使用迭代法来解决,具体实现代码如下: //用迭代法寻找编程环境支持的最大整数(int型)的斐波那契数是第几个斐波那契数 public static int max_int_iter