846. Hand of Straights, 1296. Divide Array in Sets of K Consecutive Numbers
use treeMap
T: O(nlogn*k)
S: O(n)
class Solution {
public boolean isPossibleDivide(int[] nums, int k) {
int n = nums.length;
if (n%k != 0) {
return false;
}
TreeMap<Integer, Integer> map = new TreeMap<>(); // num, count
for (int num : nums) {
map.put(num, map.getOrDefault(num, 0) + 1);
}
for (int key : map.keySet()) {
if (map.get(key) > 0) {
for (int i = k - 1; i >= 0; i--) {
if (map.getOrDefault(key+i, 0) < map.get(key)) {
return false;
}
map.put(key + i, map.getOrDefault(key+i, 0) - map.get(key));
}
}
}
return true;
}
}
/*
sets of k consecutive numbers.
array is size k
Divide to one more array
use treeMap, sort and get freq map
[1,2,3,3,4,4,5,6]
after sort and get freq map
1 1 2 2 1 1 => count
1 2 3 4 5 6 => nums
[ ] k = 4
after subtract with nums[0] = 1
0 0 1 1 1 1
1 2 3 4 5 6
subtract with nums[2] = 1
0 0 1 1 1 1
1 2 3 4 5 6
[ ]
*/
use hashmap + min, max value
T: O(n*k)
S: O(n)
class Solution {
public boolean isNStraightHand(int[] nums, int k) {
int m = nums.length, min = Integer.MAX_VALUE, max = Integer.MIN_VALUE;
if (m % k != 0) {
return false;
}
Map<Integer, Integer> map = new HashMap<>();
for (int n : nums) {
min = Math.min(min, n);
max = Math.max(max, n);
map.put(n, map.getOrDefault(n, 0) + 1);
}
// 少掉 sort 的關鍵在於知道 min, max, 所以就可以檢查 [min, max] 區間內連續的值的結果
for (int i = min; i <= max; i++) {
if (map.getOrDefault(i, 0) < 0) { // < 0 代表缺數
return false; // lacks
}
if (map.getOrDefault(i, 0) == 0) {// == 0 pass
continue;
}
// 不符 sliding win
if (max - i + 1 < k) { // i = 3, 6-3+1 = 4 ==k 還行, i = 4 就不夠了
return false; // extras, won't make k subset;
}
// 一樣倒著檢查
// i = 3, j = 3+4-1 = 6, 6 to 3
for (int j = i + k - 1; j >= i; j--) {
map.put(j, map.getOrDefault(j, 0) - map.get(i));
}
}
return true;
}
}
/*
[1,2,3,3,4,4,5,6]
4
ans
[1,2,3,4] 和 [3,4,5,6]
有點 sliding window feel
1 1 2 2 1 1 => count
[1,2,3,4,5,6]
[ ]
[ ]
*/
HashMap + Sort
T: O(n + nlogn + n*k)
S: O(n)
class Solution {
public boolean isPossibleDivide(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<>();
for (int num : nums) {
map.put(num, map.getOrDefault(num, 0)+1);
}
Arrays.sort(nums);
for (int j = 0; j < nums.length; j++) {
if (map.get(nums[j]) == 0) {
continue;
}
for (int i = 1; i < k; i++) {
int nextNum = nums[j] + i;
if (!map.containsKey(nextNum) || map.get(nextNum) == 0) {
return false;
}
}
for (int i = 0; i < k; i++) {
int updateNum = nums[j] + i;
map.put(updateNum, map.get(updateNum) - 1);
}
}
return true;
}
}
Find Roots (amazing solution)
T: O(n)
S: O(n)
```java
public class Solution {
public boolean isPossibleDivide(int[] nums, int k) {
Map<Integer, Integer> countMap = new HashMap<>();
Queue<Integer> roots = new LinkedList<>();
// Count occurrences of each number
for (int num : nums) {
countMap.put(num, countMap.getOrDefault(num, 0) + 1);
}
// Identify potential "roots"
for (int num : nums) {
if (!countMap.containsKey(num - 1)) {
roots.offer(num);
}
}
System.out.println(roots.toString());
// Test each "root"
while (!roots.isEmpty()) {
int root = roots.poll();
if (countMap.get(root) == 0) {
continue;
}
// Attempt to build a sequence from root to root + k
for (int i = root; i <= root + k; i++) {
if (i < root + k) {
if (!countMap.containsKey(i) || countMap.get(i) == 0) {
return false;
}
// Decrement the count for this number
countMap.put(i, countMap.get(i) - 1);
}
// check to root+k (aka next start for previous k consecuitive numbers)
// Identify new "roots"
// ex: 1 2 3 "4". (k = 3), we check this 4 has count
if (countMap.containsKey(i) && countMap.get(i) > 0 && (!countMap.containsKey(i-1) || countMap.get(i-1) == 0)) {
roots.offer(i);
}
}
}
return true;
}
}
```
Last updated