二分查找+双指针暴力算法(LeetCode刷题!!!)
跟着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 后查看