【Algorithm】二分法
来源:互联网 发布:美蓝漫画无法连接网络 编辑:程序博客网 时间:2024/06/05 17:27
题目:
有2个数组,原始数组和部分数据被删减后的数组
数组长度未知,仅可以通过get函数去取两个数组中的值
get的值为0时,表示超过数组长度
要求用最少的次数,找到被删减掉的全部数据
思路:
1)确定两个数组的长度
用二分法查找第一个不为0的数,那么这个数的位置就是数组的长度
int get_list_length(int file, int l, int r){ if(l>r) return l; int mid = (l+r)/2; if(get(file,mid)>0) return get_list_length(file,mid+1,r); else return get_list_length(file,l,mid-1);}
2) 两个数组的长度确定后,那么就可以知道被删减的数据的长度,就是两个长度的差值
3)从左右两侧开始找第一个被删除的数和最后一个被删除的数,存入记录删除数据的数组中,这样二分查找的长度不断在减小
要知道左侧第一个被删的数据同样需要二分法,只有找到左侧第一个不相等的数据就可以了
难点在于找下一个,这里有一个差值offset,因为之前已经删了,两个坐标就不是一一对应,新数组的坐标应该减去offset
int get_the_first_delete_data(int l, int r, int offset){ if (l>r)return l; int mid = (l+r)/2; if(get(1,mid) != get(2, mid-offset)) return get_the_first_delete_data(file,mid+1,r); else return get_the_first_delete_data(file,l,mid-1);}
找右侧最后一个也是同样的原理,只不过条件是反的
int get_the_last_delete_data(int l, int r, int offset){ if (l>r)return l; int mid = (l+r)/2; if(get(1,mid) != get(2, mid-offset)) return get_the_last_delete_data(file,l,mid-1); else return get_the_last_delete_data(file,mid+1,r);}
左右两侧都找到之后,那整体长度就缩短了
4)有一个可以优化的地方就是get取过的数据一定要存下来,这样可以减少再去取数据的次数
int get_data()( if(file_data[file-1][index]==0) return get(file,index); else return file_data[file-1][index];)
这个方法算下来之后,次数大概在2700-2800左右,但是不能通过考试
我也不知道为啥。。。。
后来看了别人的思路,是这样的
1)二分法确定两个数组的长度
2)找到第二个数组中第一个元素,然后在原来的数组中从第一个元素查找,找到相等元素之前的那些元素都是删掉的,这个思路很好
3)同理 找到第二个数组中最后一个元素,然后在原来的数组中从最后一个元素查找,找到相等元素之前的那些元素都是删掉的
4)然后也是用二分法,找到一个位置,左右两边被删掉的元素相同,那么问题变成了2个子问题,不断递归,最后找到不断缩小两个元素所在区间,输出结果
/*调用部分*/cal(0,first_len, offset, delete_len);/*代码实现*/void cal(int start, int end, int offset, int del){ if(start+1 == end) { /*全找到了,打印结果*/ } int mid = (start+end)/2; int a = get_data(2,mid); int foffset = 0; int add = 0; if(del%2) add =1; if(del>1) { for(int i = 0;i<=del/2;i++) { int b = get_data(1,mid+del/2+i+add+offset); if(a==b) { foffset=del/2+i+add; break; } int c = get_data(1,mid+del/2-i+add+offset); if(a==c) { foffset=del/2-i; break; } } if(foffset!=0) cal(start,mid,offset,foffset); if(foffset!=del) cal(mid,end,offset+offset,del-foffset); } else { if(a==myget(1,mid+offset)) cal(mid,end,offset,1); else cal(start,mid,offset,1); }}
二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好;其缺点是要求待查表为有序表。
这里虽然不是有序,但是也可以用来查找最后一个不为0的数来确定长度,因为这个0左右两次的数是不一样的,用来找两个数组的偏移也是一样
int bsearchWithoutRecursion(int array[],int low,int high,int target){ while(low<=high) { int mid=(low+high)/2; if(array[mid]>target) high=mid-1; else if(array[mid]<target) low=mid+1; else return mid; } return-1;}
- 【Algorithm】二分法
- [Algorithm]二分法查找算法
- Algorithm学习笔记 --- 一元三次方程求解(二分法)
- 二分法~~
- 二分法
- 二分法
- 二分法
- 二分法
- 二分法
- 二分法
- 二分法
- 二分法
- 二分法
- 二分法
- 二分法
- 二分法
- 二分法
- 二分法
- Matlab Hermite(2n+1)插值
- java解决pat乙级练习题1002. 写出这个数
- jquery获取input输入框的类型
- 欢迎使用CSDN-markdown编辑器
- centos7安装mysql5.7
- 【Algorithm】二分法
- MongoDB简单介绍
- Plugin org.apache.maven.plugins:maven-compiler-plugin:3.2 or one of its dependencies could not be re
- 洛谷 P3359 改造异或树
- 笨方法学python 习题34(访问列表元素)习题35(作死小游戏)
- 页面验证码的显示与点击刷新问题
- 【LeetCode】165. Compare Version Numbers
- Java中的反射机制
- H5页面在iOS网页中的数字被识别为电话号码(数字颜色自动被改变成蓝色)?