二分值插斐波那契查找
Posted chaostudy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分值插斐波那契查找相关的知识,希望对你有一定的参考价值。
二分查找
二分查找的思路分析
-
首先确定该数组的中间的下标
- mid= (left +right)/ 2
-
然后让需要查找的数findVal和a[mid]比较
- findVal> ar[mid],说明你要查找的数在mid的右边,因此需要递归的向右查找
- findVal< ar[mid],说明你要查找的数在mid的左边,因此需要递归的向左查找
- findVal== ar[mid]说明找到,就返回
-
什么时候我们需要结束递归。
- 找到就结束递归
- 递归完整个数组,仍然没有找到findVal,也需要结束递归当left>right就需要退出
使用二分查找的前提是该数组是有序的。
查找一个不重复的值
public static void main(String[] args) {
int[] arr = {1,23,45,67,79,90,212}
int i = erFenSearch(arr, 0, arr.length-1, 1);
System.out.println(i);
}
public static int erFenSearch(int[] arr,int left, int right,int findValue){
if (left > right){
return -1;
}
int mid = (left + right) / 2 ;
int midValue = arr[mid];
if (findValue < midValue){
return erFenSearch(arr, left, mid - 1, findValue);
}else if (findValue > midValue){
return erFenSearch(arr, mid + 1, right, findValue);
}else {
return mid;
}
}
查找所有的下标
public static void main(String[] args) {
int[] arr = {1,23,46,89,89,89,89,122,165,267};
List<Integer> list = erFenSearch1(arr, 0, arr.length - 1, 89);
System.out.println(list);
}
public static List<Integer> erFenSearch1(int[] arr, int left, int right, int findValue){
if (left > right){
return new ArrayList<Integer>();
}
int mid = (left + right) / 2 ;
int midValue = arr[mid];
if (findValue < midValue){
return erFenSearch1(arr, left, mid - 1, findValue);
}else if (findValue > midValue){
return erFenSearch1(arr, mid + 1, right, findValue);
}else {
List<Integer> list = new ArrayList<Integer>();
int temp = mid - 1;
while (true){
if (temp < 0 || arr[temp] != findValue){
break;
}
list.add(temp);
temp--;
}
list.add(mid);
temp = mid + 1;
while (true){
if (temp > arr.length - 1 || arr[temp] != findValue){
break;
}
list.add(temp);
temp++;
}
return list;
}
}
插值查找
要求数组有序,适用于数据分布均匀的情况;
public static void main(String[] args) {
int[] arr = new int[100];
for (int i = 0; i < arr.length; i++) {
arr[i] = i + 1;
}
int i = insertValueSearch(arr, 0, arr.length - 1, 99);
System.out.println(i);
}
public static int insertValueSearch(int[] arr,int left, int right,int findValue){
if (left > right || findValue < arr[0] || findValue > arr[arr.length-1]){
return -1;
}
int mid = left + (right - left) * (findValue - arr[left]) / (arr[right] - arr[left]);
int midValue = arr[mid];
if (findValue > midValue){
return insertValueSearch(arr, mid + 1, right, findValue);
}else if (findValue < midValue){
return insertValueSearch(arr, left, mid - 1, findValue);
}else {
return mid;
}
}
斐波那契查找
斐波那契数列{1,1,2,3,5, 8, 13,21, 34, 55}发现斐波那契数列的两个相邻数的比例,无限接近黄金分割值0.618
核心f(k) =f(k - 1) + f(k - 2) ====>>> f(k) - 1 =( f(k - 1) - 1)+(f(k - 2) - 1) + 1
public class FibSearch {
public static int maxSize = 20;
public static void main(String[] args) {
int[] arr = {1,8,10,89,1000,1024};
System.out.println(fibSearch(arr,1));
}
//制造斐波那契数列
public static int[] fib(){
int[] f = new int[maxSize];
f[0] = 1;
f[1] = 1;
for (int i = 2; i < maxSize; i++) {
f[i] = f[i - 1] + f[i - 2];
}
return f;
}
//斐波那契查找方法
public static int fibSearch(int[] arr,int key){
int low = 0;
int high =arr.length - 1;
int k = 0;//表示斐波那契分割数值的下标
int mid = 0;
//获取斐波那契数列
int[] f = fib();
//获取到比arr大的斐波那契分割数值的下标
while (high > f[k] - 1){
k++;
}
//因为f[k]值可能大于arr的长度,因此我们需要使用Arrays类,构造一个新的数组,并指向temp[]不足的部分会使用最大值填充
int[] temp = Arrays.copyOf(arr,f[k]);
for (int i = high + 1; i < temp.length; i++) {
temp[i] = temp[high];
}
while (low <= high){
mid = low + f[k - 1] - 1;
if (key < temp[mid]){
high = mid - 1;
k--;//f(k) =f(k - 1)高 + f(k - 2)低
}else if (key > temp[mid]){
low = mid + 1;
k -= 2;//f(k) =f(k - 1)高 + f(k - 2)低
}else {
if (high < mid){
return high;
}else {
return mid;
}
}
}
return -1;
}
}
以上是关于二分值插斐波那契查找的主要内容,如果未能解决你的问题,请参考以下文章
leetcode查找算法(顺序查找,二分法,斐波那契查找,插值查找,分块查找)
[Algorithm]二分插值斐波那契查找算法 Java 代码实现