面试之基础算法题:求一个数字在给定的已排序数组中出现的起始、终止索引号(Java版)

勤奋不是嘴上说说而已,而是实际的行动,在勤奋的苦度中持之以恒,永不退却。业精于勤,荒于嬉;行成于思,毁于随。在人生的仕途上,我们毫不迟疑地选择勤奋,她是几乎于世界上一切成就的催产婆。只要我们拥着勤奋去思考,拥着勤奋的手去耕耘,用抱勤奋的心去对待工作,浪迹红尘而坚韧不拔,那么,我们的生命就会绽放火花,让人生的时光更加的闪亮而精彩。

导读:本篇文章讲解 面试之基础算法题:求一个数字在给定的已排序数组中出现的起始、终止索引号(Java版),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

题目

给定一个升序的整数数组,查找某一个值在数组中出现的索引号,例如,输入数组[2, 3, 3, 4, 4, 5];查找的数是3,则返回[1, 2]。时间复杂度要求为O(logN)。

思路

基本上大致思考一番,就知道可以用二分查找法求解。
然后因为java不能在一个方法里面返回两个int常量,当然返回一个List<Integer>另当别论,此处的思路就是两个查找方法,分别查找起始索引和终止索引。
起始索引:
起始索引的定位,首先比较中间的数和要查找的数 target,如果 target 小于中间的数,那么在数组的左半部分继续查找,如果 target 大于中间的数,在数组的右半部分继续查找;如果 target 和中间的数相等,那么比较中间数字的前一个数字是否和 target 相等,如果不相等,那么当前的中间索引就是起始索引,如果相等,那么继续在前半部分查找;
类似地,定位终止索引时,如果 target 和中间的数相等时,那么比较中间数字的后一个数字是否和 target 相等,如果不相等,那么当前的中间索引就是终止索引,如果相等,那么继续在后半部分查找。

实现

package algorithm.interview;

/**
 * Author: Johnny
 * Date: 2018/5/15
 * Time: 22:02
 * 给定一个升序的整数数组,查找某一个值在数组中出现的索引号,例如,输入数组2,3,3,4,4,5;查找的数是3,则返回1,2。时间复杂度要求为O(logN)
 */
public class GetFirstLastIndex {
public static void main(String[] args) {
        int[] sortedArray = {1, 1, 2, 3, 3, 6, 6, 6, 6, 9, 9, 10};
        int length = sortedArray.length;
        int target = 6;
        System.out.println(getFirstTarget(sortedArray, length, target, 0, length - 1));
        System.out.println(getSecondTarget(sortedArray, length, target, 0, length - 1));
    }

    /**
     * 寻找开始索引
     */
    static int getFirstTarget(int[] array, int n, int target, int nStart, int nEnd) {
        if (nStart > nEnd) {
            // 返回-1表示没有待查询的元素
            return -1;
        }
        // 中间索引
        int nMid = nStart + ((nEnd - nStart) >> 1);
        int nMidData = array[nMid];

        while (nStart <= nEnd) {
            if (target > nMidData) {
                nStart = nMid + 1;
            } else if (target < nMidData) {
                nEnd = nMid - 1;
            } else {
                if ((target != array[nMid - 1] && nMid > 0) || nMid == 0) {
                    return nMid;
                } else {
                    nEnd = nMid - 1;
                }
            }
            // 更新中间值得索引和值
            nMid = nStart + ((nEnd - nStart) >> 1);
            // 数组越界判断
            if (nMid < 0) {
                return -1;
            }
            nMidData = array[nMid];
        }
        return -1;
    }

    /**
     * 寻找结束索引
     */
    static int getSecondTarget(int[] array, int n, int target, int nStart, int nEnd) {
        if (nStart > nEnd) {
            return -1;
        }
        // 中间索引
        int nMid = nStart + ((nEnd - nStart) >> 1);
        int nMidData = array[nMid];

        while (nStart <= nEnd) {
            if (target > nMidData) {
                nStart = nMid + 1;
            } else if (target < nMidData) {
                nEnd = nMid - 1;
            } else {
                if ((target != array[nMid + 1] && nMid < n) || nMid == n - 1) {
                    return nMid;
                } else {
                    nStart = nMid + 1;
                }
            }
            //更新中间值得索引和值
            nMid = nStart + ((nEnd - nStart) >> 1);
            if (nMid < 0) {
                return -1;
            }
            nMidData = array[nMid];
        }
        return -1;
    }   
}

变形

上面的问法可以经过变形,换一种表现形式来提问:

  1. 假设给定一个有序的整型数组arr,以及整数 k,问k在数组中出现几次?
    根据上面求得的first_index和last_index,即可得到出现次数为: (last_index - first_index) + 1

参考

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/142374.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!