二分的概念
二分算法:是用来在一个有序数组中查找一个元素的算法。时间复杂度O(log n)
二分的二段性
集合中的元素有存在分界线,给定条件可以将集合中的元素分为两部分,一部分满足条件,一部分不满足条件。(不断将区间一分为二逼近端点)
1.查找当前有序数组中大于等于x的第一个数(取区间靠左的值)
int arr[]={1,2,3,4,5}; int l=0,r=arr.length-1; int x=2; while(l<r){ int mid=(l+r)/2;//取区间中间的位置靠左的值 if(arr[mid]>=x) r=mid;//区间向左缩短一半 else l=mid+1;//区间向右缩短一半 }
2. 查找当前有序数组中小于等于x的最后一个数
int arr[]={1,2,3,4,5}; int l=0,r=arr.length-1; int x=2; while(l<r){ int mid=(l+r+1)/2;//取区间中间位置靠右的位置 if(arr[mid]>x) r=mid-1;//区间向左缩短一半 else l=mid;//区间向右缩短一半 }
例题实战 1
问题描述
给定一个数组,其采用如下代码定义
int data[200];
for(i=0;i<200;i++){
data[i]=4*i+6;
}
先给定某个数(data数组中),请你求出他在数组中的位置
输入描述
输入一个待查的整数(该整数一定在数组data中)
输出描述
输出该整数在数组中的指标
代码
package erfen; import java.util.*; public class erfen { public static void main(String[] args) { // TODO Auto-generated method stub Scanner scan=new Scanner(System.in); int res=scan.nextInt();//待查数 int data[]=new int [200]; for(int i=0;i<200;i++) { data[i]=4*i+6; } int l=0, r = data.length-1,mid=0; while(l<r) { mid=(l+r)/2;//中间左侧 if(data[mid]>=res) { r=mid; }else { l=mid+1; } } System.out.print(l); } }
例题实战 2
问题描述
给定n个数形成一个序列a,那定义如果一个连续子序列包含序列a中所有不同元素。则该连续子序列便为蓝桥序列,现在问你,该蓝桥序列长度最短为多少
例如 1 2 2 2 3 2 2 1 ,包含3个不同的数1,2,3,而3 2 2 1符合题目要求,因此答案为4
连续子序列:从序列a中选取若干个连续的数形成一个序列叫做连续子序列
输入格式
第一行输入一个整数n,表示序列长度
第二行输入n个元素。
输出格式
输出一个整数,表示最短的蓝桥序列长度。
代码
package erfen; import java.util.*; public class erfen2 { public static void main(String[] args) { // TODO Auto-generated method stub Scanner scan=new Scanner(System.in); int n=scan.nextInt(); int []arr=new int[n]; for(int i:arr) { arr[i]=scan.nextInt(); } //去重操作 Set<Integer> set=new HashSet<>(); for(int i:arr) { set.add(arr[i]); }//计算a序列中的不同元素 int m=set.size();//满足条件的最小个数 int l=1,r=arr.length; while(l<r) { int mid=(l+r)/2; if(check(mid,arr,m)) r=mid; else l=mid+1; } System.out.println(l); } public static boolean check(int mid, int[] arr, int m) { int n=arr.length; int []f=new int [1001]; int l=0; int r=0;//同向双指针 int ans=0;//当前区间含有的元素个数 while(r<n) { f[arr[r]]++; if(f[arr[r]]==1) { ans++; } if(r-l+1>mid) { f[arr[l]]--; if(f[arr[l]]==0){ ans--; } l++; } r++; if(ans>=m) { return true; } // TODO Auto-generated method stub } return false; } }