力扣406. 根據身高重建佇列
下面這題的解法不僅僅讓我學會了解這道題,也讓我見識到了二維陣列竟然還能以一行元素作為單位進行排序和遍歷操作,真是學到了,學到了~~~
406. 根據身高重建佇列
假設有打亂順序的一群人站成一個佇列。 每個人由一個整數對(h, k)表示,其中h是這個人的身高,k是排在這個人前面且身高大於或等於h的人數。 編寫一個演算法來重建這個佇列。
注意:
總人數少於1100人。示例
輸入: [[7,0], [4,4], [7,1], [5,0], [6,1], [5,2]] 輸出: [[5,0], [7,0], [5,2], [6,1], [4,4], [7,1]]
題意分析:
其實這題就是說有一個佇列,這個佇列中高度層次不齊,但是知道每個人的高度 p[0] 以及他前面比他高的人的個數 p[1] , 本來如果這個people按照佇列的順序給我們每個人的這個p[]陣列,那輸入就是答案。但是現在題目把每個人的p[]陣列順序打亂了,讓我們求每個人在佇列中的位置,就是要把打亂的每個p[]順序還原
思路:
1. 先按身高降序排序,相同身高按k升序排序,經過此次排序後高的人一定在矮的人的前面並且相同高度的人的相對順序就是最終結果的相對順序。請記住這兩點,敲黑板
2. 建立一個集合,這個集合的每個元素是一個一維陣列,也就是我們二維陣列的一行。
3. 以行為單位遍歷排好序的people[][]陣列,假設每行資料是p[], 把每行元素插入到集合的索引為p[1]的位置,
4. 把集合中的資料轉換為一個二維陣列,返回即是正確結果
下面解釋為什麼經過第三步後就達到了我們題目要求的輸出結果:
經過第一步排序後高的人一定在矮的人的前面並且相同高度的人的相對順序就是最終結果的相對順序,所以 在進行第三步的過程中,高的人的資料肯定是先被存入集合的,所以每當我們取出一行資料,集合中已有的元素的身高肯定都是大於等於當前元素的身高的,所以當我們取出p[]陣列後,發現前面應該有p[1]個人比自己高或者高度和自己相同,那麼當前元素就應該排在集合的p[1]下標的位置(仔細想想是不是),好比說目前有一個佇列的人,這些人要麼比你高,要麼和你一樣高,現在要你插入入隊中,保證你前面有p[1]個人的身高大於等於你,你是不是應該排在索引為p[1]的位置
所以經過第三步的插入操作後,把每個人都插入到了正確的位置,所以根據這個集合轉換的二維陣列當然就是正確結果了。
1 class Solution {
2 public int[][] reconstructQueue(int[][] people) {
3 // 先按身高降序排序,相同身高按k升序排序
4 Arrays.sort(people, new Comparator<int[]>(){ // 排序的每個元素是一個一維陣列,也就是原二維陣列的一行資料
5 public int compare(int[] o1, int[] o2){ // 二維陣列排序還能這麼排,真是學到了,學到了
6 return o1[0] == o2[0] ? o1[1] - o2[1] : o2[0] - o1[0];
7 }
8 });
9
10 // 遍歷陣列,把每行元素新增到一個集合的p[1]位置
11 List<int[]> list = new LinkedList<int[]>(); // 把二維陣列一行元素作為一個物件
12 for(int[] p : people){
13 list.add(p[1], p);
14 }
15
16 int n = list.size();
17 // 返回集合轉換為陣列的陣列
18 return list.toArray(new int[n][2]); // 將集合轉換成二維陣列
19 }
20 }
力扣測試時間為10ms, 空間為40.9MB
複雜度分析:
時間複雜度:排序操作的時間是O(nlogn), 把一個元素插入到列表集合中的時間花費是O(n-k),因為需要把k位置以及k位置之後的元素往後移,插入n的元素的時間複雜度為
,所以最終的時間複雜度為O(n^2)空間複雜度為列表所佔空間和轉化為二維陣列所佔空間,都是O(N), 所以空間複雜度為O(N)