【算法】【优选算法】二分查找算法(下)

目录

  • 一、852.⼭脉数组的峰顶索引
    • [1.1 二分查找](#1.1 二分查找)
    • [1.2 暴力枚举](#1.2 暴力枚举)
  • 二、162.寻找峰值
    • [2.1 二分查找](#2.1 二分查找)
    • [2.2 暴力枚举](#2.2 暴力枚举)
  • 三、153.寻找旋转排序数组中的最⼩值
    • [3.1 二分查找](#3.1 二分查找)
    • [3.2 暴力枚举](#3.2 暴力枚举)
  • [四、LCR 173.点名](#四、LCR 173.点名)
    • [4.1 二分查找](#4.1 二分查找)
    • [4.2 哈希表](#4.2 哈希表)
    • [4.3 暴力枚举](#4.3 暴力枚举)
    • [4.4 位运算](#4.4 位运算)
    • [4.5 数学(求和)](#4.5 数学(求和))

一、852.⼭脉数组的峰顶索引

题目链接:852.⼭脉数组的峰顶索引

题目描述:

题目解析:

  • 给我们一个数组,元素是先递增在递减的,让我们返回最大元素下标。

1.1 二分查找

解题思路:

  • 我们这个数组本来就是一个被天然分成两段,递增区间和递减区间,的数据,天然使用二分查找的题。
  • 当mid的元素小于后一个元素的时候,mid在递增区间,所以left = mid + 1。
  • 当mid的元素大于后一个元素的时候,mid在递减区间,所以right = mid。

解题代码:

java 复制代码
//时间复杂度:O(logN)
//空间复杂度:O(1)
class Solution {
    public int peakIndexInMountainArray(int[] arr) {
        int left = 0;
        int right = arr.length-1;
        while(left < right) {
            int mid = left + (right - left) / 2;
            if(arr[mid] < arr[mid+1]) left = mid + 1;
            else right = mid;
        }
        return left;
    }
}

1.2 暴力枚举

解题思路:

  • 直接使用for循环遍历数组,该下标元素大于前面和后面元素,返回下标。
  • 因为这个数组一定是一个山脉数组,所以不用管数组头和尾。

解题代码:

java 复制代码
//时间复杂度:O(n)
//空间复杂度:O(1)
class Solution {
    public int peakIndexInMountainArray(int[] arr) {
        for(int i = 1; i < arr.length - 1; i++) {
            if(arr[i] > arr[i-1] && arr[i] > arr[i+1]) return i;
        }
        return 0;
    }
}

二、162.寻找峰值

题目链接:162.寻找峰值

题目描述;

题目解析:

  • 给我们的数组是,递增递减反复进行,让我们找到其中一个峰值的下标。
  • 数组可能是这几个情况:1 . /\/\/\ ,2. / ,3. \

2.1 二分查找

解题思路:

  • 其实我们可以将数组分为,有要求峰值和没有要求峰值两段,因为给了峰值不等于下一个元素。
  • 所以当mid小于下一个元素的时候,mid就是在没有要求峰值那段,left = mid+1。
  • 当mid大于下一个元素的时候,mid就是在有峰值那段,right = mid

解题代码:

java 复制代码
//时间复杂度:O(logN)
//空间复杂度:O(1)
class Solution {
    public int findPeakElement(int[] nums) {
        int left = 0;
        int right = nums.length - 1;
        while(left < right) {
            int mid = left + (right - left) / 2;
            if(nums[mid] < nums[mid + 1]) left = mid + 1;
            else right = mid; 
        }
        return left;
    }
}

2.2 暴力枚举

解题思路:

  • 直接转变为求数组最大值下标,遍历数组即可。

解题代码:

java 复制代码
//时间复杂度:O(n)
//空间复杂度:O(1)
class Solution {
    public int findPeakElement(int[] nums) {
        int ret = 0;
        for(int i = 0; i < nums.length; i++) {
            if(nums[i] > nums[ret])  ret = i;
        }
        return ret;
    }
}

三、153.寻找旋转排序数组中的最⼩值

题目链接:153.寻找旋转排序数组中的最⼩值

题目描述:

题目解析:

  • 数组旋转一次就代表将数组尾元素放在数组头。
  • 给我们一个原来升序的数组,旋转多次后,找到数组中最小元素下标。
  • 数组中元素各不相同。
  • 数组会是下面这种状态或者一个完全递增的状态

3.1 二分查找

解题思路:

  • 我们这个数组本来就是已经是被分成两段了的。
  • 我们可以使用nums[ 0 ]或者nums[ nums.length - 1 ]来当分界线。
  • 使用nums[ nums.length - 1 ]为界限:
    • mid元素大于等于界限时,在数组段1,所以left = mid + 1。
    • mid元素小于界限的时候,在数组段2,所以right = mid。
  • 使用nums[ 0 ]为界限:
    • mid元素大于等于界限时,在数组段1,所以left = mid + 1。
    • mid元素小于界限的时候,在数组段2,所以right = mid。
    • 考虑数组完全递增时,nums[0]才是最小值。

解题代码:

java 复制代码
//时间复杂度:O(logN)
//空间复杂度:O(1)
//使用nums[ nums.length - 1 ]为界限:
class Solution {
    public int findMin(int[] nums) {
        int left  = 0;
        int right = nums.length - 1;
        while(left < right) {
            int mid = left + (right - left) / 2;
            if(nums[mid] < nums[nums.length-1]) right = mid;
            else left = mid + 1;
        }
        return nums[left];
    }
}
//使用nums[ 0 ]为界限:
class Solution {
    public int findMin(int[] nums) {
        int left  = 0;
        int right = nums.length - 1;
        while(left < right) {
            int mid = left + (right - left) / 2;
            if(nums[mid] >= nums[0]) left = mid + 1;
            else right = mid;
        }
        if(nums[0] < nums[left]) left = 0;
        return nums[left];
    }
}

3.2 暴力枚举

解题思路;

  • 直接循环遍历数组找最小值即可。

解题代码:

java 复制代码
//时间复杂度:O(n)
//空间复杂度:O(1)
class Solution {
    public int findMin(int[] nums) {
        int ret = nums[0];
        for(int i = 0; i < nums.length; i++) {
            if(nums[i] < ret) ret = nums[i];
        }
        return ret;
    }
}

四、LCR 173.点名

题目链接:LCR 173.点名

题目描述:

题目解析:

  • 给你一个长度为n数组,这个数组中有0到n中的数,按升序排列,找出数组在0到n中不含有的数。

4.1 二分查找

解题思路:

  • 这个数组分为这样两段,一段是下标与元素值相同的,一段是下标是元素值减1。
  • 所以当mid元素等于mid的时候,落在第一段,left = mid + 1;
  • 当mid元素不等于mid的时候,落在第二段,right = mid。

解题代码:

java 复制代码
//时间复杂度:O(logN)
//空间复杂度:O(1)
class Solution {
    public int takeAttendance(int[] records) {
        int left = 0;
        int right = records.length;
        while(left < right) {
            int mid = left + (right - left) / 2;
            if(records[mid] == mid) left = mid + 1;
            else right = mid;
        }
        return left;
    }
}

4.2 哈希表

解题思路:

  • 借助一个数组来标记0到n中出现过的元素。

解题代码:

java 复制代码
//时间复杂度:O(n)
//空间复杂度:O(n)
class Solution {
    public int takeAttendance(int[] records) {
        int[] hash = new int[records.length + 1];
        for(int i = 0; i < records.length; i++) {
            hash[records[i]]++;
        }
        for(int i = 0; i < hash.length; i++) {
            if(hash[i] == 0) return i;
        }
        return 0;
    }
}

4.3 暴力枚举

解题思路:

  • 直接遍历数组,当出现第一个下标和元素不相等的直接返回元素减一即可。
  • 遍历完数组还是没找到,证明是0到n中n不在数组中。

解题代码:

java 复制代码
//时间复杂度:O(n)
//空间复杂度:O(1)
class Solution {
    public int takeAttendance(int[] records) {
        for(int i = 0; i < records.length; i++) {
            if(records[i] != i) return records[i]-1;
        }
        return records.length;
    }
}

4.4 位运算

解题思路:

  • 直接使用一个变量来将0到n的数全部异或。
  • 在于数组元素进行异或。

解题代码:

java 复制代码
//时间复杂度:O(n)
//空间复杂度:O(1)
class Solution {
    public int takeAttendance(int[] records) {
        for(int i = 0; i < records.length; i++) {
            if(records[i] != i) return records[i]-1;
        }
        return records.length;
    }
}

4.5 数学(求和)

解题思路:

  • 直接先将0到n的和求出来。
  • 在减去数组中的元素即可。

解题代码:

java 复制代码
//时间复杂度:O(n)
//空间复杂度:O(1)
class Solution {
    public int takeAttendance(int[] records) {
        int n = records.length;
        int ret = (n*(n+1))/2;
        for(int i = 0; i < records.length; i++) {
            ret = ret - records[i];
        }
        return ret;
    }
}
相关推荐
yava_free15 分钟前
JVM这个工具的使用方法
java·jvm
十七算法实验室24 分钟前
Matlab实现麻雀优化算法优化随机森林算法模型 (SSA-RF)(附源码)
算法·决策树·随机森林·机器学习·支持向量机·matlab·启发式算法
黑不拉几的小白兔35 分钟前
PTA部分题目C++重练
开发语言·c++·算法
迷迭所归处36 分钟前
动态规划 —— dp 问题-买卖股票的最佳时机IV
算法·动态规划
不会编程的懒洋洋43 分钟前
Spring Cloud Eureka 服务注册与发现
java·笔记·后端·学习·spring·spring cloud·eureka
赖龙1 小时前
java程序打包及执行 jar命令及运行jar文件
java·pycharm·jar
U12Euphoria1 小时前
java的runnable jar采用exe和.bat两种方式解决jre环境的问题
java·pycharm·jar
chordful1 小时前
Leetcode热题100-32 最长有效括号
c++·算法·leetcode·动态规划
_OLi_1 小时前
力扣 LeetCode 459. 重复的子字符串(Day4:字符串)
算法·leetcode·职场和发展·kmp
java小吕布1 小时前
Java Lambda表达式详解:函数式编程的简洁之道
java·开发语言