力扣35题-搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。
示例 1:
输入: [1,3,5,6], 5
输出: 2
示例 2:
输入: [1,3,5,6], 2
输出: 1
示例 3:
输入: [1,3,5,6], 7
输出: 4
示例 4:
输入: [1,3,5,6], 0
输出: 0

做这个题之前,我是没有二分法的思路的,想到的就是暴力for循环遍历,时间复杂度为O(n),代码如下:

class Solution {
    public int searchInsert(int[] nums, int target) {
        if (nums == null || nums.length == 0 || target == 0) {
            return 0;
        }

        for (int i = 0; i < nums.length; i++) {
            if (nums[i] == target) {
                return i;
            }

            if (target < nums[i]) {
                return i - 1 > 0 ? i : 0;
            }

            if (i + 1 == nums.length) {
                return nums.length;
            }

            if (target > nums[i] && target <= nums[i + 1]) {
                return i + 1;
            }
        }

        return 0;
    }
}

然后内存占用很大:
在这里插入图片描述
看了题解以后发现可以用二分法,然后我又去复习了一遍二分法。

二分法的描述是这样的:

给定一列值,给出一个数字,返回这个数字在这列值中的索引值,如果这个数字没有在这列值当中,返回-1

二分法,原理很简单,但是有一个前提,就是必须是有序的,什么意思呢,就是如果给定一列值,如果我们想要使用二分查找法的话,这列值的顺序,就是必须是一个有序的,所以,我们在拿到一列值的时候,就首先必须得对它排序,然后才能使用二分查找法。那么,怎么去查找呢?就是首先找出这列值靠近中间位置的值,如果这列值的长度是奇数的话,那么就是这列值的中位数,如果是偶数的话,可以找中间的两个值的任意一个即可,找到以后,拿我们要去查找的这个值和中间的这个值去比较,我们记要查找的值为a,中间的那个值为b,如果a>b,那么就说明,a有可能在b的左边,但是一定不可能在b的右边,当然,如果a==b的话,那么我们就找到了,可以直接返回。如果a<b的话,那么就说明,a有可能在b的右边,但是一定不可能在b的左边,然后我们此时将我们要查找的这列值缩短一下,怎么缩短呢?如果a>b,那么我们就把[0,b]作为新的一列值,如果a<b,那么我们就把[b,值长度]作为新的一列值,再按照上面的思路一直找下去,直到找到最后一个元素,如果没有找到,返回-1

代码也很简单,力扣上也有对应的题目,顺便可以做了然后AC加一
https://leetcode-cn.com/problems/binary-search/

	public int search(int[] nums, int target) {
        int result = Arrays.binarySearch(nums,target);
        return result < 0 ? -1 : result;
    }

你以为是上面这样?不不不,我就是皮一下,这个是Java自带的二分查找,我们需要自己实现一个算法:

class Solution {
    public int search(int[] nums, int target) {
        int left = 0;
        int right = nums.length;

        while (left <= right) {
            int middle = (left + right) / 2;
            if (middle >= nums.length) {
                return -1;
            }
            if (nums[middle] > target) {
                right = middle - 1;
            } else if (nums[middle] < target) {
                left = middle + 1;
            } else {
                return middle;
            }
        }

        return -1;
    }
}

首先,我们定义left和right值分别为0和数组的长度,确保我们能够从左查找到右,然后我们定义一个while循环,用于遍历,跳出循环的条件就是left>right的时候,因为这个时候说明我们已经查找完了,然后我们去计算最中间的那个数,有可能你会问,int middle = (left + right) / 2;不用考虑小数的情况吗?其实不用特意的去计算,直接向上取整就行,然后下面一部为了防止要查找的数字到最后一个还没找到,加了一个判断,直接返回-1,接着我们去判断,如果中间的那个数大于我们的target,那么我们就把中间的这个数-1,然后给right,否则+1给left,如果相等,直接返回。

那么,最开始的我们那个题目,怎么使用二分法呢?代码如下:

class Solution {
    public int searchInsert(int[] nums, int target) {
        int n = nums.length;
        int left = 0, right = n - 1, ans = n;
        while (left <= right) {
            int mid = ((right - left) >> 1) + left;
            if (target <= nums[mid]) {
                ans = mid;
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return ans;
    }
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值