每日算法-250411

news2025/4/17 17:19:46

这是我今天的 LeetCode 刷题记录和心得,主要涉及了二分查找的应用。


3143. 正方形中的最多点数

题目简述:
Problem 3143 Description

思路

本题的核心思路是 二分查找

解题过程

为什么可以二分?
我们可以对正方形的半边长 len 进行二分。当正方形的半边长 len 越大时,可能包含的点越多,但也越有可能包含具有相同标签的点。反之,len 越小,包含的点越少,标签冲突的可能性也越小。包含点数的多少以及是否合法(无重复标签)相对于 len 的增长,具有一定的单调性(或者说,存在一个最大的 len 使得正方形合法),这满足二分查找的条件。

二分什么?
我们需要二分查找满足条件的 最大 正方形半边长 len。查找范围可以从 0 到所有点坐标绝对值的最大值。

如何检查(check 函数)?
check(len) 函数用于判断以半边长 len 构成的正方形是否“合法”。
合法性判断包含两步:

  1. 遍历所有点,检查其坐标 (x, y) 是否满足 abs(x) <= lenabs(y) <= len
  2. 对于落在正方形内的点,使用一个哈希表(或大小为 26 的数组 hash)记录出现的标签。如果在添加一个点的标签时,发现该标签已经存在于哈希表中(即 hash[s[i] - 'a'] >= 1),则说明存在重复标签,该 len 值对应的正方形不合法,check 返回 false
  3. 如果遍历完所有点都没有发现重复标签,则该 len 合法,check 返回 true

指针如何移动?
在二分查找过程中:

  • 计算中间值 mid
  • 调用 check(mid)
    • 如果 check(mid) 返回 true,说明半边长为 mid 的正方形是合法的。这表示我们可能可以找到一个更大的合法正方形,因此我们尝试增大边长,将搜索范围的左边界更新为 left = mid + 1。同时,因为这是一个合法的 len,我们需要记录下此时正方形内的点数(可以在 check 函数内部完成,或者在 check 返回 true 时更新全局变量 ret)。
    • 如果 check(mid) 返回 false,说明半边长为 mid 的正方形不合法(有标签冲突),意味着当前的 len 太大了,我们需要缩短边长,将搜索范围的右边界更新为 right = mid - 1

最终结果:
二分查找结束后,变量 ret 中存储的就是满足条件的最大合法正方形所包含的点数。

复杂度

  • 时间复杂度: O ( N log ⁡ M ) O(N \log M) O(NlogM),其中 N N N 是点的数量, M M M 是坐标的最大绝对值(二分查找的上界)。check 函数需要 O ( N ) O(N) O(N) 时间,二分查找进行 log ⁡ M \log M logM 次。
  • 空间复杂度: O ( C ) O(C) O(C) O ( N ) O(N) O(N) O ( C ) O(C) O(C) 是指存储标签计数的哈希表/数组所需空间( C = 26 C=26 C=26)。如果考虑最坏情况下所有点标签不同且都在某个正方形内,可能认为是 O ( N ) O(N) O(N),但通常关注辅助空间,所以 O ( C ) O(C) O(C) 更精确描述 check 函数的额外空间。

Code

class Solution {
    private int ret;

    public int maxPointsInsideSquare(int[][] points, String ss) {
        char[] s = ss.toCharArray();
        int left = 0;
        int right = 0;
        for (int[] point : points) {
            right = Math.max(right, Math.max(Math.abs(point[0]), Math.abs(point[1])));
        }
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (check(points, s, mid)) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return ret;
    }

    private boolean check(int[][] points, char[] s, int len) {
        int[] hash = new int[26];
        int tmp = 0; // 合法正方形里点的个数
        // 1.是不是合法的
        for (int i = 0; i < points.length; i++) {
            if (Math.abs(points[i][0]) <= len && Math.abs(points[i][1]) <= len) {
                if (hash[s[i] - 'a'] >= 1) {
                    // 标签已经存在
                    return false;
                }
                hash[s[i] - 'a']++;
                tmp++;
            }
        }
        // 2.更新数目
        ret = tmp;
        return true;
    }
}

69. x 的平方根

题目简述:
Problem 69 Description

思路

采用 二分查找

解题过程

为什么可以二分?
我们要找的是一个整数 ans,使得 ans * ans <= x 并且 (ans + 1) * (ans + 1) > x。考虑函数 f(y) = y * y,这是一个在非负整数域上的单调递增函数。我们需要找到满足 y*y <= x 的最大整数 y。这种在单调序列(或具有单调性质的函数)上查找满足特定条件的边界值的问题,非常适合使用二分查找。

二分什么?
二分查找的目标值,即可能的平方根 mid。查找范围是 [0, x](或者可以优化为 [0, x/2 + 1] 或像代码中的 [1, x/2],需要处理 x=0, 1 的边界情况,原代码 right = x/2 对于 x=0, 1 需要注意,但最终逻辑能处理)。

指针如何移动?
在二分查找 [left, right] 区间内:

  • 计算中间值 mid。为了防止 mid * mid 溢出 int,使用 long 类型进行计算和比较。
  • 比较 (long)mid * midx
    • 如果 mid * mid < x:说明 mid 太小了,它可能是平方根的一部分,但我们应该尝试更大的值。真正的整数平方根应该在 mid 的右侧(或就是 mid 本身)。所以,更新搜索区间的左边界 left = mid + 1
    • 如果 mid * mid >= x:说明 mid 可能等于 x 的平方根,或者比它大。我们需要尝试更小的值(或者 mid 就是边界)。所以,更新搜索区间的右边界 right = mid - 1

返回什么?
循环终止条件是 left > right。根据二分查找的实现方式,最终 left 指针将指向第一个满足 mid * mid > xmid(或者说,left 是满足 (left-1)*(left-1) <= x 的最小 left)。
分析代码中的返回逻辑 return left * left == x ? left : left - 1;

  • 循环结束后,left 的值是第一个使得 mid*mid >= x 评估为 true 时的 mid 值加 1(或者是 mid 本身,如果 mid*mid == x 且之后 right 被设为 mid-1 导致循环结束)。
  • 如果 left * left == x,说明 left 正好是 x 的精确整数平方根,直接返回 left
  • 如果 left * left != x (根据循环条件,此时必然是 left * left > x),这意味着 left 已经超过了目标平方根,而 left - 1 是最后一个满足 (left - 1) * (left - 1) <= x 的整数。因此,返回 left - 1 作为 x 的平方根的整数部分。

复杂度

  • 时间复杂度: O ( log ⁡ x ) O(\log x) O(logx),二分查找的范围是 x(或 x/2),每次迭代区间减半。
  • 空间复杂度: O ( 1 ) O(1) O(1),只需要常数级别的额外空间。

Code

class Solution {
    public int mySqrt(int x) {
        int left = 1, right = x / 2;
        while (left <= right) {
            long mid = left + (right - left) / 2;
            if (mid * mid < x) {
                left = (int)mid + 1;
            } else {
                right = (int)mid - 1;
            }
        }
        return left * left == x ? left : left - 1;
    }
}

2300. 咒语和药水的成功对数(复习)

题目简述:
Problem 2300 Description

这是第二次写这道题,已经可以说是完全掌握了,就不再多说了,详细题解请看 每日算法-250407。

核心思路回顾:
为了高效计算每个 spell 能成功组合的 potion 数量,我们可以:

  1. potions 数组进行 排序
  2. 对于每个 spell = spells[i],我们需要找到 potions 中满足 spell * potion >= success 的药水数量。由于 potions 已排序,spell * potion 的值也相对于 potion 是单调递增的(因为 spell > 0)。
  3. 因此,我们可以使用 二分查找 在排序后的 potions 数组中找到 第一个 满足 potion >= success / spell (注意整数除法和精度问题,最好是比较乘积 (long)spell * potions[mid] >= success)的药水的索引 idx
  4. 所有从 idx 到数组末尾 m-1 的药水都将满足条件。所以,对于 spells[i],成功的组合数量是 m - idx

代码 (复习)

class Solution {
    public int[] successfulPairs(int[] spells, int[] potions, long success) {
        Arrays.sort(potions);
        int n = spells.length, m = potions.length;
        for (int i = 0; i < spells.length; i++) {
            spells[i] = m - check(potions, spells[i], success);
        }
        return spells;
    }

    private int check(int[] arr, int spell, long k) {
        int left = 0, right = arr.length - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            long x = (long)arr[mid] * (long)spell;
            if (x < k) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return left;
    }
}

以上就是今天的刷题总结,主要是对二分查找在不同场景下的应用。继续努力!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2333134.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

NO.90十六届蓝桥杯备战|动态规划-区间DP|回文字串|Treats for the Cows|石子合并|248(C++)

区间dp也是线性dp的⼀种&#xff0c;它⽤区间的左右端点来描述状态&#xff0c;通过⼩区间的解来推导出⼤区间的解。因此&#xff0c;区间DP的核⼼思想是将⼤区间划分为⼩区间&#xff0c;它的状态转移⽅程通常依赖于区间的划分点。 常⽤的划分点的⽅式有两个&#xff1a; 基于…

【大模型LLM第十六篇】Agent学习之浅谈Agent loop的几种常见范式

anthropics agent https://zhuanlan.zhihu.com/p/32454721762 code&#xff1a;https://github.com/anthropics/anthropic-quickstarts/blob/main/computer-use-demo/computer_use_demo/loop.py sampling_loop函数 每次进行循环&#xff0c;输出extract tool_use&#xff0…

学术分享:基于 ARCADE 数据集评估 Grounding DINO、YOLO 和 DINO 在血管狭窄检测中的效果

一、引言 冠状动脉疾病&#xff08;CAD&#xff09;作为全球主要死亡原因之一&#xff0c;其早期准确检测对有效治疗至关重要。X 射线冠状动脉造影&#xff08;XCA&#xff09;虽然是诊断 CAD 的金标准&#xff0c;但这些图像的人工解读不仅耗时&#xff0c;还易受观察者间差异…

2025年慕尼黑上海电子展前瞻

年岁之约&#xff0c;齐聚慕展&#xff1b; 乘风而起&#xff0c;畅联未来。 2025 年 4 月 15 - 17 日&#xff0c;备受瞩目的慕尼黑上海电子展即将在上海新国际博览中心盛大启幕。回首2024年展会的场景&#xff0c;那热烈非凡的氛围、精彩纷呈的展示仍历历在目&#xff0c;也…

第十九:b+树和b-树

优点一&#xff1a; B树只有叶节点存放数据&#xff0c;其余节点用来索引&#xff0c;而B-树是每个索引节点都会有Data域。 优点二&#xff1a; B树所有的Data域在叶子节点&#xff0c;并且所有叶子节点之间都有一个链指针。 这样遍历叶子节点就能获得全部数据&#xff0c;这样…

深入浅出Redis 缓存使用问题 | 长文分享

目录 数据一致性 先更新缓存&#xff0c;后更新数据库【一般不考虑】 先更新数据库&#xff0c;再更新缓存【一般不考虑】 先删除缓存&#xff0c;后更新数据库 先更新数据库&#xff0c;后删除缓存【推荐】 怎么选择这些方案&#xff1f;采用哪种合适&#xff1f; 缓存…

操作系统 3.6-内存换出

换出算法总览 页面置换算法 FIFO&#xff08;先进先出&#xff09;&#xff1a; 最简单的页面置换算法&#xff0c;淘汰最早进入内存的页面。 优点&#xff1a;实现简单。 缺点&#xff1a;可能会导致Belady异常&#xff0c;即增加内存反而降低性能。如果刚换入的页面马上又要…

【Amazon EC2】为何基于浏览器的EC2 Instance Connect 客户端连接不上EC2实例

文章目录 前言&#x1f4d6;一、报错先知❌二、问题复现&#x1f62f;三、解决办法&#x1f3b2;四、验证结果&#x1f44d;五、参考链接&#x1f517; 前言&#x1f4d6; 这篇文章将讲述我在 Amazon EC2 上使用 RHEL9 AMI 时无法连接到 EC2 实例时所遇到的麻烦&#x1f616; …

新一代AI低代码MES,助力企业数字化升级

随着DeepSeek低成本AI模型的火热&#xff0c;对于传统的MES而言&#xff0c;在这场AI的盛宴中&#xff0c;该如何去调整产品的定位&#xff0c;让MES更符合工业企业的需求呢&#xff1f; 工业互联网、AI、数字孪生等技术加速与MES融合&#xff0c;实现生产全流程的实时监控与智…

HTML应用指南:利用GET请求获取全国汉堡王门店位置信息

在当今快节奏的都市生活中&#xff0c;餐饮品牌的门店布局不仅反映了其市场策略&#xff0c;更折射出消费者对便捷、品质和品牌认同的追求。汉堡王&#xff08;Burger King&#xff09;作为全球知名的西式快餐品牌之一&#xff0c;在中国市场同样占据重要地位。自进入中国市场以…

AICon 2024年全球人工智能与大模型开发与应用大会(脱敏)PPT汇总(36份).zip

AICon 2024年全球人工智能与大模型开发与应用大会&#xff08;脱敏&#xff09;PPT汇总&#xff08;36份&#xff09;.zip 1、面向开放域的大模型智能体.pdf 2、企业一站式 AI 智能体构建平台演进实践.pdf 3、PPIO 模型平台出海实战&#xff0c;跨地域业务扩展中的技术优化之道…

51电子表

设计要求&#xff1a; 基本任务&#xff1a; 用单片机和数码管设计可调式电子钟&#xff0c;采用24小时制计时方式&#xff0c;要求能够稳定准确计时&#xff0c;并能调整时间。发光二极管每秒亮灭一次。电子钟显示格式为&#xff1a;时、分、秒各两位&#xff0c;中间有分隔…

9-函数的定义及用法

一.前言 C 语⾔强调模块化编程&#xff0c;这⾥所说的模块就是函数&#xff0c;即把每⼀个独⽴的功能均抽象为⼀个函数来实现。从⼀定意义上讲&#xff0c;C 语⾔就是由⼀系列函数串组成的。 我们之前把所有代码都写在 main 函数中&#xff0c;这样虽然程序的功能正常实现&…

用HTML和CSS绘制佩奇:我不是佩奇

在这篇博客中&#xff0c;我将解析一个完全使用HTML和CSS绘制的佩奇(Pig)形象。这个项目展示了CSS的强大能力&#xff0c;仅用样式就能创造出复杂的图形&#xff0c;而不需要任何图片或JavaScript。 项目概述 这个名为"我不是佩奇"的项目是一个纯CSS绘制的卡通猪形象…

彩讯携Rich AICloud与一体机智算解决方案亮相中国移动云智算大会

2025年4月10日&#xff0c;2025中国移动云智算大会在苏州盛大开幕&#xff0c;本次大会以“由云向智 共绘算网新生态”为主题&#xff0c;与会嘉宾围绕算力展开重点探讨。 大会现场特设区域展出各参会单位的最新算力成果&#xff0c;作为中国移动重要合作伙伴&#xff0c;彩讯…

声学测温度原理解释

已知声速&#xff0c;就可以得到温度。 不同温度下的胜诉不同。 25度的声速大约346m/s 绝对温度-273度 不同温度下的声速。 FPGA 通过测距雷达测温度&#xff0c;固定测量距离&#xff0c;或者可以测出当前距离。已知距离&#xff0c;然后雷达发出声波到接收到回波的时间&a…

Cuto壁纸 2.6.9 | 解锁所有高清精选壁纸,无广告干扰

Cuto壁纸 App 提供丰富多样的壁纸选择&#xff0c;涵盖动物、风景、创意及游戏动漫等类型。支持分类查找与下载&#xff0c;用户可轻松将心仪壁纸设为手机背景&#xff0c;并享受软件内置的编辑功能调整尺寸。每天更新&#xff0c;确保用户总能找到新鲜、满意的壁纸。 大小&am…

C语言 AI 通义灵码 VSCode插件安装与功能详解

在 C 语言开发领域&#xff0c;一款高效的编码助手能够显著提升开发效率和代码质量。 通义灵码&#xff0c;作为阿里云技术团队打造的智能编码助手&#xff0c;凭借其强大的功能&#xff0c;正逐渐成为 C 语言开发者的新宠。 本文将深入探讨通义灵码在 C 语言开发中的应用&am…

二分查找5:852. 山脉数组的峰顶索引

链接&#xff1a;852. 山脉数组的峰顶索引 - 力扣&#xff08;LeetCode&#xff09; 题解&#xff1a; 事实证明&#xff0c;二分查找不局限于有序数组&#xff0c;非有序的数组也同样适用 二分查找主要思想在于二段性&#xff0c;即将数组分为两段。本体就可以将数组分为ar…

【模拟电路】稳压二极管/齐纳二极管

齐纳二极管也被称为稳压二极管,是一种特殊的二极管,其工作原理是利用PN结的反向击穿状态。在齐纳二极管中,当反向电压增加到一定程度,即达到齐纳二极管的击穿电压时,反向电流会急剧增加,但此时齐纳二极管的电压却基本保持不变。这种特性使得齐纳二极管可以作为稳压器或电…