牛客网剑指offer-搜索算法(java实现)

一、JZ53 数字在升序数组中出现的次数(简单)

1、暴力法,直接遍历记录出现的次数

public class Solution {
    public int GetNumberOfK(int [] array , int k) {
       int n = 0;
       for(int item: array) {
           if(item == k) n=n+1;
       }
       return n;
    }
}

2、使用二分法找到对应的左右位置

public class Solution {
    //二分查找
    private int bisearch(int[] data, double k){ 
        int left = 0;
        int right = data.length - 1;
        //二分左右界
        while(left <= right){ 
            int mid = (left + right) / 2;
            if(data[mid] < k)
                left = mid + 1;
            else if(data[mid] > k)
                right = mid - 1;
        }
        return left;
    }
    public int GetNumberOfK(int [] array , int k) {
        //分别查找k+0.5和k-0.5应该出现的位置,中间的部分就全是k
        return bisearch(array, k + 0.5) - bisearch(array, k - 0.5);
    }
}

二、JZ4 二维数组中的查找(中等)

1、暴力法,直接两次遍历

public class Solution {
    public boolean Find(int target, int [][] array) {
        for(int i= 0;i < array.length;i++) {
            for(int j= 0;j < array[i].length; j++) {
                if(array[i][j] == target) return true;    
            }
        }
        return false;
    }
}

2、先确定在哪一列,再遍历这一列是否有该值

public class Solution {
    public boolean Find(int target, int [][] array) {
        //优先判断特殊
        if(array.length == 0)  
            return false;
        int n = array.length;
        if(array[0].length == 0)  
            return false;
        int m = array[0].length;
        //从最左下角的元素开始往左或往上
        for(int i = n - 1, j = 0; i >= 0 && j < m; ){ 
            //元素较大,往上走
            if(array[i][j] > target)   
                i--;
            //元素较小,往右走
            else if(array[i][j] < target) 
                j++;
            else
                return true;
        }
        return false;
    }
}

三、JZ11 旋转数组的最小数字(简单)

1、二分查找

import java.util.ArrayList;
public class Solution {
    public int minNumberInRotateArray(int [] array) {
        // 特殊情况判断
        if (array.length== 0) {
            return 0;
        }
        // 左右指针i j
        int i = 0, j = array.length - 1;
        // 循环
        while (i < j) {
            // 找到数组的中点 m
            int m = (i + j) / 2;
            // m在左排序数组中,旋转点在 [m+1, j] 中
            if (array[m] > array[j]) i = m + 1;
            // m 在右排序数组中,旋转点在 [i, m]中
            else if (array[m] < array[j]) j = m;
            // 缩小范围继续判断
            else j--;
        }
        // 返回旋转点
        return array[i];
    }
}

四、字符串的排列(中等)

1、回溯+交换

import java.util.ArrayList;
import java.util.HashSet;
public ArrayList<String> Permutation(String str) {
        ArrayList<String> result = new ArrayList<String>();
        if(str == null || str.length() == 0) return result;
        char[] charStr = str.toCharArray();
        HashSet<String> resSet = new HashSet<String>();
        Permutation(charStr,0,resSet);
        result.addAll(resSet);
        return result;
    }

    public void Permutation(char[] chars,int begin,HashSet<String> hashSet){
        if(chars==null || chars.length==0 || begin<0 || begin>chars.length-1) { return ; }
        if(begin == chars.length-1){
            // 使用交换,可以节省原来使用的memo记录数据的空间
            hashSet.add(String.valueOf(chars));
        }else{
            for(int i=begin;i<chars.length;i++){
                swap(chars,begin,i);
                // 设定下标从上一次的下一个下标开始,可以减少循环次数
                Permutation(chars,begin+1,hashSet);
                swap(chars,begin,i);
            }
        }
    }

    public void swap(char[] chars,int begin,int i){
        char temp = chars[begin];
        chars[begin] = chars[i];
        chars[i] = temp;
    }

五、JZ44 数字序列中某一位的数字(简单)

1、step 1:通过对每个区间起点数字的计算,按照上述规律求得该区间的位数,n不断减去它前面区间的位数,定位到属于它的区间。step 2:通过除以位数定位n在哪个数字上,用字符串形式表示。step 3:通过在字符串上位置对几位数取模定位目标数字。

import java.util.*;
public class Solution {

    public int findNthDigit (int n) {
         //位数,起始数字
        int bit = 1, start = 1;
         //记录当前区间之前总共有多少位数字
        long count = 9l;
        //将n定位在某个位数的区间中
        while(n > count) {
            n -= count;
            start *= 10;
            bit += 1;
            //该区间的总共位数
            count = Integer.toUnsignedLong(9*start*bit);
        }
        //定位n在哪个数字上
        String num = String.valueOf((n-1) / bit + start);
        //定位n在数字的哪一位上
        int r = (n-1)%bit;
        return Integer.parseInt(num.substring(r, r+1));
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值