力扣解題思路 區間排序問題

2021-10-07 16:50:58 字數 3711 閱讀 5937

思路:每次遇到和區間有關的題都要思考半天區間的排序方法,是根據區間左邊排序還是根據區間右邊排序呢?

另外遇到這種題目如果採取貪心演算法最後的結果會不會是最優的呢?(主要是因為研究生期間我的研究方向是強化學習演算法,其中用到的貪婪演算法容易陷入區域性最優,所以每次看到適合用貪婪演算法解題的題目時總會思考貪婪演算法會得出最優解嗎?)->

首先,分析我們的目標是要找到找到需要移除區間的最小數量,所以想到貪心演算法:先計算最多能組成的不重疊區間個數,然後用區間總個數減去不重疊區間的個數。此時就應該先排序,那麼如何排序呢?->

按區間的結尾進行公升序排序,每次選擇結尾最小,並且和前乙個區間不重疊的區間。因此我們按照區間結尾來使用lambda表示式排序。

在每次選擇中,選擇的區間結尾越小,留給後面的區間的空間越大,那麼後面能夠選擇的區間個數也就越大。自然這樣貪心演算法並不會到達區域性最優,這就是按區間的結尾進行公升序排序的根本原因。排序**如下:

arrays.

sort

(intervals,

(o1,o2)

->

(o1[1]

-o2[1]));

完整**如下:

class

solution

}return intervals.length-count;

}}

同樣的道理,如452. 用最少數量的箭引爆氣球,使用的也是同樣的思想,只不過此時邊界重疊也必須算在作重疊區間,使用lambda表示式排序:

arrays.

sort

(points,

(o1,o2)

->

(o1[1]

-o2[1]));

完整**如下:

class

solution

}return count;

}}

說到區間問題,還有406. 根據身高重建佇列的解題方法也比較巧妙,乙個學生用兩個分量 (h, k) 描述,h 表示身高,k 表示排在前面的有 k 個學生的身高比他高或者和他一樣高。也涉及到區間的排序->

對於這種排隊的題目,我們第一想法是按照k公升序排序,因為位於佇列前方的人的前面的人數自然是較小的,但是這樣是存在問題的,人數是符合要求了,但是k的含義弄錯了,k不是前面排的人數,而是前面比他高的人數,所以先按照k公升序排序在邏輯上行不通。

那我們轉換一下思想,我們按照採用h降序排序,遇到h相同的按照k公升序排序(不可以按照降序,因為如果按照降序,插入的索引過大會導致該索引可能一開始就不存在),你以為這就結束了嗎?這仍然是不對的,因為我們還需要對這個佇列再次處理,現在開始真正的排隊:

我們再對佇列中的元素進行順序插入操作,插入時按照k作為索引,我們乙個乙個地排隊,對於前面已經排好的隊,如果我們在k的位置插入乙個新人,那麼對k之前的人沒有任何影響(因為插在其後面),對於k之後比新人高的人也沒有任何影響(因為插入的人屬於身高比較高而,k較小的,比如我們往同乙個位置k插入了多次,那麼後插入的一定是h較小的,就會把先插入在k位置的元素擠到後面去,但是因為後插入的元素h比先插入的小,所以不影響先插入k的元素的前面比他大元素的個數,也就是只要插入k位置的,前面比他大的元素永遠都是只有k個,滿足題目要求),因此,我們每插入乙個人的時候,要麼保證前面所有人都比新人高,要麼至少保證插入的位置後面的所有人都比新人高,這就要求我們在排序的時候當身高相同時k遞增排序。

我們還是使用lambda表示式對陣列排序:

arrays.

sort

(people,

(a, b)

->

(a[0

]== b[0]

? a[1]

- b[1]

: b[0]

- a[0]));

因為鍊錶的特新適合插入和刪除節點,所以我們在鍊錶上完成這個佇列的插入操作:

class

solution

return list.

toarray

(new

int[list.

size()

][2]

);}}

例如:

[7,

0],[

7,1]

,[6,

1],[

5,0]

,[5,

2],[

4,4]

再乙個乙個插入。

[7,0][7

,0],

[7,1

][7,

0],[

6,1]

,[7,

1][5

,0],

[7,0

],[6

,1],

[7,1

][5,

0],[

7,0]

,[5,

2],[

6,1]

,[7,

1][5

,0],

[7,0

],[5

,2],

[6,1

],[4

,4],

[7,1

]

思路:

二分法我覺得實在沒必要,因為要在排序的同時儲存索引以便後續使用我們就得使用treemap,因為treemap天生根據key值排序,所以key就設定為我們需要排序的元素,而value自然就是索引。

因為我們要找到每個元素對應的右邊區間,所以我們會根據此區間的右邊界來尋找目標區間(目標區間即為左邊界大於當前區間右邊界的區間),因此treemap有個ceiling方法剛好可以幫我們完成任務~~所以我們key中需要儲存的是區間右邊界!!

public

int[

]findrightinterval

(interval[

] intervals)

for(

int i =

0; i < intervals.length; i++

)return res;

}

思路:

這一題,題目中的意思很明顯,就是無需排序!!我們可以採用雙指標的方式對比a和b的頭指標指向的區間:

public

int[

]intervalintersection

(int

a,int[

] b));

}else

if(left==right));

}if(a[i][1

]

])i++

;else

j++;}

return list.

toarray

(new

int[list.

size()

]);}

注意 list.toarray 可以直接將鍊錶轉成陣列!!

力扣解題思路 打家劫舍

思路 題目 你是乙個專業的小偷,計畫偷竊沿街的房屋,每間房內都藏有一定的現金。這個地方所有的房屋都圍成一圈,這意味著第乙個房屋和最後乙個房屋是緊挨著的。同時,相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。給定乙個代表每個房屋存放金額的非負整數陣列,計算你在...

力扣解題思路 素數

首先,如何判斷乙個數是否為素數呢,首先我們知道最小的素數是2,那麼我們從2開始判斷該數是否能找到被除數即可,完整 如下 public boolean isprimenum int i return true 思路 統計所有小於非負整數 n 的質數的數量。那麼這一題我們需要對每個小於n的數進行判斷一次...

力扣解題思路 169 多數元素

思路 給定乙個大小為 n 的陣列,找到其中的多數元素。多數元素是指在陣列 現次數大於 n 2 的元素。你可以假設陣列是非空的,並且給定的陣列總是存在多數元素。首先最直觀的方法就是先排序,最中間那個數出現次數一定多於 n 2。public intmajorityelement int nums 這種方...