开始学算法1===>二分查找+双指针暴力算法(LeetCode刷题!!!)

发布于:2022-10-12 ⋅ 阅读:(343) ⋅ 点赞:(0)

跟着carl哥的第一天

今天仔细学了二分查找,跟双指针算法。通过这篇文章可以让你更快认识到二分查找的魅力,以及双指针算法的思想。

二分算法

先上模板

int left = 0; //定义左边界
int right = nums.length - 1; //定义右边界
int mid = 0;
while(left <= right){ //设置循环,直到left > right
	mid = left + ((right - left) / 2); //防止溢出,等同于(left + right) / 2
	if(nums[mid] == target) {
		return mid; //数组中找到目标值,直接返回下标
	} else if (target < nums[mid]) { //目标值在左边界到中间的位置
		right = mid - 1; //所以现在数组范围为[left, mid - 1]
	} else { //target在中间到右边界的位置
		left = mid + 1;
	}
}
return left; //重点!!! 先记住一个点 因为求mid时是向下取整,所以到最后都是left = mid。

先看第一道题

leetcode704.二分查找

给定一个 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 

提示:

  • 你可以假设 nums 中的所有元素是不重复的。
  • n 将在 [1, 10000]之间。
  • nums 的每个元素都将在 [-9999, 9999]之间。

(大家可以想一下,二分查找首先是个什么东西,有一个目标值要查找,然后定位到是在左区域还是右区域,直至到区域缩小至1~2个元素)

答案:::

public class test01 {

    //定义输入输出
    public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    public static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));

	//二分查找
    private static int search(int[] nums, Integer target) {

        //设置两个变量 分别表示左右两个边界
        int left = 0;
        int right = nums.length-1;

        //循环
        while(left <= right) {
            //设置中间值,用来定位target属于左边的一半还是右边的一半
            int mid = (left + right) / 2;
            //如果属于左边的一半 则右边界right移动到刚刚的中间值mid
            if (target <= nums[mid]) {
                right = mid;
            //如果属于右边的一半,则把左边界前移到中间值+1(因为上边是<=,所以nums[mid]属于左边界)
            //则左边界变成mid+1
            } else {
                left = mid + 1;
            }
        }
        //如果到最后没有找到target,则返回-1
        if (nums[left] != target)
            return -1;
        return left;
    }

    public static void main(String[] args) throws IOException {

        //读入一行,并按照空格拆分
        String s = in.readLine();
        String[] str = s.split(" ");
        //获取数组的长度
        int n = str.length;

        //读入一个数字,默认读入String 需要转为int
        Integer target = Integer.parseInt(in.readLine());

        //转为int数组
        int[] nums = new int[n];
        for (int i = 0; i < n; i ++) {
            nums[i] = Integer.parseInt(str[i]);
        }

		//输出答案并冲刷管道,关闭管道
        int count = search(nums, target);
        out.write(count);
        out.flush();
        out.close();
    }
}

再看第二道题

leetcode35.搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。你可以假设数组中无重复元素。

示例 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

思路:其实这道题不是很难,但是要你进一步的理解二分查找 (偷偷说一句,直接用模板就可以ac了,都不需要改代码。。。。) 大家可以试试


答案:

public class test03 {

    public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    public static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
    public static void main(String[] args) throws IOException {

        String[] arr = in.readLine().split(",");
        Integer target = Integer.parseInt(in.readLine());
        int n = arr.length;
        Integer[] nums = new Integer[n];
        for (int i = 0; i < n; i ++) {
            nums[i] = Integer.parseInt(arr[i]);
        }

        int count = searchInsert(nums, target);
        out.write(count);
        out.flush();
        out.close();
    }

    private static int searchInsert(Integer[] nums, Integer target) {

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

        return left;
    }
}

这里需要大家理解的就是为什么直接用模板就能ac?为什么目标值找不到插的位置也跟找到目标值的做法一样, 不需要额外添加判定条件? 为什么返回值是left?

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到