编程珠玑第9章二分搜索(有重复数字)中查找某数出现的第一个位置
2013-08-21 09:49
531 查看
binary search:search the first occurence of a number
查找的数中有重复的数
只需在原始的二分搜索基础上进行修改,当中间的数A[mid]与target值相同时,target值的第一次出现要么是在mid处,要么是在mid左边。若low与mid(low==mid)的闭区间只包含一个数,则返回值为mid,若low<mid,则修改high为mid
具体实现如下
编程珠玑上Column 9给出了另外一个解法。
首先虚拟出两个数组元素,x[-1],x
,n为数组的size,实际上这两个元素不存在,循环时不变量是x[l]<t<x<=x[u]
这与一般二分搜索假设的范围有点不一样。因为l初始为-1,u初始为n,该条件初始时候成立,实际上这两个虚拟的元素在代码中未使用
invariant在循环中保持。
因为初始时u>=l+2
m>=l+1
l<=u-2
所以l+1<=m<=u-1
所以l<m<u
根据循环中的语句l<u在循环中是得到保持的
关于编程珠玑中9.3中的代码
if p>1000|| x[p] !=t
p=-1
这里的条件p>1000应该改为p>=1000,因为p=1000的时候,数组已经越界了。
实际上该算法算出的p是可能等于1000。因为要使p=1000,那么目标值t肯定处于后半区别,即l=1000-512
l+i=1000,处在[1000-512,1000]的区间之内。而l的更新必定遵循l=1000-512+256+128+...+1的规律,该数必定是个奇数,l最大可能的值是1000-512+256+128+64+32+16+8+4+2+1=999而p=l+1=1000,这时求出的p是可能等于1000的,所以这里写成p>1000是不行的
9.3最后一个版本代码是循环展开之后的版本。
第7题求解某数的二进制序列中1的个数
int count =0;
while(x>0){
x=x&(x-1);
count++;
}
查找的数中有重复的数
只需在原始的二分搜索基础上进行修改,当中间的数A[mid]与target值相同时,target值的第一次出现要么是在mid处,要么是在mid左边。若low与mid(low==mid)的闭区间只包含一个数,则返回值为mid,若low<mid,则修改high为mid
具体实现如下
#include<iostream> using namespace std; int binary_search(int A[],int target,int low,int high){ while(low<=high){ int mid=(low+high)/2; if(target<A[mid]) high=mid-1; else if(target>A[mid]) low=mid+1; else if(low<mid)//&&target==A[mid] high=mid; else //mid==low return mid; } return -1; } int main(){ int A[]={1,2,3,3,5,6,7,9}; cout<<binary_search(A,3,0,7)<<endl; int B[]={1,2,3,3,4,4,7}; cout<<binary_search(B,4,0,6)<<endl; return 0; }
编程珠玑上Column 9给出了另外一个解法。
首先虚拟出两个数组元素,x[-1],x
,n为数组的size,实际上这两个元素不存在,循环时不变量是x[l]<t<x<=x[u]
这与一般二分搜索假设的范围有点不一样。因为l初始为-1,u初始为n,该条件初始时候成立,实际上这两个虚拟的元素在代码中未使用
invariant在循环中保持。
因为初始时u>=l+2
m>=l+1
l<=u-2
所以l+1<=m<=u-1
所以l<m<u
根据循环中的语句l<u在循环中是得到保持的
l=-1; u=n while(l+1!=u){ /*invariant :x[l]<t &&x[u]>=t &&l<u*/ int m=(l+u)/2; if(x(m)<t) l=m; else u=m; } p = u ; /*assert l+1==u&&x[l]<t&&x[u]>=t*/ if(p>=n || x[p]!=t) p=-1
关于编程珠玑中9.3中的代码
if p>1000|| x[p] !=t
p=-1
这里的条件p>1000应该改为p>=1000,因为p=1000的时候,数组已经越界了。
实际上该算法算出的p是可能等于1000。因为要使p=1000,那么目标值t肯定处于后半区别,即l=1000-512
l+i=1000,处在[1000-512,1000]的区间之内。而l的更新必定遵循l=1000-512+256+128+...+1的规律,该数必定是个奇数,l最大可能的值是1000-512+256+128+64+32+16+8+4+2+1=999而p=l+1=1000,这时求出的p是可能等于1000的,所以这里写成p>1000是不行的
9.3最后一个版本代码是循环展开之后的版本。
第7题求解某数的二进制序列中1的个数
int count =0;
while(x>0){
x=x&(x-1);
count++;
}
相关文章推荐
- sqlserver2008r2查找非中文字母数字出现的第一个位置
- 剑指offer——面试题38:数字在排序数组中出现的次数(利用二分查找来找第一次和最后一次的位置)
- 34. Search for a Range(二分查找有重复元素数组中的目标数的第一个位置和最后一个位置)
- 程序员面试题目总结--数组(二)【二分查找、找出给定数字出现次数、两个有序整型数组交集、找出数组中唯一的重复元素、判断数组中的数值是否连续相邻】
- 查找字符流中第一个出现的不重复字符
- 码农小汪剑指Offer之35-数字在排序数组中出现的次数 暴力 二分查找的运用
- 二分查找解决数组中出现数字的次数
- 求串s中出现的第一个最长重复子串及其位置
- 用java实现,查找字符串中第一个没有重复出现的字符
- 查找字符串中第一个出现的不重复的字符
- 查找数组重复出现数字(2次或者3次)的唯一数
- 第一个只出现一次的字符+数组中重复的数字
- 第一个只出现一次的字符位置和字符流中第一个不重复的字符
- 二分查找的变形,统计数字在排序数组出现的次数
- 插入元素到有序数组,二分搜索查找插入位置
- 【递归、二分查找】数字在排序数组中出现的次数
- leetcode 35. Search Insert Position搜索插入位置(二分查找)
- 在排序的数组中二分查找一个元素,返回在数组中它第一次出现的位置
- C++实现一个栈,出栈,入栈,返回最小值 时间复杂度为O(1),查找字符串中第一个重复出现的字符
- 二分查找--数字在排序数组中出现的次数