[Android算法初级学习]简单二分法查找

之前一直很迷茫想要提升android技术到底该学什么?到底是系统源码,高级自定义view呢还是java入门基础,包括很多刚开始学习android的新人也是,后来慢慢的深入下去才发现基础真的很重要,想要造高楼,必须打地基给打结实。于是打算开始算法的简单初级学习,为了能够更好地学习高层的知识,把自己的基础稳固下来。

这里我选择的是《算法图解》和《大话数据结构》这两本入门基础级别的书(建议优先看算法图解,因为前者属于启蒙,后面的已经初具规模),可以帮你了解到大概的算法和数据结构的内容。
后期的进阶可以选择《编程之美》、《数据结构和算法java语言描述》、《剑指offer》、《编程珠玑》等书。

网上看到的算法与数据结构从入门到进阶的学习书籍推荐,可以参考一下

接下来就是今天的主角了,简单二分法查找。

二分法查找

相信我们平时项目中会遇到很多查找的情况,比如查找某项在列表中的位置。又或者在联系人中快速找到对应的某个人。如果我们按照顺序查找,万一结果在最后一项且数据量很大的时候,查找的效率就很低,损耗性能。这个时候就体现了二分法的作用了。
注意二分法的前提是列表为有序的才管用。

二分法的逻辑其实很简单,可以参考我们小时候猜数字,1-100猜数字,如果数字大了,我们就取剩下部分的中间数继续猜,小了一样。

  1. 查找的范围,指定低位和高位,即第一位和最后一位
    在这里插入图片描述
  2. 先取中间值,即(low + high)/ 2 ,得到中间值和预期值进行比较,如果小了,范围就从中间值到最高位缩进再次进行取中间值比较,重复如此

在这里插入图片描述
3. 最后如果得到的值和预期值一样就可以返回结果了。

编码实践

 public static void main(String args[]) {
        int[] datas = {1,2,3,4,5,6,7,8,9,10,40,50,60,70};
        int result = binarySearch(datas, 10);
        System.out.print("result position = " + result);
    }

	//查找数组中值的所在位置(采用二分法)
    private static int binarySearch(int[] data, int item) {
        if(data == null || data.length == 0) {
            return -1;
        }
        //低位
        int low = 0;
        //高位
        int high = data.length - 1;
        //一直循环查找,直到找到合数的值,目前不考虑去重
        while (low <= high) {
            int mid = (high + low) / 2;
            //取中间值来比较
            int guess = data[mid];
            if(guess == item) {
                return mid;
            } else if (guess > item) {
                high = mid -1;
            } else {
                low = mid + 1;
            }
        }
        //未找到
        return -1;
    }

结果

result position = 9

元素重复的二分查找法

这样最简单的二分查找的算法掌握了,为啥要说最简单,因为往往现实情况更复杂,会遇到元素重复或者元素乱序的情况。。。一般如果乱序可以先将列表按照一定规则排好序再去进行二分查找,这边我再讲一个元素重复的二分查找

原理其实也很简单,如果我们取到中间值和预期值相等的时候出现了重复元素,我们就可以循环遍历下之前的元素或者之后的元素进行判断取值,如果也是等于预期值,那就把它取出来。当然有可能会遇到全是相同的元素的时候,这个时候这个办法效率又低了。。。(WTF,无底洞的需求和限量的头发)

思路就是上面写的,中间值前后循环遍历取值,不相等就丢掉

编码实践

代码:

 public static void main(String args[]) {
        int[] datas = {1,2,3,4,5,6,7,10,10,10,40,50,60,70};
        List<Integer> results = binarySearchList(datas, 10);
        System.out.print("result position = " + results);
    }

    //查找重复元素的二分法
    private static List<Integer> binarySearchList(int[] data, int item) {
        if(data == null || data.length == 0) {
            return null;
        }
        List<Integer> results = new ArrayList<>();

        int low = 0;
        int high = data.length - 1;

        while(low <= high) {
            int mid = (low + high) / 2;
            int guess = data[mid];
            if(guess == item) {
                if(mid > 0) {
                    //遍历中间值前面的元素,判断是否有重复元素在
                    for(int i = mid - 1; i >= 0; i--) {
                        if(data[i] == item) {
                            results.add(i);
                        } else {
                            //如果不重复直接跳出循环
                            break;
                        }
                    }
                }
                //正常情况取中间值
                results.add(mid);

                if(mid < high) {
                    //同上,遍历中间值后面的元素,判断是否重复
                    for(int i = mid + 1; i <= high; i++) {
                        if(data[i] == item) {
                            results.add(i);
                        } else {
                            break;
                        }
                    }
                }
                return results;
            } else if (guess > item) {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        return results;
    }

结果:

result position = [7, 8, 9]

这样,基本的二分查找就结束了,其实原理都不是很难,只要肯静下心来稍微分析一下就会了。各位如果看到有问题的可以及时反馈。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值