這是悅樂書的第352次更新,第377篇原創
java
今天介紹的是LeetCode
算法題中Easy
級別的第214
題(順位題號是914
)。在一副牌中,每張牌上都寫有一個整數。算法
當且僅當您能夠選擇X >= 2
時才返回true
,以即可以將整個牌組分紅一組或多組牌,其中:數組
每組都有X
張牌。數據結構
每組中的全部牌都具備相同的整數。測試
例如:優化
輸入:[1,2,3,4,4,3,2,1]
輸出:true
說明:可能的分區[1,1],[2,2],[3,3],[4,4]code
輸入:[1,1,1,2,2,2,3,3]
輸出:false
說明:沒有可能的分區。遞歸
輸入:[1]
輸出:false
說明:沒有可能的分區。get
輸入:[1,1]
輸出:true
說明:可能的分區[1,1]class
輸入:[1,1,2,2,2,2]
輸出:true
說明:可能的分區[1,1],[2,2],[2,2]
注意:
1 <= deck.length <= 10000
0 <= deck[i] <10000
題目的意思是將數組deck中的元素進行分組,值相等的劃分爲同一組,每一組中的元素個數都相等,且大於等於2。咱們可使用一個HashMap
,以deck
中的元素爲key
,以其出現次數爲value
,對HashMap
的value
值進行遍歷。
最理想的狀況,HashMap
中只有一組key-value
,但測試用例中確定不會這麼輕易讓你AC。來看幾組例子分析下規律:
{1,1,1,2,2,2,3,3} {{1,1,1},{2,2,2},{3,3}} --> {3,3,2} {1,1,2,2,2,2,3,3,3,3,3,3} {{1,1},{2,2,2,2},{3,3,3,3,3,3}} --> {2,4,6}
第一個例子中,他們的最大公約數爲1,即分組的組數存在奇偶分佈的狀況。
第二個例子中,他們的最大公約數爲2,即分組的組數都是偶數,而且對於其中的4個2和6個3,是還能夠繼續拆分的,4個2拆成兩組2個2,6個3拆成三組2個3。
所以,咱們只須要判斷HashMap
中每對數據的最大公約數是否是等於1便可。
public boolean hasGroupsSizeX(int[] deck) { if (deck.length < 2) { return false; } Map<Integer, Integer> map = new HashMap<Integer, Integer>(); for (int num : deck) { map.put(num, map.getOrDefault(num, 0)+1); } int count = 0; for (Integer value : map.values()) { if (value < 2) { return false; } if (count == 0) { count = value; } else { if (count != value) { int gcd = 1; for (int i=1; i<= count || i<=value; i++) { if (count%i == 0 && value%i == 0) { gcd = i; } } if (gcd == 1) { return false; } } } } return true; }
思路和第一種解法同樣,只是將其中部分代碼抽離了出來,而且簡化了一些if-else
判斷。
public boolean hasGroupsSizeX2(int[] deck) { if (deck.length < 2) { return false; } Map<Integer, Integer> map = new HashMap<Integer, Integer>(); for (int num : deck) { map.put(num, map.getOrDefault(num, 0)+1); } int min = 10001; for (Integer num : map.values()) { min = Math.min(min, num); } if (min == 1) { return false; } for (Integer num : map.values()) { if (getGCD(min, num) == 1) { return false; } } return true; } public int getGCD(int a, int b) { int gcd = 1; for (int i=1; i<= a || i<=b; i++) { if (a%i == 0 && b%i == 0) { gcd = i; } } return gcd; }
由於限定了數組deck
中元素值範圍,所以咱們可使用一個整型數組count
來計算deck
中各元素的出現次數,而後遍歷count
中的元素,求出他們的最大公約數,只要有一對數的最大公約數等於1,就直接返回false。
public boolean hasGroupsSizeX3(int[] deck) { int[] count = new int[10001]; for (int num : deck) { count[num]++; } int temp = -1; for (int num : count) { if (num > 0) { if (num < 2) { return false; } if (temp == -1) { temp = num; } else { if (getGCD(temp, num) == 1) { return false; } } } } return true; } public int getGCD(int a, int b) { int gcd = 1; for (int i=1; i<= a || i<=b; i++) { if (a%i == 0 && b%i == 0) { gcd = i; } } return gcd; }
對第三種解法,咱們還能夠再優化下,將求最大公約數的方法獨立處理,而且用遞歸處理。
public boolean hasGroupsSizeX4(int[] deck) { int[] count = new int[10001]; for (int num : deck) { count[num]++; } int tem = count[deck[0]]; for (int num : count) { if (num > 0) { tem = gcd(tem, num); } } return tem > 1; } /** * 利用遞歸求a和b的最大公約數 * @param a * @param b * @return */ public int gcd(int a, int b) { return a == 0 ? b : gcd(b%a, a); }
算法專題目前已連續日更超過六個月,算法題文章220+篇,公衆號對話框回覆【數據結構與算法】、【算法】、【數據結構】中的任一關鍵詞,獲取系列文章合集。
以上就是所有內容,若是你們有什麼好的解法思路、建議或者其餘問題,能夠下方留言交流,點贊、留言、轉發就是對我最大的回報和支持!