LeetCode——二分查找

二分查找

分类:1)找某个数;2)找左边界;3)找右边界

注意点:1)mid = left + (right - left) / 2

​ 2)if中的判断条件,目的是把数组分开,确定更小的搜索区间

1.搜索插入位置35简单

java 复制代码
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 (nums[mid] == target) {
                return mid;
            } else if (nums[mid] < target) {
                left = mid + 1;
            } else if (nums[mid] > target) {
                right = mid - 1;
            }
        }
        // if (left > nums.length) {
        //     return left + 1;
        // }
        // return left;
        return left;
    }
}

记录:数组是排序好的,从中找到目标值,返回索引。定义初始搜索区间[0, n - 1],是个闭区间,所以结束循环的条件是left <= right,计算mid,调整搜索区间:如果mid的值大于target,说明右半部分区间都大于target,就要缩小搜索区间到左半部分;如果mid的值小于target,说明左半部分区间都小于target,就要缩小搜索区间到右半部分,直到找到target返回下标或者数组中不存在target。

2. 搜索二维矩阵 74中等

java 复制代码
class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        // 循环判断target是否在某行中
        int m = matrix.length;
        int n = matrix[0].length;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (matrix[i][j] >= matrix[i][0] && matrix[i][j] <= matrix[i][n-1]) {
                    // 二分查找
                    int left = 0;
                    int right = n - 1;
                    while (left <= right) {
                        int mid = left + (right - left) / 2;
                        if (matrix[i][mid] == target) {
                            return true;
                        } else if (matrix[i][mid] > target) {
                            right = mid - 1;
                        } else if (matrix[i][mid] < target) {
                            left = mid + 1;
                        }
                    }
                } else {
                    continue;
                }
            }
        }
        // 在某行中使用二分查找
        return false;
    }
}

记录:二维有序,所以先确定要搜索的行,在某行中进行二分查找,找到target。

3. 在排序数组中查找元素的第一个和最后一个位置 34 中等

java 复制代码
class Solution {
    public int[] searchRange(int[] nums, int target) {
        // 定义二位result数组存放结果
        int[] result = new int[2];
        result[0] = -1;
        result[1] = -1;
        // if (nums.length == 0) {
        //     return result;
        // }
        // if (nums.length == 1 && nums[0] != target) {
        //     return result;
        // }
        // 同时寻找左边界和右边界,l_代表左边界,r_代表右边界
        int l_left = 0;
        int l_right = nums.length;
        int r_left = 0;
        int r_right = nums.length;
        // 左边界
        while (l_left < l_right) {
            int mid = l_left + (l_right - l_left) / 2;
            if (nums[mid] == target) {
                l_right = mid;
            } else if (nums[mid] < target) {
                l_left = mid + 1;
            } else if (nums[mid] > target) {
                l_right = mid;
            }
        }
        // 右边界
        while (r_left < r_right) {
            int mid = r_left + (r_right - r_left) / 2;
             if (nums[mid] == target) {
                r_left = mid + 1;
             } else if (nums[mid] < target) {
                r_left = mid + 1;
             } else if (nums[mid] > target) {
                r_right = mid;
             }
        }

        if (l_left < nums.length && nums[l_left] == target) {
            result[0] = l_left;
        }
        // 这里的条件一定要注意!!!
        if (r_left - 1 >= 0 && r_left - 1 < nums.length && nums[r_left - 1] == target) {
            result[1] = r_left - 1;
        }

    return result;
    }
}

记录:题目中寻找第一个和最后一个位置,相当于搜索左边界和右边界,将问题转换后按逻辑写。

4. 搜索旋转排序数组 33 中等

java 复制代码
// 思路一:排序后进行二分查找
// 思路二:找到旋转点,分成左右两部分,比较一下target和两部分的开始值,确定其中一部分进行二分查找------>最后计算一下在原nums中的下标
// 思路三:直接二分,判断两边那边有序,在顺序区间二分,如果没在,再分为有序和乱序两部分
// 思路二
// class Solution {
//     public int search(int[] nums, int target) {
//         int n = nums.length;
//         int index = 0;
//         for (int i = 1; i < n; i++) {
//             if (nums[i] <= nums[i - 1]) {
//                 index = i;
//                 break;
//             }
//         }
//         int left = 0;
//         int right = n - 1;
//         // 设个标识标记是前半部分还是后半部分
//         int flag = 0; // 0表示二分前半部分,1表示二分后半部分
//         // 判断一下二分前一部分,还是后一部分
//         if (nums[0] > target) {
//             left = index;
//             flag = 1;
//         } else {
//             if (index != 0) {
//                 right = index - 1;
//             }
//         }
//         // 二分
//         while (left <= right) {
//             int mid = left + (right - left) / 2;
//             if (nums[mid] == target) {
//                 // if (flag == 0) {
//                 //     System.out.println("111");
//                 //     return mid + (n - index);
//                 // }
//                 // return mid - index;
//                 return mid;
//             } else if (nums[mid] < target) {
//                 left = mid + 1;
//             } else if (nums[mid] > target) {
//                 right = mid - 1;
//             }
//         }
//         return -1;
//     }
// }

// 思路三
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 (nums[mid] == target) {
                return mid;
            } else if (nums[mid] >= nums[left]) {
                // 主要是判断下次是选顺序区间还是乱序区间
                // 左半部分有序
                if (nums[mid] > target && target >= nums[left]) {
                    right = mid - 1;
                } else {
                    left = mid + 1;
                }
                // if (nums[left] < nums[mid] && nums[left] >= target) {
                //     left = mid + 1;
                // } else {
                //     right = mid - 1;
                // }
            } else if (nums[mid] <= nums[right]) {
                // 右半部分有序
                // if (nums[left] > target) {
                //     left = mid + 1;
                // } else {
                //     right = mid - 1;
                // }
                if (nums[mid] < target && target <= nums[right]) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }
            System.out.println("left:" + left + "--mid:" + mid);
        }
        return -1;
    }
}

5. 寻找旋转排序数组中的最小值 153 中等

java 复制代码
// 思路一:排序后第一个
// class Solution {
//     public int findMin(int[] nums) {
//         Arrays.sort(nums);
//         return nums[0];
//     }
// }

// // 思路二:本身有序,旋转是向后移一位------>找到中间点
// class Solution {
//     public int findMin(int[] nums) {
//         int n = nums.length;
//         int result = nums[0];
//         for (int i = 1; i < n; i++) {
//             if (nums[i] < nums[i-1]) {
//                 result = nums[i];
//                 break;
//             }
//         }
//         return result;
//     }
// }

// 思路三:二分查找
class Solution {
    public int findMin(int[] nums) {
        int left = 0;
        int right = nums.length - 1;
        int minValue = 5001;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (nums[left] <= nums[mid]) {
                minValue = Math.min(minValue, nums[left]);
                left = mid + 1;
            } else {
                minValue = Math.min(minValue, nums[mid]);
                right = mid - 1;
            }
        }
        return minValue;
    }
}
相关推荐
巨大八爪鱼5 分钟前
XP系统下用mod_jk 1.2.40整合apache2.2.16和tomcat 6.0.29,让apache可以同时访问php和jsp页面
java·tomcat·apache·mod_jk
码上一元2 小时前
SpringBoot自动装配原理解析
java·spring boot·后端
计算机-秋大田2 小时前
基于微信小程序的养老院管理系统的设计与实现,LW+源码+讲解
java·spring boot·微信小程序·小程序·vue
魔道不误砍柴功4 小时前
简单叙述 Spring Boot 启动过程
java·数据库·spring boot
失落的香蕉4 小时前
C语言串讲-2之指针和结构体
java·c语言·开发语言
枫叶_v4 小时前
【SpringBoot】22 Txt、Csv文件的读取和写入
java·spring boot·后端
wclass-zhengge4 小时前
SpringCloud篇(配置中心 - Nacos)
java·spring·spring cloud
路在脚下@4 小时前
Springboot 的Servlet Web 应用、响应式 Web 应用(Reactive)以及非 Web 应用(None)的特点和适用场景
java·spring boot·servlet
黑马师兄4 小时前
SpringBoot
java·spring
数据小小爬虫4 小时前
如何用Java爬虫“偷窥”淘宝商品类目API的返回值
java·爬虫·php