Java二分查找指定元素、查找数组中只出现一次的数字、搜索有序数组中某元素插入位置

二分查找指定元素

/*
* 需求:
* 给定一个数组,判断是否包含某个值,如果包含则返回其下标,否则返回-1
* 顺序查找:
*   1 遍历,循环比较
*   2 如果有和目标元素相等,返回下标
*   3 如果循环结束,没有相等的,返回-1
* 缺点:查询效率低,如果有100万个数据,恰好查询值在末尾,时间复杂度则为100万,数据量小时使用
* 二分查找:
*   1 建立在排序的基础上
*   2 数据没有重复元素,如果有,先找到之前一个
*   3 用于查找固定有序的数
*   实现:
*       1 确定起始和结束位置
*       2 确定中间数据,判断是否为目标数据。若是直接返回
*       3 若目标数据小于中间数据,起始值不变,结束值为中间值减一
*       4 若目标数据大于中间数据,结束值不变,起始值为中间值加一
*       5 若起始值大于结束值,结束比较,说明不存在
*       6 循环执行
* */
public class Array_BinarySearch {
    public static void main(String[] args) {
        int[] nums = {2,3,1,5,6,0};
        int value = 5;

        int result = m2(nums, value);
        System.out.println(result);
    }
    public static int m1(int[] nums, int value){
        // 顺序查找
        for (int i = 0; i < nums.length; i++) {
            if (nums[i]==value) return i;
        }
        return -1;
    }
    public static int m2(int[] nums, int value){
//        Arrays.sort(nums);
        int count = 0; // 计算查找次数

        int startPos = 0; // 起始位置
        int endPos = nums.length - 1; // 结束位置
        int middle = (startPos+endPos) / 2; // 中间位置

        // 若起始值大于结束值,结束比较
        while (startPos<=endPos){
            count++;
            if (nums[middle]==value){ // 判断目标数据是否等于中间值
                System.out.println("count:"+count);
                return middle;
            }else if (nums[middle]>value){ // 判断目标数据是否小于中间值
                endPos = middle - 1;
            }else if (nums[middle]<value){ // 判断目标数据是否大于中间值
                startPos = middle + 1;
            }
            middle = (startPos+endPos) / 2; // 重新计算中间值
        }
        System.out.println("count:"+count);
        return -1;
    }
}
// 方法声明:[修饰符列表] 返回值类型 方法名(参数列表){方法体}

/*
* 基本数据类型 保存值的大小,引用数据类型保存内存地址,Java中string是引用
* 传值:基本类型传递
*
* 值传递(pass by value)是指在调用函数时将实际参数复制一份传递到函数中,
*   这样在函数中如果对参数进行修改,将不会影响到实际参数
* 引用传递(pass by reference)是指在调用函数时将实际参数的地址直接传递到函数中,
*   那么在函数中对参数所进行的修改,将影响到实际参数
* */

查找数组中只出现一次的数字

/*
* 只出现一次的数字
*   给定一个非空整数数组,除了某个元素只出现一次外,其余元素均出现2次,找出只出现一次的元素,不使用额外的数组空间
*   实例:
*   输入:{2,2,1}  输出:1
*   输入:{2,4,1,2,1}  输出:4
* */
public class SearchOnly {
    public static void main(String[] args) {
        int[] nums = {2,1,4,4,2,1};

        int result = searcher(nums);
        System.out.println(result);
    }
    public static int searcher(int[] nums){

        for (int i = 0; i < nums.length; i++) {
            // 假设所有元素都是单个的,标记为false
            boolean flag = false;
            for (int j = 0; j < nums.length; j++) {
                // 判断是否有元素出现第二次
                // i!=j说明不是同一个位置上的元素
                // nums[i]==nums[j]说明有元素出现第二次
                if (i!=j && nums[i]==nums[j]){
                    // 下表不等,有成对的情况,标记为true
                    flag = true;
                    // 说明有相同元素,终止内层循环,找下一个数
                    break;
                }
            }
            // 判断该数是否为单个
            if (!flag){
                return nums[i];
            }
        }
        // 没有任何一个数是的单个,返回-1
        return -1;
    }
}

搜索有序数组中某元素插入位置

/*
* 搜索插入位置:
* 给定一个排序数组和一个目标值,在数组中查找目标值,返回其索引,若目标值不存在,返回它将要被按顺序插入的位置
* 假设数组无重复元素
* 示例:
* 输入:{1,3,5,6} ,5   输出:2
* 示例:
* 输入:{1,3,5,6} ,4   输出:2
*
* 思路:
*   1.数组有序
*   2.升序:如果目标值等于当前位,返回索引。如果大于上一位,且小于下一位,则为插入位置。都不满足则插入末尾
*   3.降序:如果目标值等于当前位,返回索引。如果小于上一位,且大于下一位,则为插入位置。都不满足则插入末尾
* */
public class InsertLocation {
    public static void main(String[] args) {
//        int[] nums = {1,3,5,6};
        int[] nums = {8,6,5,3,1};
        int number = 2;

        int result = test(nums, number);
        System.out.println(result);
    }
    public static int test(int[] nums, int number){

        for (int i = 0; i < nums.length; i++) {
            if (nums[0]<nums[1]){ // 升序

                if (number<=nums[i]) return i;
            }else if (nums[0]>nums[1]){ // 降序

                if (number>=nums[i]) return i;
            }
        }
        /*
        * 如果执行到这里,说明上面return没有执行
        * 说明number比数组中所有元素都大或都小
        * 则应插入到最后
        * */
        return nums.length;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值