成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

為了得到無重疊區間,煞費苦心

開發 前端
給定一個區間的集合,找到需要移除區間的最小數量,使剩余區間互不重疊。注意: 可以認為區間的終點總是大于它的起點。區間 [1,2] 和 [2,3] 的邊界相互“接觸”,但沒有相互重疊。

[[438794]]

無重疊區間

力扣題目鏈接:https://leetcode-cn.com/problems/non-overlapping-intervals

給定一個區間的集合,找到需要移除區間的最小數量,使剩余區間互不重疊。

注意: 可以認為區間的終點總是大于它的起點。區間 [1,2] 和 [2,3] 的邊界相互“接觸”,但沒有相互重疊。

示例 1:

  • 輸入: [ [1,2], [2,3], [3,4], [1,3] ]
  • 輸出: 1
  • 解釋: 移除 [1,3] 后,剩下的區間沒有重疊。

示例 2:

  • 輸入: [ [1,2], [1,2], [1,2] ]
  • 輸出: 2
  • 解釋: 你需要移除兩個 [1,2] 來使剩下的區間沒有重疊。

示例 3:

  • 輸入: [ [1,2], [2,3] ]
  • 輸出: 0
  • 解釋: 你不需要移除任何區間,因為它們已經是無重疊的了。

思路

相信很多同學看到這道題目都冥冥之中感覺要排序,但是究竟是按照右邊界排序,還是按照左邊界排序呢?

這其實是一個難點!

按照右邊界排序,就要從左向右遍歷,因為右邊界越小越好,只要右邊界越小,留給下一個區間的空間就越大,所以從左向右遍歷,優先選右邊界小的。

按照左邊界排序,就要從右向左遍歷,因為左邊界數值越大越好(越靠右),這樣就給前一個區間的空間就越大,所以可以從右向左遍歷。

如果按照左邊界排序,還從左向右遍歷的話,其實也可以,邏輯會有所不同。

一些同學做這道題目可能真的去模擬去重復區間的行為,這是比較麻煩的,還要去刪除區間。

題目只是要求移除區間的個數,沒有必要去真實的模擬刪除區間!

我來按照右邊界排序,從左向右記錄非交叉區間的個數。最后用區間總數減去非交叉區間的個數就是需要移除的區間個數了。

此時問題就是要求非交叉區間的最大個數。

右邊界排序之后,局部最優:優先選右邊界小的區間,所以從左向右遍歷,留給下一個區間的空間大一些,從而盡量避免交叉。全局最優:選取最多的非交叉區間。

局部最優推出全局最優,試試貪心!

這里記錄非交叉區間的個數還是有技巧的,如圖:

無重疊區間

區間,1,2,3,4,5,6都按照右邊界排好序。

每次取非交叉區間的時候,都是可右邊界最小的來做分割點(這樣留給下一個區間的空間就越大),所以第一條分割線就是區間1結束的位置。

接下來就是找大于區間1結束位置的區間,是從區間4開始。那有同學問了為什么不從區間5開始?別忘已經是按照右邊界排序的了。

區間4結束之后,在找到區間6,所以一共記錄非交叉區間的個數是三個。

總共區間個數為6,減去非交叉區間的個數3。移除區間的最小數量就是3。

C++代碼如下:

  1. class Solution { 
  2. public
  3.     // 按照區間右邊界排序 
  4.     static bool cmp (const vector<int>& a, const vector<int>& b) { 
  5.         return a[1] < b[1]; 
  6.     } 
  7.     int eraseOverlapIntervals(vector<vector<int>>& intervals) { 
  8.         if (intervals.size() == 0) return 0; 
  9.         sort(intervals.begin(), intervals.end(), cmp); 
  10.         int count = 1; // 記錄非交叉區間的個數 
  11.         int end = intervals[0][1]; // 記錄區間分割點 
  12.         for (int i = 1; i < intervals.size(); i++) { 
  13.             if (end <= intervals[i][0]) { 
  14.                 end = intervals[i][1]; 
  15.                 count++; 
  16.             } 
  17.         } 
  18.         return intervals.size() - count
  19.     } 
  20. }; 
  • 時間復雜度:O(nlogn) ,有一個快排
  • 空間復雜度:O(1)

大家此時會發現如此復雜的一個問題,代碼實現卻這么簡單!

總結

本題我認為難度級別可以算是hard級別的!

總結如下難點:

  • 難點一:一看題就有感覺需要排序,但究竟怎么排序,按左邊界排還是右邊界排。
  • 難點二:排完序之后如何遍歷,如果沒有分析好遍歷順序,那么排序就沒有意義了。
  • 難點三:直接求重復的區間是復雜的,轉而求最大非重復區間個數。
  • 難點四:求最大非重復區間個數時,需要一個分割點來做標記。

這四個難點都不好想,但任何一個沒想到位,這道題就解不了。

一些錄友可能看網上的題解代碼很簡單,照葫蘆畫瓢稀里糊涂的就過了,但是其題解可能并沒有把問題難點講清楚,然后自己再沒有鉆研的話,那么一道貪心經典區間問題就這么浪費掉了。

貪心就是這樣,代碼有時候很簡單(不是指代碼短,而是邏輯簡單),但想法是真的難!

這和動態規劃還不一樣,動規的代碼有個遞推公式,可能就看不懂了,而貪心往往是直白的代碼,但想法讀不懂,哈哈。

所以我把本題的難點也一一列出,幫大家不僅代碼看的懂,想法也理解的透徹!

補充

本題其實和452.用最少數量的箭引爆氣球非常像,弓箭的數量就相當于是非交叉區間的數量,只要把弓箭那道題目代碼里射爆氣球的判斷條件加個等號(認為[0,1][1,2]不是相鄰區間),然后用總區間數減去弓箭數量 就是要移除的區間數量了。

把452.用最少數量的箭引爆氣球代碼稍做修改,就可以AC本題。

  1. class Solution { 
  2. public
  3.     // 按照區間右邊界排序 
  4.     static bool cmp (const vector<int>& a, const vector<int>& b) { 
  5.         return a[1] < b[1]; 
  6.     } 
  7.     int eraseOverlapIntervals(vector<vector<int>>& intervals) { 
  8.         if (intervals.size() == 0) return 0; 
  9.         sort(intervals.begin(), intervals.end(), cmp); 
  10.  
  11.         int result = 1; // points 不為空至少需要一支箭 
  12.         for (int i = 1; i < intervals.size(); i++) { 
  13.             if (intervals[i][0] >= intervals[i - 1][1]) { 
  14.                 result++; // 需要一支箭 
  15.             } 
  16.             else {  // 氣球i和氣球i-1挨著 
  17.                 intervals[i][1] = min(intervals[i - 1][1], intervals[i][1]); // 更新重疊氣球最小右邊界 
  18.             } 
  19.         } 
  20.         return intervals.size() - result; 
  21.     } 
  22. }; 

這里按照 左區間遍歷,或者按照右邊界遍歷,都可以AC,具體原因我還沒有仔細看,后面有空再補充。

  1. class Solution { 
  2. public
  3.     // 按照區間左邊界排序 
  4.     static bool cmp (const vector<int>& a, const vector<int>& b) { 
  5.         return a[0] < b[0]; 
  6.     } 
  7.     int eraseOverlapIntervals(vector<vector<int>>& intervals) { 
  8.         if (intervals.size() == 0) return 0; 
  9.         sort(intervals.begin(), intervals.end(), cmp); 
  10.  
  11.         int result = 1; // points 不為空至少需要一支箭 
  12.         for (int i = 1; i < intervals.size(); i++) { 
  13.             if (intervals[i][0] >= intervals[i - 1][1]) { 
  14.                 result++; // 需要一支箭 
  15.             } 
  16.             else {  // 氣球i和氣球i-1挨著 
  17.                 intervals[i][1] = min(intervals[i - 1][1], intervals[i][1]); // 更新重疊氣球最小右邊界 
  18.             } 
  19.         } 
  20.         return intervals.size() - result; 
  21.     } 
  22. }; 

本文轉載自微信公眾號「代碼隨想錄」,可以通過以下二維碼關注。轉載本文請聯系代碼隨想錄公眾號。

 

責任編輯:武曉燕 來源: 代碼隨想錄
相關推薦

2015-10-19 11:14:17

Edge瀏覽器Windows 10

2020-05-21 11:23:08

微軟LinuxWindows

2020-12-31 05:47:40

網格化網格通信

2020-07-23 16:00:38

Redis字符串Java

2024-06-13 17:06:03

2020-03-16 09:26:56

開發技能代碼

2013-11-28 10:09:33

大數據數據中心SDN

2011-11-25 10:20:36

飛視美視頻

2012-11-26 13:46:17

路由器交換機

2018-04-20 08:37:23

災難恢復數據備份

2015-11-24 10:09:49

Windows 10TH2數據搜集

2009-03-25 08:45:33

AndroidGoogle移動OS

2013-07-31 13:55:01

2009-10-30 11:32:23

2011-03-07 13:24:15

2021-01-26 09:13:07

前端開發者程序員

2019-03-21 09:45:11

TypeScript編程語言Javascript

2022-12-15 07:45:51

極客版編程速查表

2012-01-05 09:26:56

App Store作產品賺錢

2016-12-16 12:06:09

數據分析大數據
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久久www成人免费无遮挡大片 | 久草网站 | 久久久久久亚洲国产精品 | 精品久久99 | 亚洲视频二区 | 99re在线视频观看 | 国产一区日韩在线 | 日本欧美国产在线观看 | 精品亚洲视频在线 | 国产成人精品一区二区三区在线 | 亚洲精品在线播放 | 国产精品成人一区二区三区夜夜夜 | 99久久精品国产一区二区三区 | 成人免费小视频 | 欧美午夜剧场 | 日韩中文字幕视频在线 | 成人国产精品免费观看 | 国产一区精品在线 | 国产一级视频在线观看 | 一级a爱片性色毛片免费 | 在线视频一区二区三区 | 在线看av的网址 | 欧美一区永久视频免费观看 | 成人欧美一区二区三区黑人孕妇 | 欧美日韩国产在线 | 日韩视频在线一区 | 久久精品亚洲 | 在线观看中文字幕一区二区 | 麻豆国产精品777777在线 | 嫩草黄色影院 | www.久久.com | 欧美最猛性xxxxx亚洲精品 | 午夜欧美一区二区三区在线播放 | 91看片在线观看 | 天天操天天摸天天爽 | 国产精品久久午夜夜伦鲁鲁 | 毛片网在线观看 | 国产视频精品在线观看 | 欧美日韩在线观看视频网站 | 美女视频一区 | 美女爽到呻吟久久久久 |