【九十三】【算法分析与设计】719. 找出第 K 小的数对距离,N 台电脑的最长时间,二分答案法

news2024/11/18 7:50:56

719. 找出第 K 小的数对距离 - 力扣(LeetCode)

数对 (a,b) 由整数 ab 组成,其数对距离定义为 ab 的绝对差值。

给你一个整数数组 nums 和一个整数 k ,数对由 nums[i]nums[j] 组成且满足 0 <= i < j < nums.length 。返回 所有数对距离中k 小的数对距离。

示例 1:

输入:nums = [1,3,1], k = 1 输出:0 解释:数对和对应的距离如下: (1,3) -> 2 (1,1) -> 0 (3,1) -> 2 距离第 1 小的数对是 (1,1) ,距离为 0 。

示例 2:

输入:nums = [1,1,1], k = 2 输出:0

示例 3:

输入:nums = [1,6,1], k = 3 输出:5

提示:

  • n == nums.length

  • 2 <= n <= 10(4)

  • 0 <= nums[i] <= 10(6)

  • 1 <= k <= n * (n - 1) / 2

方法1,二分答案法,没有剪枝

1.

nums数组中的数对组合,下标分别为<0,1>,<0,2>...<0,n-1>

<1,2>,<1,3>....<1,n-1>

....

<n-2,n-1>

一共有n-1+n-2+....+1=((n-1)+1)*(n-1)/2=(n-1)*n/2对数对.

对于每一个数对,差值的绝对值,可以发现排序之后不会影响数组组合和结果.

我们需要找到所有数对距离从大到小排序之后的第k小的数对距离.

2.

将所有的数对距离排序之后,找到第k小的数对距离.

我们需要找一个数对距离的值,这个值是第k小的数对距离.

如果固定数对距离,可以求得他是第几小的数对距离,只需要求得小于等于limit的数对距离有多少个就知道这是第几小的数对距离.

用二分法找数对距离,判断数对距离是否是第k小的数对距离.

f(limit)函数返回小于等于limit数对距离的个数.如果小于k,说明数对距离不可能是答案.[0,limit]都不可能是答案.

去右边找答案.

如果是大于等于k,说明可能是答案,ret记录下来,去左边找可能的答案.

 
class Solution {
public:
    /*
    数对距离,二元组,排序和不排序不影响答案.
    数组n个元素,对应的数对个数是1+2+...+n-1=(1+n-1)*(n-1)/2=n*(n-1)/2
    分别下标对应<0,1><0,2>...<0,n-1>====> n-1
    <1,2>...<1,n-1>=====> n-2
    ...
    <n-2,n-1>=====> 1

    数对距离的可能范围[0,num_max-nums_min]
    数对距离排序之后第k个,是我们要找的值

    数对距离排序后第k个数对距离是答案.
    二分答案法,f(limit)数对距离大于等于limit的个数.
    二分答案法,固定答案判断其他条件,更方便
    1,2,3,4,5,6
    */

    vector<int> arr; // 保存输入的数组
    int k; // 第 k 小的数对距离
    int n; // 数组长度
    int ret; // 保存结果,即第 k 小的数对距离

    // 判断在给定的限制下,数对距离小于等于 limit 的个数是否大于等于 k
    bool f(int limit) {
        int count = 0; // 满足条件的数对个数
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                if (arr[j] - arr[i] <= limit) {
                    count++;
                } else {
                    break;
                }
            }
        }
        return count >= k;
    }

    // 初始化函数,计算数组长度并排序
    void init() {
        n = 0, ret = 0;
        sort(arr.begin(), arr.end());
        n = arr.size();
    }

    // 二分查找解决问题
    void solve() {
        int l = 0, r = arr[n - 1] - arr[0]; // 定义二分查找的左右边界
        while (l <= r) {
            int mid = l + ((r - l) >> 1); // 计算中间值
            if (f(mid)) { // 如果在当前限制下满足条件的数对个数大于等于 k
                ret = mid; // 更新结果
                r = mid - 1; // 缩小右边界
            } else {
                l = mid + 1; // 增大左边界
            }
        }
    }

    // 主函数,计算第 k 小的数对距离
    int smallestDistancePair(vector<int>& _nums, int _k) {
        ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); // 加速输入输出
        arr = _nums, k = _k;
        init(); // 调用初始化函数
        solve(); // 调用二分查找解决问题
        return ret; // 返回结果
    }
};

方法2,二分答案法,剪枝

1.

找小于等于limit的个数是否大于等于k.

这个过程j可以不用回退.

i和i+1~j-1数对距离都小于等于limit,但是i和j数对距离大于limit,那么i+1和i+1~j-1的数对距离也以一定小于等于limit.

所以j不需要回退,直接加上当前位置和j之间的个数.

如果ij相等j需要++.

 
class Solution {
public:
    /*
    数对距离,二元组,排序和不排序不影响答案.
    数组n个元素,对应的数对个数是1+2+...+n-1=(1+n-1)*(n-1)/2=n*(n-1)/2
    分别下标对应<0,1><0,2>...<0,n-1>====> n-1
    <1,2>...<1,n-1>=====> n-2
    ...
    <n-2,n-1>=====> 1

    数对距离的可能范围[0,num_max-nums_min]
    数对距离排序之后第k个,是我们要找的值

    数对距离排序后第k个数对距离是答案.
    二分答案法,f(limit)数对距离大于等于limit的个数.
    二分答案法,固定答案判断其他条件,更方便
    1,2,3,4,5,6

    */

    vector<int> arr;
    int k;
    int n;
    int ret;
    
    bool f(int limit) {// 判断在给定的限制下,数对距离小于等于 limit 的个数是否大于等于 k
        int count = 0;
        int j = 1;
        for (int i = 0; i < n; i++) {
            if (i == j)
                j++;
            count += j - i - 1;
            for (; j < n; j++) {//剪枝不回退
                if (arr[j] - arr[i] <= limit) {
                    count++;
                } else {
                    break;
                }
            }
        }
        return count >= k;
    }
    void init() {
        n = 0, ret = 0;

        sort(arr.begin(), arr.end());
        n = arr.size();
    }
    void solve() {
        int l = 0, r = arr[n - 1] - arr[0];
        while (l <= r) {
            int mid = l + ((r - l) >> 1);//位运算一定要加括号
            if (f(mid)) {
                ret = mid;
                r = mid - 1;
            } else {
                l = mid + 1;
            }
        }
    }

    int smallestDistancePair(vector<int>& _nums, int _k) {
        ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
        arr = _nums, k = _k;
        init();
        solve();
        return ret;
    }
};

N 台电脑的最长时间 - 力扣(LeetCode)

你有 n 台电脑。给你整数 n 和一个下标从 0 开始的整数数组 batteries ,其中第 i 个电池可以让一台电脑 运行 batteries[i] 分钟。你想使用这些电池让 全部 n 台电脑 同时 运行。

一开始,你可以给每台电脑连接 至多一个电池 。然后在任意整数时刻,你都可以将一台电脑与它的电池断开连接,并连接另一个电池,你可以进行这个操作 任意次 。新连接的电池可以是一个全新的电池,也可以是别的电脑用过的电池。断开连接和连接新的电池不会花费任何时间。

注意,你不能给电池充电。

请你返回你可以让 n 台电脑同时运行的 最长 分钟数。

示例 1:

输入:n = 2, batteries = [3,3,3] 输出:4 解释: 一开始,将第一台电脑与电池 0 连接,第二台电脑与电池 1 连接。 2 分钟后,将第二台电脑与电池 1 断开连接,并连接电池 2 。注意,电池 0 还可以供电 1 分钟。 在第 3 分钟结尾,你需要将第一台电脑与电池 0 断开连接,然后连接电池 1 。 在第 4 分钟结尾,电池 1 也被耗尽,第一台电脑无法继续运行。 我们最多能同时让两台电脑同时运行 4 分钟,所以我们返回 4 。

示例 2:

输入:n = 2, batteries = [1,1,1,1] 输出:2 解释: 一开始,将第一台电脑与电池 0 连接,第二台电脑与电池 2 连接。 一分钟后,电池 0 和电池 2 同时耗尽,所以你需要将它们断开连接,并将电池 1 和第一台电脑连接,电池 3 和第二台电脑连接。 1 分钟后,电池 1 和电池 3 也耗尽了,所以两台电脑都无法继续运行。 我们最多能让两台电脑同时运行 2 分钟,所以我们返回 2 。

提示:

  • 1 <= n <= batteries.length <= 10(5)

  • 1 <= batteries[i] <= 10(9)

1.

我们需要找运行时间,电池可以供电脑运行的最长的时间,我们找的这个时间一定有一个范围,0~所有时间累加和/n.

我们希望运行时间尽可能长.

f函数表示limit某一个特定的运行时间,电池是否可以供这些电脑运行这些时间.

如果不能说明limit这个运行时间短了,如果可以,再去更大的运行时间找,看看有没有更大的答案.

2.

f函数怎么判断这些电池能否供电脑运行这些时间,电池的电量如果大于等于limit,这个电池直接供一个电脑就可以了,如果电池电量小于limit说明,这个电池供完之后还需要其他的电池的帮助,这就是一个电池累加和,和总需要的电量的匹配问题.

只需要保证这些电池的累加和大于等于我们需要的电量即可.

所以我们需要将电量小于limit的电量累加,电脑数减去电量大于等于limit的个数,这个数乘以limit.

看累加电量是否大于等于n*limit.

3.

可以统一操作,如果不对n这个数进行修改,还原回去,左边就需要加上等量的值.也就是limit*(电量大于等于limit的个数).只需要电量大于等于limit的值加limit即可.

 
class Solution {
public:
    #define LL long long // 定义长整型别名

    int n; // 电脑的数量
    vector<int> arr; // 电池的电量数组
    LL ret; // 记录最长运行时间
    LL sum; // 电池电量总和

    // 判断在给定限制时间limit下,电池能否支持所有电脑运行
    bool f(LL limit) {
        LL totalTime = 0; // 记录总共供电时间
        for (int i = 0; i < arr.size(); ++i) {
            // 如果电池电量大于等于限制时间,则加上限制时间;否则,加上电池电量
            totalTime += arr[i] >= limit ? limit : arr[i];
            // 如果总供电时间大于等于限制时间乘以电脑数量,返回true
            if (totalTime >= limit * n) {
                return true;
            }
        }
        return false; // 如果无法满足条件,返回false
    }

    // 初始化,计算电池电量总和
    void init() {
        sum = accumulate(arr.begin(), arr.end(), 0LL);
    }

    // 二分查找解决最长运行时间
    void solve() {
        LL l = 0, r = sum / n; // 左边界为0,右边界为电池总电量除以电脑数量
        while (l <= r) {
            LL mid = l + ((r - l) >> 1); // 计算中间值
            // 如果在中间值限制下可以满足条件,更新结果,并尝试更长时间
            if (f(mid)) {
                ret = mid;
                l = mid + 1;
            } else { // 否则,尝试更短时间
                r = mid - 1;
            }
        }
    }

    // 主函数,计算最大运行时间
    long long maxRunTime(int _n, vector<int>& _batteries) {
        ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); // 加速输入输出
        n = _n; // 初始化电脑数量
        arr = _batteries; // 初始化电池数组
        init(); // 计算电池总电量
        solve(); // 二分查找计算最大运行时间
        return ret; // 返回结果
    }
};

结尾

最后,感谢您阅读我的文章,希望这些内容能够对您有所启发和帮助。如果您有任何问题或想要分享您的观点,请随时在评论区留言。

同时,不要忘记订阅我的博客以获取更多有趣的内容。在未来的文章中,我将继续探讨这个话题的不同方面,为您呈现更多深度和见解。

谢谢您的支持,期待与您在下一篇文章中再次相遇!         

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

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

相关文章

uniapp星空效果

uniapp星空效果 背景实现思路代码实现尾巴 背景 之前在网上看到过一个视频&#xff0c;使用纯css实现过一个星空效果。具体出处找不到了&#xff0c;我们按照他那个思路来实现一个类似的效果&#xff0c;还是先上一张图镇楼&#xff1a; 实现思路 首先我们这个效果使用的是…

es数据备份和迁移Elasticsearch

Elasticsearch数据备份与恢复 前提 # 注意&#xff1a; 1.在进行本地备份时使用--type需要备份索引和数据&#xff08;mapping,data&#xff09; 2.在将数据备份到另外一台ES节点时需要比本地备份多备份一种数据类型&#xff08;analyzer,mapping,data,template&#xff09; …

JAVA开发面试超详细

一、Java 基础 1.JDK 和 JRE 有什么区别&#xff1f; jdk&#xff1a;java development kit jre&#xff1a;java runtime Environment jdk是面向开发人员的&#xff0c;是开发工具包&#xff0c;包括开发人员需要用到的一些类。 jre是java运行时环境&#xff0c;包括java虚拟机…

使用可接受gitlab参数的插件配置webhook

jenkins配置 安装Generic Webhook Trigger 配置远程触发令牌 勾选Print post content和Print contributed variables用于打印值 配置gitlab 选择新增webhook 配置webhook http://JENKINS_URL/generic-webhook-trigger/invoke,将JENKINS_URL修改成自己的jenkins地址 先保存…

Docker(四) 文件和网络

1 Dockerfile 1.1 什么是Dockerfile Dockerfile是一个文本文件&#xff0c;包含一系列命令&#xff0c;这些命令用于在 Docker 镜像中自动执行操作。Dockerfile 定义了如何构建 Docker 镜像的步骤和所需的操作。 Dockerfile 中包含的命令可以设置和定制容器的环境&#xff0c;…

30.包名的修改和新建后端模块

权限和第三方登录确实令人头疼,我们来学一点简单一点的。 另外,如果各位有属于自己的域名和ICP/IP备案,布置一个作业,自行实现第三方QQ登录。 我们所说的包名修改,是一次性修改ruoyi的全部包名,因为发现很多人有这样的需求,下载别人的代码,想要改成自己公司的包名,结…

android11屏蔽下拉菜单快捷开关

1.文件位置&#xff1a; frameworks/base/packages/SystemUI/res/values/config.xml a.这个文件定义了初始化的一些组件&#xff0c;部分代码如下&#xff1a; //overlay/frameworks/base/packages/SystemUI/res/values/config.xml<!-- The default tiles to display in …

git使用介绍

一、为什么做版本控制&#xff08;git是版本控制工具&#xff09; 为了保留之前所以的版本&#xff0c;以便回滚和修改 二、点击安装 三、基础操作 1、初步认识 想要让git对一个目录进行版本控制需要以下步骤&#xff1a; 进入要管理的文件夹进行初始化命令 git init管理…

工厂做外贸,国内公司跟香港公司有什么区别

最近有不少做内贸的工厂朋友想转型做外贸&#xff0c;问我要不要单独注册一个公司&#xff0c;以及注册哪里的公司&#xff0c;国内的公司跟香港的公司有什么区别&#xff1f;今天就简单来给大家分享一下这块的一个区别。 首先工厂转型做外贸的话&#xff0c;比较建议注册一个…

【C++】 单例设计模式的讲解

前言 在我们的学习中不免会遇到一些要设计一些特殊的类&#xff0c;要求这些类只能在内存中特定的位置创建对象&#xff0c;这就需要我们对类进行一些特殊的处理&#xff0c;那我们该如何解决呢&#xff1f; 目录 1. 特殊类的设计1.1 设计一个类&#xff0c;不能被拷贝&#xf…

算法特训,AB5 .点击消除BC.149简写单词牛客.除2!牛客.Fibonacci数列

目录 AB5 .点击消除 BC.149简写单词 牛客.除2&#xff01; 牛客.Fibonacci数列 AB5 .点击消除 点击消除&#xff0c;类似于括号匹配a(b[b]a){c{d,这种&#xff0c;利用栈去消除,这样正好可以处理&#xff0c;假如相同就不进栈&#xff0c;同时还要出栈。注意我们这么搞完他是…

Leaflet【二】图层绘制——UI图层【点线面】 矢量图层【img、svg】

layer图层 在leaflet当中使用图层比OL当中简便一点&#xff0c;我们创建的layer图层可以直接通过 addTo 方法加到地图上&#xff0c;不需要通过layer、source再去做一些区分&#xff0c; 图标 Icon 创建Marker时提供的一个Icon 详细配置–>go // 导入一张图片作为图标imp…

在 Android 上存档短信:4 种方法的终极指南

概括 无论是个人对话还是专业信件&#xff0c;我们的短信收件箱很快就会因大量线程和对话而变得混乱。为了帮助管理这种过载&#xff0c;许多 Android 用户转向了归档短信这一便捷功能。在本指南中&#xff0c;我们将探讨如何在 Android 设备上存档短信的详细信息&#xff0c;…

文心一言 VS 讯飞星火 VS chatgpt (265)-- 算法导论20.1 4题

四、假设不使用一棵叠加的度为 u \sqrt{u} u ​ 的树&#xff0c;而是使用一棵叠加的度为 u 1 k u^{\frac{1}{k}} uk1​的树&#xff0c;这里 k 是大于 1 的常数&#xff0c;则这样的一棵树的高度是多少&#xff1f;又每个操作将需要多长时间&#xff1f;如果要写代码&#xf…

JPHS-JMIR Public Health and Surveillance

文章目录 一、期刊简介二、征稿信息三、期刊表现四、投稿须知五、投稿咨询 一、期刊简介 JMIR Public Health and Surveillance是一本多学科期刊&#xff0c;专注于公共卫生创新与技术的交叉领域&#xff0c;包括公共卫生信息学、监测&#xff08;监测系统和快速报告&#xff…

大模型难落地?聊聊大模型在智能财务应用的正确打开方式

大模型难落地&#xff1f;No&#xff0c;是你还不够了解它&#xff01; &#xff08;全文4989字&#xff0c;阅读约需10分钟&#xff09; 这两天&#xff0c;大模型几乎成了WAIC&#xff08;世界人工智能大会&#xff09;的唯一主题。大会上&#xff0c;各家企业的大模型悉数…

excel转pdf并且加水印,利用ByteArrayOutputStream内存流不产生中间文件

首先先引入包&#xff1a;加水印和excel转PDF的 <dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.12</version></dependency><dependency><groupId>org.apache.poi&l…

vue核心模块源码解析

响应式原理 Object.definePropertysetterProxy var count 1 var state {} Object.defineProperty(state , count,{get(){return count},set(val){count val} }) //弊端&#xff1a;不能主动监听到对象属性的新增或者删除&#xff0c;add/deleteref和reactive 声明响应式数…

Golang net/http标准库常用方法(二)

大家好&#xff0c;针对Go语言 net/http 标准库&#xff0c;将梳理的相关知识点分享给大家~~ 围绕 net/http 标准库相关知识点还有许多章节&#xff0c;请大家多多关注。 文章中代码案例只有关键片段&#xff0c;完整代码请查看github仓库&#xff1a;https://github.com/hltfa…

K8S认证|CKA题库+答案| 1. 权限控制RBAC

1、权限控制RBAC 您必须在以下Cluster/Node上完成此考题&#xff1a; Cluster Master node Worker node k8s master …