41 Group the People Given the Group Size They Belong To

題目

There are n people whose IDs go from 0 to n - 1 and each person belongs exactly to one group. Given the array groupSizes of length n telling the group size each person belongs to, return the groups there are and the people’s IDs each group includes.

You can return any solution in any order and the same applies for IDs. Also, it is guaranteed that there exists at least one solution.

Example 1:

Input: groupSizes = [3,3,3,3,3,1,3]
Output: [[5],[0,1,2],[3,4,6]]
Explanation:
Other possible solutions are [[2,1,6],[5],[0,4,3]] and [[5],[0,6,2],[4,3,1]].

Example 2:

Input: groupSizes = [2,1,3,3,3,2]
Output: [[1],[0,5],[2,3,4]]

Constraints:

groupSizes.length == n
1 <= n <= 500
1 <= groupSizes[i] <= n

分析

題意:groupSizes中的數字表示:當前這個人所屬的組的總人數。
[2,1,3,3,3,2]意思是
0號ID所屬組的人數爲2
1號ID所屬組的人數爲1
2號ID所屬組的人數爲3
3號ID所屬組的人數爲3
4號ID所屬組的人數爲3
5號ID所屬組的人數爲2

顯然,0和5爲一組,1單人一組,2,3,4爲一組
所以結果爲[[0,5],[1],[2,3,4]]

分析:

  1. 最簡單的情況,相同groupSize的且個數等於groupSize的,對應下標一定是同組。如[2,2],groupsize=2,且個數爲2,。
  2. 相同groupSize但個數不等於groupSize,此時個數一定是偶數倍可均分。如[2,2,2,2](不可能出現[2,2,2]),此時答案可以是0,1,2,3的任意兩兩組合。

算法:

1. 將groupSize中相同的值的"下標"放在一個數組中;
2. 如果“相同的值的個數”等於“相同值”,就把該數組加到結果集;
	否則:
		創建“相同值的個數/2”個數組,將下標均分在這些數組中,加入結果集;
3. 返回結果集

如何完成第一步?其實跟“找出數組中的所有相同值”方法一樣:
遍歷groupSize,如果groupSizes[i]==x,將i加入tmp數組中,直到i=groupSizes.length;最後返回該tmp數組

如何完成“下標均分”?
以[2,2,2,2]爲例:
創建“相同值的個數/groupSizes[i]”個數組 --> 創建2個數組
每組均分“相同值”個數組 --> 即每組均分2個數據,[0,1] [2,3]

解答

這個算法有個錯誤,我改不出來。
在這裏插入圖片描述

返回的結果是正確的,但是多了,個數等於n * tmp.size() / groupSizes[i];
我試了試把創建tmp單獨放在外面,個數爲groupSizes去重後的大小,然而仍然不正確。

class Solution {
    public List<List<Integer>> groupThePeople(int[] groupSizes) {
        List<List<Integer>> res = new ArrayList<>();
        int n = groupSizes.length;
        int i=0;
        while(i<n){
            List<Integer> tmp = search(groupSizes[i],groupSizes);
            int k=0;
            if(tmp.size()==groupSizes[i])
                res.add(tmp);
            else{
                for(int j=0;j<tmp.size()/groupSizes[i];++j){
                    List<Integer> tmp2 = new ArrayList<>();
                    int flag=groupSizes[i];
                    while(flag>0){
                        tmp2.add(tmp.get(k++));
                        flag--;
                    }
                    res.add(tmp2);
                }
                k=0;
            }
            i++;
        }
        return res;
    }
    // 返回所有相同組數的下標(組員)
    public List<Integer> search(int x,int[] groupSizes){
        List<Integer> tmp = new ArrayList<>();
        for(int i=0;i<groupSizes.length;++i){
            if(x==groupSizes[i])
                tmp.add(i);
        }
        return tmp;
    }
}

看看評論區答案,算法類似,但是通過Map,更加簡單。

class Solution {
        public List<List<Integer>> groupThePeople(int[] groupSizes) {
        // 存放結果集
        List<List<Integer>> res=new ArrayList<>();
        // key:組成員數,value:所有組員
        Map<Integer, List<Integer>> map=new HashMap<>();
        for(int i=0;i<groupSizes.length;i++) {
        	// 如果map中不存在這個成員組數,就加到map中
            if(!map.containsKey(groupSizes[i])) map.put(groupSizes[i], new ArrayList<>());
            // 獲取當前成員小組
            List<Integer> cur=map.get(groupSizes[i]);
            // 把當前成員加到小組中
            cur.add(i);
            // 如果當前組成員數等於實際組成員數
            if(cur.size()==groupSizes[i]) {
                res.add(cur);
                // 將當前組移除
                map.remove(groupSizes[i]);
            }
            // 如果當前組成員數不等於實際組成員數,也就是分析中算法的第二種情況,此時回到循環開頭map.containsKey判斷就不成立,就不會創建新的list。通過這種方式,解決了我上述算法的問題。
        }
        return res;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章