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;
    }
}
相关推荐
martian6657 分钟前
Spring Boot后端开发全攻略:核心概念与实战指南
java·开发语言·spring boot
跟着珅聪学java2 小时前
spring boot +Elment UI 上传文件教程
java·spring boot·后端·ui·elementui·vue
我命由我123452 小时前
Spring Boot 自定义日志打印(日志级别、logback-spring.xml 文件、自定义日志打印解读)
java·开发语言·jvm·spring boot·spring·java-ee·logback
lilye662 小时前
程序化广告行业(55/89):DMP与DSP对接及数据统计原理剖析
java·服务器·前端
徐小黑ACG3 小时前
GO语言 使用protobuf
开发语言·后端·golang·protobuf
想跑步的小弱鸡5 小时前
Leetcode hot 100(day 3)
算法·leetcode·职场和发展
战族狼魂6 小时前
CSGO 皮肤交易平台后端 (Spring Boot) 代码结构与示例
java·spring boot·后端
xyliiiiiL7 小时前
ZGC初步了解
java·jvm·算法
杉之7 小时前
常见前端GET请求以及对应的Spring后端接收接口写法
java·前端·后端·spring·vue
hycccccch8 小时前
Canal+RabbitMQ实现MySQL数据增量同步
java·数据库·后端·rabbitmq