数组之二分查询

目录

数组

数组的优缺点

(1)优点

(2)缺点

数组之二分

1.二分的条件

2.二分的循环结束条件及左右端点的改变

3.常规二分示例

4.有重复元素的二分


数组

数组是存放在连续内存空间上的相同类型数据的集合。

数组可以方便的通过下标索引的方式获取到下标下对应的数据。

举一个字符数组的例子

数组的优缺点

(1)优点

数组根据索引查询一个数据的时间复杂度为O(1) 数组首地址+索引*数据类型偏移量

(2)缺点

正是因为数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址时间复杂度为O(n)。

例如删除下标为3的元素,需要对下标为3的元素后面的所有元素都要做移动操作,如图所示:

数组之二分

1.二分的条件

有序数组 无重复元素

2.二分的循环结束条件及左右端点的改变

二分查找涉及的很多的边界条件,逻辑比较简单,但就是写不好。例如到底是 while(left < right) 还是 while(left <= right),到底是right = middle呢,还是要right = middle - 1呢?

我们定义 target 是在一个在左闭右闭的区间里,也就是[left, right] (这个很重要非常重要)

例如在数组:1,2,3,4,7,9,10中查找元素2

【1】确定搜索范围 left=0 right=arr.length-1 [left,right]

【2】比较中间值 mid=(left+right)/2 如果中间值大于target那么target就在左半部分 如果中间值小于target那么target就在右半不放呢

【3】更新搜索范围 这个时候就要看 如果在左半部分 肯定是要改变right

疑难点: right=mid-1 还是right=mid ?

if (nums[middle] > target) right 要赋值为 middle - 1,因为当前这个nums[middle]一定不是target(也就是说target一定不能在mid位置)那么搜索范围肯定不,那么接下来要查找的左区间结束下标位置就是 middle - 1 类比 如果中间值大于target left=mid+1

[4]循环【1-3】

3.常规二分示例

 
class Solution {
     public int search(int[] nums, int target) {
 int left =0;
 int right=nums.length-1;
 int mid=0;
 while(left<=right){
     mid=(left+right)/2;
     int num=nums[mid];
     if(num>target){
       right=mid-1;
     }else if(num<target){
         left=mid+1;
     }else  {
         return mid;
     }
 ​
 }
 return -1;
     }
 }

 
 ​
 ​

 import java.util.Scanner;
 ​
 public class Main{
   
 ​
     public static void main(String[] args) {
    
         Scanner sc = new Scanner(System.in);
         int t = sc.nextInt();
         for (int i = 0; i < t; i++) {
         //【1】确定取值范围
                  double a = 0.0;
         double b = 100.0;
             double y = sc.nextDouble();
             if (y>201805052114.0||y<14.0) {
                 System.out.println(-1);
             } else {
      
                 double mid = 0;
                 while (b-a>0.00001) {
   
                     mid = (a + b) / 2;
                     //比较中间值与目标值
                     if (2018*mid*mid*mid*mid+21*mid+5*mid*mid*mid+5*mid*mid+14>y) {//
                         b = mid;//更新搜索范围
                     } else {
                        a=mid;//更新搜索范围
 ​
                     }
 ​
                   
                 }
                 System.out.printf("%.4f\n", mid);
 ​
             }
         }
     }
 }

登录—专业IT笔试面试备考平台_牛客网

 class Solution {
     public int searchInsert(int[] nums, int target) {
       int left=0;
       int right=nums.length-1;
       int mid=0;
       while(left<=right){
 mid=(left+right)>>1;
       if(nums[mid]>target){//比较中间值
             right=mid-1;
       }else if(nums[mid]<target){
           left=mid+1;
       }else{
           return mid;
       }
       }
       return left;
     }
 }

4.有重复元素的二分

 
class Solution {
     public int[] searchRange(int[] nums, int target) {
            int left=0;
            int right=nums.length-1;
            int mid=0;
            int index=0;
            while(left<=right){
                mid=(left+right)/2;
             int   num=nums[mid];
                if(num>target){
                    right=mid-1;
                }else if(num<target){
                    left=mid+1;
                }else {
                    index=mid;
                    break;
                }
 ​
            }
          
            if(left>right){
            int[]arr={-1,-1};
         return arr;
         }else
     {
          int start=index;
          int end=index;
          while(--start>=0&&start<nums.length&&nums[start]==target);
          while(++end>=0&&end<nums.length&&nums[end]==target);
          int arr[]={start+1,end-1};
          return arr;
          
     }
 ​
 }
 }
 ​
  • 8
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值