C++ 二进制搜索以查找数字所在的范围
我有一个数组C++ 二进制搜索以查找数字所在的范围,c++,C++,我有一个数组 Values array: 12 20 32 40 52 ^ ^ ^ ^ ^ 0 1 2 3 4 我必须在其上执行二进制搜索以查找数字所在范围的索引。例如: 给定数字->19(它位于索引0和1之间),返回0 给定数字->22(它位于索引1和2之间),返回1 给定数字->40(它位于索引3和4之间),返回3 我以下面的方式实现了二进制搜索,这对于案例1和案例3是正确的,但是如果我们搜索案例2或52、55、32等
Values array: 12 20 32 40 52
^ ^ ^ ^ ^
0 1 2 3 4
我必须在其上执行二进制搜索以查找数字所在范围的索引。例如:
#include <iostream>
using namespace std;
int findIndex(int values[], int number, unsigned first, unsigned last)
{
unsigned midPoint;
while(first<last)
{
unsigned midPoint = (first+last)/2;
if (number <= values[midPoint])
last = midPoint -1;
else if (number > values[midPoint])
first = midPoint + 1;
}
return midPoint;
}
int main()
{
int a[] = {12, 20, 32, 40, 52};
unsigned i = findIndex(a, 55, 0, 4);
cout << i;
}
#包括
使用名称空间std;
int findIndex(int值[],int编号,无符号第一个,无符号最后一个)
{
无符号中点;
当(P)> C或C++中的范围通常是直接指向下界,但一个超出了上限。除非你感到极度受虐,否则你可能也会坚持在你的搜索中遵守这个约定。
假设您将遵循此操作,则您的last=middpoint-1;
是不正确的。相反,您希望将last设置为实际使用范围结束后的1,因此它应该是last=middpoint;
你也只需要一次比较,而不是两次。在二进制搜索中,只要两个边界不相等,你就要将下限或上限设置为中心点,所以你只需要做一次比较就可以决定是哪个
<至少>按惯例,在C++中,你使用“<代码> > P>进行所有的比较,成功的正则二进制搜索返回密钥的索引。如果找不到密钥,它总是在低于我们正在搜索的密钥的索引的索引处停止。我猜下面的修改的二进制搜索算法将起作用。< /P>
Given sorted array A
Find a key using binary search and get an index.
If A[index] == key
return index;
else
while(index > 1 && A[index] == A[index -1]) index = index -1;
return index;
binrch(数组、num、low、high){
如果(数值>数组[高])
高回报;
而(1){
如果(低==高-1)
低回报;
如果(低>=高)
返回低-1;
中=(低+高)/2
如果(num
这将在min(A[i])为什么不使用标准库函数的条件下工作
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
int main() {
for (int input = 10; input < 55; input++) {
cout << input << ": ";
// Your desire:
vector<int> v = { 12, 20, 32, 40, 52 };
if (input < v.front() || input > v.back()) {
cout << "Not found" << endl;
} else {
auto it = upper_bound(v.begin(), v.end(), input);
cout << it - v.begin() - 1 << endl;
}
}
}
#包括
#包括这里有一个更具体的答案
int findIndex(int values[],int key,int first, int last)
{
if(values[first]<=key && values[first+1]>=key)// stopping condition
{
return first;
}
int imid=first+(last-first)/2;
if(first==last || imid==first)
{
return -1;
}
if(values[imid]>key)
{
return findIndex(values,key,first,imid);
}
else if(values[imid]<=key)
{
return findIndex(values,key,imid,last);
}
}
int findIndex(int值[],int键,int first,int last)
{
if(values[first]=key)//停止条件
{
先返回;
}
int imid=first+(last first)/2;
if(first==last | | imid==first)
{
返回-1;
}
if(值[imid]>键)
{
返回findIndex(值、键、第一个、imid);
}
else if(输入的值[imid]
四,
1 3 8 10
四,
输出
3(3和8中的最小值)
#包括
int main()
{
int c,first,last,middle,n,search,array[100];
scanf(“%d”和“&n”);
对于(c=0;c/*binary_range.c(c)2016adolfo@di-mare.com*/
/* http://stackoverflow.com/questions/10935635 */
/*这段代码很容易翻译成Fortran*/
#include/*printf()*/
#include/*assert()*/
/**查找最大索引“i”,以便“*nSEED nVEC[N-1]”。
-使用二进制搜索查找“*nSEED”的范围。
*/
整数二进制范围(整数*nSEED,整数nVEC[],整数N){
低、高、中、高;
如果(*nSEED>nVEC[N-1]){
返回N;
}
对于(;){/*lo=binary_range_search()*/
lo=0;
hi=N-1;
对于(;;){
正=(高-低)>>1;/*mid=(高-低)/2*/
如果(加==0){assert(hi-lo==1);
如果(*nSEED nVEC[N-1]){
返回N;
}
i=0;
而(i[12<(19)返回1*/
val=19;断言(二进制范围(&val,nVEC,N)==1);
/*22->[20<(22)返回2*/
val=22;断言(二进制范围(&val,nVEC,N)==2);
/*40->[32<(40)返回3*/
val=40;断言(二进制范围(&val,nVEC,N)=3);
/*超过52的都返回N*/
val=53;断言(二进制范围(&val,nVEC,N)=N);
}}
}
/**测试程序*/
int main(){
如果(1){
printf(“\ntest_10935635()”);
测试_10935635();
}
printf(“\nEND”);
返回0;
}
/*编译器:gcc.exe(tdm-1)4.9.2*/
/*IDE:Code::Blocks 16.01*/
/*语言:C&C++
/*EOF:binary_range.c*/
我知道这是一个旧线程,但由于我必须解决一个类似的问题,我想我会分享它。给定一组不重叠的整数范围,我需要测试给定的值是否位于其中任何一个范围内。以下(在Java中)使用修改的二进制搜索来测试值是否位于排序的(从低到高)范围内一组整数范围
/**
* Very basic Range representation for long values
*
*/
public class Range {
private long low;
private long high;
public Range(long low, long high) {
this.low = low;
this.high = high;
}
public boolean isInRange(long val) {
return val >= low && val <= high;
}
public long getLow() {
return low;
}
public void setLow(long low) {
this.low = low;
}
public long getHigh() {
return high;
}
public void setHigh(long high) {
this.high = high;
}
@Override
public String toString() {
return "Range [low=" + low + ", high=" + high + "]";
}
}
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
//Java implementation of iterative Binary Search over Ranges
class BinaryRangeSearch {
// Returns index of x if it is present in the list of Range,
// else return -1
int binarySearch(List<Range> ranges, int x)
{
Range[] arr = new Range[ranges.size()];
arr = ranges.toArray(arr);
int low = 0, high = arr.length - 1;
int iters = 0;
while (low <= high) {
int mid = low + (high - low) / 2; // find mid point
// Check if x is present a
if (arr[mid].getLow() == x) {
System.out.println(iters + " iterations");
return mid;
}
// If x greater, ignore left half
if (x > arr[mid].getHigh()) {
low = mid + 1;
}
else if (x >= arr[mid].getLow()) {
System.out.println(iters + " iterations");
return mid;
}
// If x is smaller, ignore right half of remaining Ranges
else
high = mid - 1;
iters++;
}
return -1; // not in any of the given Ranges
}
// Driver method to test above
public static void main(String args[])
{
BinaryRangeSearch ob = new BinaryRangeSearch();
// make a test list of long Range
int multiplier = 1;
List<Range> ranges = new ArrayList<>();
int high = 0;
for(int i = 0; i <7; i++) {
int low = i + high;
high = (i+10) * multiplier;
Range r = new Range(low, high);
multiplier *= 10;
ranges.add(r);
}
System.out.println(Arrays.toString(ranges.toArray()));
int result = ob.binarySearch(ranges, 11);
if (result == -1)
System.out.println("Element not present");
else
System.out.println("Element found at "
+ "index " + result);
}
}
/**
*非常基本的长值范围表示法
*
*/
公共类范围{
私人长低;
私人长高;
公共范围(长-低、长-高){
这个.低=低;
这个高=高;
}
公共布尔值isInRange(长值){
返回val>=low&&val=arr[mid].getLow(){
System.out.println(iters+迭代);
中途返回;
}
//如果x较小,则忽略剩余范围的右半部分
其他的
高=中-1;
iters++;
}
return-1;//不在任何给定范围内
}
//以上测试的驱动程序方法
公共静态void main(字符串参数[])
{
BinaryRangeSearch ob=新的BinaryRangeSearch();
//制作一份远程测试列表
整数乘数=1;
列表范围=新的ArrayList();
int高=0;
对于(int i=0;i我的python实现:
时间复杂度:O(log(n))
空间复杂度:O(对数(n))
def searchForRange(数组,目标):
范围=[-1,-1]
AlteredBinarySrach(数组,目标,0,len(数组)-1,范围,真)
AlteredBinarySrach(数组,目标,0,len(数组)-1,范围,False)
返回范围
def alteredBinarySerach(阵列、目标、左、右、右)
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
int main() {
for (int input = 10; input < 55; input++) {
cout << input << ": ";
// Your desire:
vector<int> v = { 12, 20, 32, 40, 52 };
if (input < v.front() || input > v.back()) {
cout << "Not found" << endl;
} else {
auto it = upper_bound(v.begin(), v.end(), input);
cout << it - v.begin() - 1 << endl;
}
}
}
int findIndex(int values[],int key,int first, int last)
{
if(values[first]<=key && values[first+1]>=key)// stopping condition
{
return first;
}
int imid=first+(last-first)/2;
if(first==last || imid==first)
{
return -1;
}
if(values[imid]>key)
{
return findIndex(values,key,first,imid);
}
else if(values[imid]<=key)
{
return findIndex(values,key,imid,last);
}
}
#include <stdio.h>
int main()
{
int c, first, last, middle, n, search, array[100];
scanf("%d",&n);
for (c = 0; c < n; c++)
scanf("%d",&array[c]);
scanf("%d", &search);
first = 0;
last = n - 1;
middle = (first+last)/2;
while (first <= last) {
if (array[middle] < search)
{
first = middle + 1; }
else if (array[middle] == search) {
break;
}
else
{
last = middle - 1;
}
middle = (first + last)/2;
}
printf("%d\n",array[middle]);
return 0;
}
/* binary_range.c (c) 2016 adolfo@di-mare.com */
/* http://stackoverflow.com/questions/10935635 */
/* This code is written to be easily translated to Fortran */
#include <stdio.h> /* printf() */
#include <assert.h> /* assert() */
/** Find the biggest index 'i' such that '*nSEED <= nVEC[i]'.
- nVEC[0..N-1] is an strict ascending order array.
- Returns and index in [0..N].
- Returns 'N' when '*nSEED>nVEC[N-1]'.
- Uses binary search to find the range for '*nSEED'.
*/
int binary_range( int *nSEED, int nVEC[] , int N ) {
int lo,hi, mid,plus;
if ( *nSEED > nVEC[N-1] ) {
return N;
}
for (;;) { /* lo = binary_range_search() */
lo = 0;
hi = N-1;
for (;;) {
plus = (hi-lo)>>1; /* mid = (hi+lo)/2; */
if ( plus == 0 ) { assert( hi-lo==1 );
if (*nSEED <= nVEC[lo]) {
hi = lo;
}
else {
lo = hi;
}
}
mid = lo + plus; /* mid = lo + (hi-lo)/2; */
if (*nSEED <= nVEC[mid]) {
hi = mid;
}
else {
lo = mid;
}
if (lo>=hi) { break; }
}
break;
} /* 'lo' is the index */
/* This implementation does not use division. */
/* ========================================= */
assert( *nSEED <= nVEC[lo] );
return lo;
}
/** Find the biggest index 'i' such that '*nSEED <= nVEC[i]'.
- nVEC[0..N-1] is an strict ascending order array.
- Returns and index in [0..N].
- Returns 'N' when '*nSEED>nVEC[N-1]'.
- Uses sequential search to find the range for '*nSEED'.
*/
int sequential_range( int* nSEED, int nVEC[] , int N ) {
int i;
if ( *nSEED > nVEC[N-1] ) {
return N;
}
i=0;
while ( i<N ) {
if ( *nSEED <= nVEC[i] ) { break; }
++i;
}
return i;
}
/** test->stackoverflow.10935635(). */
void test_10935635() {
{{ /* test.stackoverflow.10935635() */
/* http://stackoverflow.com/questions/10935635 */
/* binary_range search to find the range in which the number lies */
/* 0 1 2 3 4 */
int nVEC[] = { 12,20,32,40,52 }; int val;
int N = sizeof(nVEC)/sizeof(nVEC[0]); /* N = DIM(nVEC[]) */
val=19; val = binary_range( &val,nVEC,N );
/* 19 -> [12 < (19) <= 20] -> return 1 */
val=19; assert( binary_range( &val,nVEC,N ) == 1 );
/* 22 -> [20 < (22) <= 32] -> return 2 */
val=22; assert( binary_range( &val,nVEC,N ) == 2 );
/* 40 -> [32 < (40) <= 40] -> return 3 */
val=40; assert( binary_range( &val,nVEC,N ) == 3 );
/* Everything over 52 returns N */
val=53; assert( binary_range( &val,nVEC,N ) == N );
}}
}
/** Test program. */
int main() {
if (1) {
printf( "\ntest_10935635()" );
test_10935635();
}
printf( "\nEND" );
return 0;
}
/* Compiler: gcc.exe (tdm-1) 4.9.2 */
/* IDE: Code::Blocks 16.01 */
/* Language: C && C++ */
/* EOF: binary_range.c */
/**
* Very basic Range representation for long values
*
*/
public class Range {
private long low;
private long high;
public Range(long low, long high) {
this.low = low;
this.high = high;
}
public boolean isInRange(long val) {
return val >= low && val <= high;
}
public long getLow() {
return low;
}
public void setLow(long low) {
this.low = low;
}
public long getHigh() {
return high;
}
public void setHigh(long high) {
this.high = high;
}
@Override
public String toString() {
return "Range [low=" + low + ", high=" + high + "]";
}
}
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
//Java implementation of iterative Binary Search over Ranges
class BinaryRangeSearch {
// Returns index of x if it is present in the list of Range,
// else return -1
int binarySearch(List<Range> ranges, int x)
{
Range[] arr = new Range[ranges.size()];
arr = ranges.toArray(arr);
int low = 0, high = arr.length - 1;
int iters = 0;
while (low <= high) {
int mid = low + (high - low) / 2; // find mid point
// Check if x is present a
if (arr[mid].getLow() == x) {
System.out.println(iters + " iterations");
return mid;
}
// If x greater, ignore left half
if (x > arr[mid].getHigh()) {
low = mid + 1;
}
else if (x >= arr[mid].getLow()) {
System.out.println(iters + " iterations");
return mid;
}
// If x is smaller, ignore right half of remaining Ranges
else
high = mid - 1;
iters++;
}
return -1; // not in any of the given Ranges
}
// Driver method to test above
public static void main(String args[])
{
BinaryRangeSearch ob = new BinaryRangeSearch();
// make a test list of long Range
int multiplier = 1;
List<Range> ranges = new ArrayList<>();
int high = 0;
for(int i = 0; i <7; i++) {
int low = i + high;
high = (i+10) * multiplier;
Range r = new Range(low, high);
multiplier *= 10;
ranges.add(r);
}
System.out.println(Arrays.toString(ranges.toArray()));
int result = ob.binarySearch(ranges, 11);
if (result == -1)
System.out.println("Element not present");
else
System.out.println("Element found at "
+ "index " + result);
}
}
def searchForRange(array, target):
range = [-1, -1]
alteredBinarySerach(array, target, 0, len(array) -1, range, True)
alteredBinarySerach(array, target, 0, len(array) -1, range, False)
return range
def alteredBinarySerach(array, target, left, right, range, goLeft):
if left > right:
return
middle = (left+ right)//2
if array[middle] > target:
alteredBinarySerach(array, target, left, middle -1, range, goLeft)
elif array[middle] < target:
alteredBinarySerach(array, target, middle +1, right, range, goLeft)
else:
if goLeft:
if middle == 0 or array[middle -1] != target:
range[0] = middle
else:
alteredBinarySerach(array, target, left, middle -1 , range, goLeft)
else:
if middle == len(array) -1 or array[middle+1] != target:
range[1] = middle
else:
alteredBinarySerach(array, target, middle +1, right , range, goLeft)