0
点赞
收藏
分享

微信扫一扫

剑指offer5----搜索算法

秀儿2020 2022-02-09 阅读 29

53 数字在升序数组中出现的次数

给定一个长度为 n 的非降序数组和一个非负数整数 k ,要求统计 k 在数组中出现的次数
要求:空间复杂度 O(1),时间复杂度 O(logn)

思路:二分法。

1.mid=array.length/2   ; 分成[0,mid] [mid+1;length-1]
    if(array[mid]<k)    则对[mid+1;length-1]二分,否则在[0,mid]二分。

2.设置-1,以说明没找到,没找到就回0

3.找到mid 后,看之前之后一位在不在下标范围内且等不等于k,若相等继续推,不等直接返回mid
    递归写法,while都行*/

public class Solution {
    public int GetNumberOfK(int [] array , int k) {
        if(array == null || array.length == 0)  return 0;
        int first=GetFirst( 0, array.length-1, k,array);
        int last=GetLast( 0, array.length-1, k,array);
         if(first > -1 && last > -1) return last - first + 1;//找到了,就做差+1
         return 0;//如果左右都是-1,说明没有找到K,应该直接返回0
    }
    
    int GetFirst(int start,int end,int k,int[] arr){
        if(start>end) return -1;
        int mid=start+(end-start)/2;
        if(arr[mid]>k) return GetFirst(start,mid-1,k,arr);
        if(arr[mid]<k) return GetFirst(mid+1,arr.length-1,k,arr);
        else{ //最大困惑是怎么找前面的k....若前面那个数也==k那么继续递归
            if(mid-1>=0&&arr[mid-1]==k) return GetFirst(start,mid-1,k,arr);
            else return mid;}
                                                   }
     int GetLast(int start,int end,int k,int[] arr){
         while(start<=end){
             int mid=start+(end-start)/2;
              if(arr[mid]>k)    end=mid-1;
             else if(arr[mid]<k)   start=mid+1;
             else{
                 if(mid+1<=end&&arr[mid+1]==k) start=mid+1;
                 else return mid; }
             mid=(start+end)<<2; }
          return -1;
      }
}

4 二维数组中的查找

在一个二维数组array中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

[[1,2,8,9],[2,4,9,12],[4,7,10,13],[6,8,11,15]]

给定 target = 7,返回 true。

给定 target = 3,返回 false。
进阶:空间复杂度 O(1)O(1) ,时间复杂度 O(n+m)

思路:从左下角看,若大于则右,小于则上,等于则返回(行列一定要在范围内)

public class Solution {
    public boolean Find(int target, int [][] array) {
         int row=array.length-1;
         int low=0;
        while(row>=0&&low<=array[0].length-1){
            if(array[row][low]>target) row--;
            else  if(array[row][low]<target) low++;
            else return true;
        }
        return false;
    }
}

11 旋转数组的最小数字

有一个长度为 n 的非降序数组,比如[1,2,3,4,5],将它进行旋转,即把一个数组最开始的若干个元素搬到数组的末尾,变成一个旋转数组,比如变成了[3,4,5,1,2],或者[4,5,1,2,3]这样的。请问,给定这样一个旋转数组,求数组中的最小值。

要求:空间复杂度:O(1) ,时间复杂度:O(logn)

思路:非降序数组,那么以中间值为基准,arr[mid]>arr[end]的话那么最小值应该mid后面;

否则high==mid(即中间值<右边,则以中间值为右边界,因为中间值为分界线,两边都是递增,右边递增包不包括中间元素2说;当中间值==右边边界得时候,那么右边界向前移动继续判断(总会移动到最小值那里)

import java.util.ArrayList;
public class Solution {
    public int minNumberInRotateArray(int [] array) {
        if(array.length<=0) return 0;
        int low=0; int high=array.length-1;
       
        while(low<high){
            int mid=low+(high-low)/2;
            if(array[mid]>array[high]) low=mid+1;
            else if(array[mid]<array[high]) high=mid;
            else high--;
        }
        return array[low];
    }
}

44 数字序列中某一位的数字

数字以 0123456789101112131415... 的格式作为一个字符序列,在这个序列中第 2 位(从下标 0 开始计算)是 2 ,第 10 位是 1 ,第 13 位是 1 ,以此类题,请你输出第 n 位对应的数字。

思路:【1,9】 1x9=9;  [10,99]  2x90=180;  [100,999] 3x900=2700

1.先求n在哪个区间里面 n-9-180-2700直到小于0即可

int base=1;  int count=1;(位数)

while(n-base*9*count>0){

n-=9*base*count;base=base*10;count++;

}//循环结束时候的base是我们的区间的起始值,这时候的n也是....'

2.对n取余,若无余数就是之前哪个数//191-189=2--100,193-189=4--101

int len=n%count; int num=base+(n-1)/count;

import java.util.*;
public class Solution {
    public int findNthDigit (int n) {
       int count=1;//每一个区间的位数
        int base=1;
        while(n-9*base*count>0){ //190
            n-=9*base*count;//181-180=1
            base=base*10;
            count++; }
        //while循环出来得到n已经到了数值所处的区间,以及位数,
        //base区间起步
         int curNum=(n-1)/count+base;//所求num
        int resDigit = 0;
        for (int i=n%count; i<count; i++){
             resDigit = curNum % 10;
            curNum /= 10;
        }
          return resDigit;
    }
}
举报

相关推荐

0 条评论