目录

  • 二分查找
    • 1060. 有序数组中的缺失元素
    • 1901. 找出顶峰元素 II
    • ⭐1231. 分享巧克力
    • 1182. 与目标颜色间的最短距离

二分查找

1060. 有序数组中的缺失元素

现有一个按 升序 排列的整数数组 nums ,其中每个数字都 互不相同 。

给你一个整数 k ,请你找出并返回从数组最左边开始的第 k 个缺失数字。

示例 1:

输入:nums = [4,7,9,10], k = 1
输出:5
解释:第一个缺失数字为 5 。

示例 2:

输入:nums = [4,7,9,10], k = 3
输出:8
解释:缺失数字有 [5,6,8,…],因此第三个缺失数字为 8 。

示例 3:

输入:nums = [1,2,4], k = 3
输出:6
解释:缺失数字有 [3,5,6,7,…],因此第三个缺失数字为 6 。

思路:

  1. 局部局部的查找
  2. nums[L]nums[R]找到缺失多少个数字
  3. 如果我在nums[L]nums[R]之间发现的缺失的数字远大于我要找的第k的数字。那我需要找的就是nums[R] + xxx(k-已经发现的缺失的数字)
  4. 如果我在nums[L]nums[R]之间发现的缺失的数字小于我要找的第k个数字,那我就要到里面去好好找找缺失的到底是哪一个了。
  5. 这里的好好找找的就可以采用二分法进行。如果L到mid之间缺失的数大于k,那我再去好好找。如果L到mid之间缺失的数字小于k。那我就可以去mid到R之间找第k-xxx(之前已经发现的缺失的数字的个数)个数字

代码实现:

class Solution {public int missingElement(int[] nums, int k) {int start = 0;int end = nums.length - 1;int temp = helper(nums, start, end);if (k > temp) {//如果发现确实好像还不够我要的,那就是在最后面了return nums[end] + (k - temp);}while (start + 1 < end) {//二分法查找int mid = start + (end - start) / 2;if (helper(nums, start, mid) < k) {//如果还是不够,重新搞k = k - helper(nums, start, mid);start = mid;} else {//如果够了,那我要确定一下end = mid;}}return nums[start] + k;}public int helper(int[] nums, int L, int R) {return (nums[R] - nums[L]) - (R - L);//表示在nums[L]和nums[R]之间还能再插入多少个数字}
}

1901. 找出顶峰元素 II

一个 2D 网格中的 顶峰元素 是指那些 严格大于 其相邻格子(上、下、左、右)的元素。

给你一个 从 0 开始编号 的 m x n 矩阵 mat ,其中任意两个相邻格子的值都 不相同 。找出 任意一个 顶峰元素 mat[i][j] 并 返回其位置 [i,j] 。

你可以假设整个矩阵周边环绕着一圈值为 -1 的格子。

要求必须写出时间复杂度为 O(m log(n)) 或 O(n log(m)) 的算法

示例 1:

输入: mat = [[1,4],[3,2]]
输出: [0,1]
解释: 3和4都是顶峰元素,所以[1,0]和[0,1]都是可接受的答案。

示例2:

输入: mat = [[10,20,15],[21,30,14],[7,16,32]]
输出: [1,1]
解释: 30和32都是顶峰元素,所以[1,1]和[2,2]都是可接受的答案。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-a-peak-element-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路:
我将当前点,当前点的上下左右四个点的上下左右四个点找出最大的点。然后以此向外扩张。我肯定能找到一个最大的点。然后我去判断他上下左右的点都比他小。那么当前点就是顶峰元素

实现代码:

class Solution {public int[] findPeakGrid(int[][] mat) {int row = 0;int col = 0;int[] pos = new int[2];while (!isPeak(mat, row, col)) {pos = biggerPeak(mat, row, col);row = pos[0];col = pos[1];}return pos;}public boolean isPeak(int[][] mat, int row, int col) {if (col > 0 && mat[row][col - 1] > mat[row][col]) {//左return false;}if (col < mat[0].length - 1 && mat[row][col + 1] > mat[row][col]) {//右return false;}if (row > 0 && mat[row - 1][col] > mat[row][col]) {//上return false;}if (row < mat.length - 1 && mat[row + 1][col] > mat[row][col]) {//下return false;}return true;}public static int[] biggerPeak(int[][] mat, int row, int col) {//寻找当前点,周围一圈点中最大的元素,以此向外扩张,int[] pos = new int[2];int maxV = mat[row][col];if (col > 0 && mat[row][col - 1] > maxV) {//左maxV = mat[row][col - 1];pos[0] = row;pos[1] = col - 1;}if (col < mat[0].length - 1 && mat[row][col + 1] > maxV) {//右maxV = mat[row][col + 1];pos[0] = row;pos[1] = col + 1;}if (row > 0 && mat[row - 1][col] > maxV) {//上maxV = mat[row - 1][col];pos[0] = row - 1;pos[1] = col;}if (row < mat.length - 1 && mat[row + 1][col] > maxV) {//下pos[0] = row + 1;pos[1] = col;}return pos;}
}

⭐1231. 分享巧克力

你有一大块巧克力,它由一些甜度不完全相同的小块组成。我们用数组 sweetness来表示每一小块的甜度。

你打算和 K 名朋友一起分享这块巧克力,所以你需要将切割 K 次才能得到 K+1 块,每一块都由一些 连续 的小块组成。

为了表现出你的慷慨,你将会吃掉 总甜度最小 的一块,并将其余几块分给你的朋友们。

请找出一个最佳的切割策略,使得你所分得的巧克力 总甜度最大,并返回这个 最大总甜度

示例 1:

输入:sweetness = [1,2,3,4,5,6,7,8,9], K = 5
输出:6
解释:你可以把巧克力分成 [1,2,3], [4,5], [6], [7], [8], [9]。

示例 2:

输入:sweetness = [5,6,7,8,9,1,2,3,4], K = 8
输出:1
解释:只有一种办法可以把巧克力分成 9 块。

示例 3:

输入:sweetness = [1,2,2,1,2,2,1,2,2], K = 2
输出:5
解释:你可以把巧克力分成 [1,2,2], [1,2,2], [1,2,2]。

思路:
这道题在有一次美团的笔试里出现过相似的,美团比这个还难,但是理解了这道题,美团那道题也还是挺好解的

二分查找基本特点:

  1. 查找对象有序;
  2. 通过某一个标准判断移动上界还是下界;
  3. 针对本题目:想要让分得的巧克力中总甜度最小的一块尽可能大。
  4. 那么可以想到应该尽可能让它接近总甜度的均值
  5. 但是还有限制条件:最终分得的巧克力数要等与k+1
  6. 考虑到上述情况,那么我们最终的目标就是,在[0,avgSweetSum]中找到一个尽可能大的值x,使得当总甜度最小的巧克力块的总甜度>=x时能分出多于k+1块巧克力;
  7. 结合我们的目标和二分查找的特点,可以得到以下方案:
  8. 查找的对象为[0,avgSweetSum]的数组;
  9. 判断标准为以当前总甜度作为总甜度最小的巧克力块的总甜度,是否能分出多于k+1块巧克力块,能,则下界移动,否则上界移动;

代码实现

class Solution {public int maximizeSweetness(int[] sweetness, int k) {int sumSw = 0;int len = sweetness.length;//---------------求均值----------------//for (int i = 0; i < len; i++) {sumSw += sweetness[i];}int avg = sumSw / (k + 1);//----在0到avg找到最大的值----//int l = 0, r = avg;while (l <= r) {int mid = (r - l) / 2 + l;if (isFeasible(mid, k, sweetness)) {l = mid + 1;//说明minDiv太小了,我要整个大一点的,我要尽可能吃更多的啊} else {r = mid - 1;//说明minDiv太大了,都切不到需要的k+1块了}}return r;}public boolean isFeasible(int minDiv, int k, int[] sweetness) {int count = 0, sum = 0;for (int x : sweetness) {sum += x;if (sum >= minDiv) {//开始切巧克力sum = 0;//重置count++;}}return count >= k + 1;//如果count >= k+1说明切的太碎了,即我设置的minDiv太小了,可以再大一点}
}

1182. 与目标颜色间的最短距离

给你一个数组 colors,里面有 123 三种颜色。

我们需要在colors 上进行一些查询操作 queries,其中每个待查项都由两个整数ic组成。

现在请你帮忙设计一个算法,查找从索引i 到具有目标颜色c的元素之间的最短距离。

如果不存在解决方案,请返回 -1。

示例 1:

输入:colors = [1,1,2,1,3,2,2,3,3], queries = [[1,3],[2,2],[6,1]]
输出:[3,0,3]
解释:
距离索引 1 最近的颜色 3 位于索引 4(距离为 3)。
距离索引 2 最近的颜色 2 就是它自己(距离为 0)。
距离索引 6 最近的颜色 1 位于索引 3(距离为 3)。

示例 2:

输入:colors = [1,2], queries = [[0,3]]
输出:[-1]
解释:colors 中没有颜色 3。

思路:
从左边找最近的颜色,求出距离;
从右边找到最近的颜色,求出距离;
两者取最小

代码实现:

class Solution {public List<Integer> shortestDistanceColor(int[] colors, int[][] queries) {int n = colors.length;int[][] dp = new int[3][n];//离下标j最近的颜色i+1最近的距离是dp[i][j]for (int i = 0; i < n; i++) {dp[0][i] = Integer.MAX_VALUE;dp[1][i] = Integer.MAX_VALUE;dp[2][i] = Integer.MAX_VALUE;}for (int i = 0, a = -1, b = -1, c = -1; i < n; ++i) {//从前往后if (colors[i] == 1) {//颜色1a = i;} else if (colors[i] == 2) {//颜色2b = i;} else {//颜色3c = i;}if (a != -1) {dp[0][i] = Math.min(dp[0][i], i - a);//最左边的离它最近的颜色1}if (b != -1) {dp[1][i] = Math.min(dp[1][i], i - b);//最左边的离它最近的颜色2}if (c != -1) {dp[2][i] = Math.min(dp[2][i], i - c);//最左边的离它最近的颜色3}}for (int i = n - 1, a = -1, b = -1, c = -1; i >= 0; --i) {if (colors[i] == 1) {a = i;} else if (colors[i] == 2) {b = i;} else {c = i;}if (a != -1) {dp[0][i] = Math.min(dp[0][i], a - i);//最右边的离它最近的颜色1}if (b != -1) {dp[1][i] = Math.min(dp[1][i], b - i);//最右边的离它最近的颜色2}if (c != -1) {dp[2][i] = Math.min(dp[2][i], c - i);//最右边的离它最近的颜色3}}List<Integer> ans = new ArrayList<>();for (int i = 0; i < queries.length; ++i) {int t = dp[queries[i][1] - 1][queries[i][0]];//颜色queries[i][1],对应的下标要减一if (t == Integer.MAX_VALUE) {ans.add(-1);//没有} else {ans.add(t);}}return ans;}
}

每日刷题——二分查找相关推荐

  1. C#LeetCode刷题-二分查找​​​​​​​

    二分查找篇 # 题名 刷题 通过率 难度 4 两个排序数组的中位数 C#LeetCode刷题之#4-两个排序数组的中位数(Median of Two Sorted Arrays)-该题未达最优解 30 ...

  2. 365天挑战LeetCode1000题——Day 035 每日一题 + 二分查找 13

    文章目录 1260. 二维网格迁移 首刷自解 算法复杂度: O ( i ∗ m ∗ n ) O(i * m * n) O(i∗m∗n), 其中i是k取模m*n 更好的方法是一维展开,算出元素下一个要去 ...

  3. 力扣牛客每日刷题(Python解法持续更新)

    力扣牛客每日刷题(持续更新) 初试结束第15天, 之前简单的处理了部分毕设方面的任务, 对接下来的学习做了个简单的规划 决定每天开始刷几道力扣题提高一下算法的理解,不能让之前学的数据结构都忘记了 每道 ...

  4. 2022-04-01每日刷题打卡

    2022-04-01每日刷题打卡 代码源--每日一题 Lusir的游戏 - 题目 - Daimayuan Online Judge Lusir 正在玩一个古老的基于 DOS 的游戏. 游戏中有 N+1 ...

  5. leetcode每日刷题计划-简单篇day8

    leetcode每日刷题计划-简单篇day8 今天是纠结要不要新买手机的一天QAQ想了想还是算了吧,等自己赚钱买,加油 Num 70 爬楼梯 Climbing Stairs class Solutio ...

  6. 2022-04-14每日刷题打卡

    2022-04-14每日刷题打卡 代码源--每日一题 上帝的集合 - 题目 - Daimayuan Online Judge 题目描述 现在上帝有一个空集合,现在他命令你为他执行下列三种操作 n 次, ...

  7. 2021-12-11每日刷题打卡

    2021-12-11每日刷题打卡 力扣--剑指offer 剑指 Offer 40. 最小的k个数 输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7.3.8这8个数字, ...

  8. 【每日刷题】P1010 幂次方题解

    [每日刷题]P1010 幂次方题解 题目描述 任何一个正整数都可以用 $2$ 的幂次方表示.例如 $137=2^7+2^3+2^0 $. 同时约定方次用括号来表示,即 $a^b$ 可表示为 $a(b) ...

  9. 2022-03-10每日刷题打卡

    2022-03-10每日刷题打卡 力扣--每日一题 589. N 叉树的前序遍历 给定一个 n 叉树的根节点 root ,返回 其节点值的 前序遍历 . n 叉树 在输入中按层序遍历进行序列化表示,每 ...

最新文章

  1. 对文本框只允许输入数字
  2. python 归一化 标准化
  3. python 实现 softmax
  4. java中表示根号三_Java命名规范
  5. c语言 异或_C语言经典例题来袭!5大方法告诉你答案
  6. Redis笔记 -- 链表和链表节点的API函数(三)
  7. 用聚宽量化炒股-3常用对象
  8. Bit Miracle Jpegv2.1.1117
  9. 黑客攻击-木马程序(3)
  10. js去掉前后空格的函数_Node.js十年,你大爷还是你大爷
  11. AR涂涂乐⭐五、关于“4”的部分解决方案
  12. 如何将excel表格导入word_如何将Excel中的数据写入Word表?
  13. 计算机毕业设计(附源码)python众筹平台
  14. 线段树 (更新区间查询点)秋实大哥与小朋友
  15. VR 中的常用指令设置及介绍
  16. 制作动态网站比较好用的软件工具
  17. 外媒称阿里副主席蔡崇信正洽谈收购篮网主场球馆 此前已收购球队49%股份
  18. 测试阶段划分为哪几个阶段?
  19. 大数据早报:三星Kakao联手开发AI语音识别技术 百度视频8月大数据报告出炉(9.19)
  20. c++获取umg ue_unreal_ue4使用C++动态载入UMG与Slot

热门文章

  1. 智鼎逻辑推理题及答案_联合利华2018年笔试真题(含答案和解析)
  2. 详细教您怎么远程控制电脑
  3. 产品经理是如何看待NPDP认证的?
  4. css实现三角形和向右箭头
  5. 002-strtoul函数(输入字符串转换为数字)
  6. 缺氧游戏计算机用水,缺氧用水裂解套路一览 缺氧游戏用水怎么玩法
  7. 你知道为什么不用XFP光模块了吗?
  8. 利用Visual Studio为X86程序开启大内存的方法
  9. 战国策-周文君免工师籍
  10. 因软件缺陷,736名员工被起诉,超40人被送进监狱