【九十三】【算法分析與設計】719. 找出第 K 小的數對距離,N 臺電腦的最長時間,二分答案法

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 的個數是否大于等于 kbool 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)) { // 如果在當前限制下滿足條件的數對個數大于等于 kret = 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 的個數是否大于等于 kint 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];// 如果總供電時間大于等于限制時間乘以電腦數量,返回trueif (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.pswp.cn/bicheng/19291.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/19291.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/19291.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

java調用遠程接口下載文件

在postman中這樣下載文件 有時下載文件太大postman會閃退&#xff0c;可以通過代碼下載&#xff0c;使用hutool的http包

3步操作助您輕松實現蘋果手機照片一鍵傳輸至電腦

對于很多使用蘋果手機的用戶來說&#xff0c;隨著手機中照片和視頻數量的不斷積累&#xff0c;如何將這些珍貴的回憶從手機轉移到電腦&#xff0c;以便更好地保存、整理和分享&#xff0c;成為了一個值得關注的問題。那么&#xff0c;蘋果手機怎么把照片導入電腦呢&#xff1f;…

鴻蒙課程培訓 | 訊方技術與鴻蒙生態服務公司簽約,成為鴻蒙鉆石服務商

3月15日&#xff0c;深圳市訊方技術股份有限公司與鴻蒙生態服務公司簽署合作協議&#xff0c;訊方技術成為鴻蒙鉆石服務商&#xff0c;正式進軍鴻蒙原生應用培訓開發領域。訊方技術總裁劉國鋒、副總經理劉銘皓、深圳區域總經理張松柏、深圳區域交付總監張梁出席簽約儀式。 作…

鄉村振興的鄉村產業創新發展:培育鄉村新興產業,打造鄉村產業新名片,促進鄉村經濟多元化發展

目錄 一、引言 二、鄉村產業創新發展的必要性 &#xff08;一&#xff09;適應新時代發展要求 &#xff08;二&#xff09;滿足消費升級需求 &#xff08;三&#xff09;促進農民增收致富 三、培育鄉村新興產業策略 &#xff08;一&#xff09;加強科技創新引領 &#…

在 MFC 中 UNICODE 加 _T 與 L 長字符串,有什么區別?

在MFC&#xff08;Microsoft Foundation Classes&#xff09;和更廣泛的Windows編程環境中&#xff0c;UNICODE宏用于指示程序應使用Unicode字符集&#xff08;通常是UTF-16&#xff09;來處理文本。當定義了UNICODE宏時&#xff0c;編譯器和庫函數會期待和處理寬字符&#xff…

Android下HWC以及drm_hwcomposer普法((上)

Android下HWC以及drm_hwcomposer普法((上) 引言 按摩得全套&#xff0c;錯了&#xff0c;做事情得全套&#xff0c;普法分析也是如此。drm_hwcomposer如果對Android圖形棧有一定研究的童鞋們應該知道它是Android提供的一個的圖形后端合成處理HAL模塊的實現。但是在分析這個之前…

Java復習-集合篇

集合 集合分為倆大類 單列集合 每個元素數據只包含一個值 雙列集合 每個元素包含倆個鍵值對 Conllection單列集合 單列集合常用的主要是下列幾種 List集合 List系列集合的特點&#xff1a;添加元素是有序、可重復、有索引 這里我們來試一下ArrayList ArrayList<String&g…

Spring OAuth2:開發者的安全盾牌!(上)

何利用Spring OAuth2構建堅不可摧的安全體系&#xff1f;如何使用 OAuth2 從跨域挑戰到性能優化&#xff0c;每一個環節都為你的應用保駕護航&#xff1f; 文章目錄 Spring OAuth2 詳解1. 引言簡述OAuth2協議的重要性Spring Framework對OAuth2的支持概述 2. 背景介紹2.1 OAuth2…

比較Rust和Haskel

在比較Rust和Haskell時&#xff0c;我們可以從多個維度來分析它們各自的優勢。以下是Rust相對于Haskell的優勢&#xff0c;以及Haskell相對于Rust的優勢&#xff1a; Rust比Haskell強的方面&#xff1a; 內存安全與并發性&#xff1a; Rust通過獨特的所有權系統和借用檢查器在…

智能倉儲物流系統(WMS)系列-管理查詢調整

好的應用系統應是細分簡單&#xff0c;界面簡潔易操作&#xff0c;程序代碼簡潔易懂的。

史上最全排序算法整理(2)

本篇文章我們將接著上篇繼續介紹常見的排序算法&#xff0c;有需要的小伙伴可以移步史上最全排序算法整理&#xff08;1&#xff09;查看相關內容哦 1.冒泡排序 1.1基本思想 在待排序的一組數中&#xff0c;將相鄰的兩個數進行比較&#xff0c;若前面的數比后面的數大就交換兩…

【解決npm install -g windows-build-tools的安裝問題】

解決npm install -g windows-build-tools的安裝問題 https://developer.huawei.com/consumer/cn/forum/topic/0203740461436730610?fid26

gitlab 創建 ssh 和 token

文章目錄 一、創建ssh key二、將密鑰內容復制到gitlab三、創建token 一、創建ssh key 打開控制臺cmd&#xff0c;執行命令 ssh-keygen -t rsa -C xxxxx xxxxx是你自己的郵箱 C:\Users\xx\.ssh 目錄下會創建一個名為id_rsa.pub的文件&#xff0c;用記事本打開&#xff0c;并…

基于深度學習的中文情感分析系統python flask

基于python的畢業設計 基于深度學習的中文情感分析系統(flask)(源碼說明文檔演示) 畢業設計課程設計期末大作業、課程設計、高分必看&#xff0c;下載下來&#xff0c;簡單部署&#xff0c;就可以使用。 包含&#xff1a;項目源碼、數據庫腳本、軟件工具等&#xff0c;該項目…

【Spring Cloud】微服務工程中的服務注冊與發現配置中心-Consul

Catalog Spring Cloud Consul一、需求二、是什么三、優點四、缺點五、怎么用六、細節 Spring Cloud Consul 一、需求 多個微服務之間通過RestTemplate中的api相互調用&#xff0c;一般要寫死微服務的IP地址和端口號&#xff0c;相當于硬編碼&#xff0c;非常不靈活&#xff0…

MyBatis出現:SQLSyntaxErrorException: Unknown column ‘XXX‘ in ‘field list‘

<update id"updateStudent">update tb_students set stu_name${stuName},stu_gender${stuGender},stu_age${stuAge},stu_tel${stuTel}where stu_num ${stuNum}</update> 本質上來說&#xff0c;是Mybatis使用上的錯誤&#xff0c;不熟悉&#xff0c;理…

C#知識|通過ADO.NET實現應用程序對數據庫的增、刪、改操作。

哈嘍,你好啊,我是雷工! 前邊學習了SQLServer數據庫相關的增刪改查的基本操作, 上節練習了C#通過ADO.NET技術和SQLServer數據庫建立連接和斷開連接的寫法, 本節繼續學習ADO.NET的相關操作,下面為向數據庫中插入數據的相關練習筆記。 01 向數據庫插入數據 插入數據的過程…

SQL函數--union all 使用方法及案例

1. 使用方法 在 SQL 中&#xff0c;UNION ALL 操作用于結合兩個或更多 SELECT 語句的結果集&#xff0c;包括所有匹配的行&#xff0c;甚至包括重復的行。這與 UNION 不同&#xff0c;因為 UNION 會自動刪除重復的行。 滿足條件&#xff1a; 1、兩個select查詢的列的數量必須相…

web前端柜架圖片:探索與解析

web前端柜架圖片&#xff1a;探索與解析 在web前端開發的世界里&#xff0c;圖片的處理與展示是一項至關重要的任務。而“web前端柜架圖片”這一概念&#xff0c;可能初聽起來讓人有些困惑&#xff0c;它究竟指的是什么&#xff1f;在本文中&#xff0c;我們將從四個方面、五個…

Ai速遞5.29

全球AI新聞速遞 1.摩爾線程與無問芯穹合作&#xff0c;實現國產 GPU 端到端 AI 大模型實訓。 2.寶馬工廠&#xff1a;機器狗上崗&#xff0c;可“嗅探”故障隱患。 3.ChatGPT&#xff1a;macOS 開始公測。 4.Stability AI&#xff1a;推出Stable Assistant&#xff0c;可用S…