数组、二分查找|LeetCode 704、35、34

报名了代码随想录的训练营,督促着学习总是好的,结果这两天因为生病给耽误了,昨天把前面两天的题目给写了一下,今天补一下博客。这种每天的训练营就适合我这种喜欢凑合的,没有这种再不干就干不完的紧迫感给我,我就能一直拖哈哈哈!

前两天针对数组模块知识点做回顾,数组这块两个核心知识点就是二分查找跟双指针思想。数组第一部分针对二分查找,第二部分针对双指针。

二分查找

思想:降低查找算法的时间复杂度。核心问题是要搞明白合法区间。

涉及细节:

1、整型数据可能的溢出

int mid = (left + (right-left)/2)

2、循环判断要加上无法满足条件的返回语句

return -1;

3、算法使用的前提条件

有序数组&&无重复元素

4、区间问题

左闭右闭:

while(left<=right){...}

left=mid+1;

right =mid -1;

左闭右开

while(left<right){...}

left=mid +1;

right =mid;

Tips:

死记硬背法:带有闭区间的,左右更新的时候需要±1。

二分查找常规题目

LeetCode 704 题目描述+解答

解题思路:这里是属于左闭右闭的情况。

Java代码:

/**
  * 题目Id:704; 
  * 题目:二分查找,binary-search; 
  * 日期:2023-10-26 16:57:47
*/

//给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否
//则返回 -1。 
//
// 示例 1: 
//
// 输入: nums = [-1,0,3,5,9,12], target = 9
//输出: 4
//解释: 9 出现在 nums 中并且下标为 4
// 
//
// 示例 2: 
// 输入: nums = [-1,0,3,5,9,12], target = 2
//输出: -1
//解释: 2 不存在 nums 中因此返回 -1
//
// Related Topics 数组 二分查找 

class Solution {
    public int search(int[] nums, int target) {
        int left =0;
        int right = nums.length-1;
        while (left <= right){
            int mid = left + ((right -left)/2);
            if (target < nums[mid]) {
                right = mid -1 ;
            }else if (target>nums[mid]) {
                left = mid+1;
            }else if (target == nums[mid]) {
                return mid;
            }
        }
        return -1;
    }
}

}

二分查找拓展题目

LeetCode 35 题目描述+解答

解题思路:这里就是如果target不在数组中,那就返回这个元素该插入的位置,不要看错题目。如果不在数组中,那么应该返回的是最终查找的位置,这个位置就是他应该插入到的位置,也就是left/right指向的位置。

Java代码:

/**
  * 题目Id:35; 
  * 题目:搜索插入位置,search-insert-position; 
  * 日期:2023-10-26 17:15:58
*/

//给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 
// 请必须使用时间复杂度为 O(log n) 的算法。 
//
// 
//
// 示例 1: 
//输入: nums = [1,3,5,6], target = 5
//输出: 2
// 
//
// 示例 2: 
//输入: nums = [1,3,5,6], target = 2
//输出: 1
// 
//
// 示例 3: 
//输入: nums = [1,3,5,6], target = 7
//输出: 4

class Solution {
    public int searchInsert(int[] nums, int target) {
            int left =0;
            int right = nums.length-1;
            while (left <= right){
                int mid = left + ((right -left)/2);
                if (target < nums[mid]) {
                    right = mid -1 ;
                }else if (target>nums[mid]) {
                    left = mid+1;
                }else if (target == nums[mid]) {
                    return mid;
                }
            }
            return left;
    }
}

}

LeetCode 34 题目描述+解答

解题思路:这道题目比前面的复杂一些,这里的数组中有重复元素。需要返回找到的第一个元素和最后一个。直接二分法,可能找到的元素是位于重复序列的中间,所以需要加上一个判断找到元素是否为序列第一个和最后一个的语句。 拆成了两个函数来写,分别返回第一个和最后一个元素的index。 这里也就是将二分查找加了一个判断找到元素是否为第一个/最后一个元素的语句。

Java代码:

/**
  * 题目Id:34; 
  * 题目:在排序数组中查找元素的第一个和最后一个位置,find-first-and-last-position-of-element-in-sorted-array; 
  * 日期:2023-10-26 17:23:08
*/

//给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。
// 如果数组中不存在目标值 target,返回 [-1, -1]。 
// 你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。 
//
// 示例 1: 
//输入:nums = [5,7,7,8,8,10], target = 8
//输出:[3,4] 
//
// 示例 2: 
//输入:nums = [5,7,7,8,8,10], target = 6
//输出:[-1,-1] 
//
// 示例 3: 
//输入:nums = [], target = 0
//输出:[-1,-1] 

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int FirstIndex = searchFirst(nums,target);
        int LastIndex = searchLast(nums,target);
        return new int[] {FirstIndex,LastIndex};
    }

    public int searchFirst(int[] nums, int target){
        int right = nums.length-1, left =0;
        while (left <= right){
            int mid = left + ((right -left)/2);
            if (target < nums[mid]) {
                right = mid-1;
            }else if (target > nums[mid]) {
                left = mid+1;
            } else if (target == nums[mid]) {
                if (mid==0||nums[mid-1]<target){
                    return mid;
                }else {
                    right = mid-1;
                }
            }
        }
        return -1;
    }

    public int searchLast(int[] nums, int target){
        int right = nums.length-1, left =0;
        while (left <= right){
            int mid = left + ((right -left)/2);
            if (target < nums[mid]) {
                right = mid-1;
            }else if (target > nums[mid]) {
                left = mid+1;
            } else if (target == nums[mid]) {
                if (mid==nums.length-1||nums[mid+1] > target){
                    return mid;
                }else {
                    left = mid+1;
                }
            }
        }
        return -1;
    }
}

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值