Welcome to Subscribe On Youtube
1296. Divide Array in Sets of K Consecutive Numbers
Description
Given an array of integers nums and a positive integer k, check whether it is possible to divide this array into sets of k consecutive numbers.
Return true if it is possible. Otherwise, return false.
Example 1:
Input: nums = [1,2,3,3,4,4,5,6], k = 4 Output: true Explanation: Array can be divided into [1,2,3,4] and [3,4,5,6].
Example 2:
Input: nums = [3,2,1,2,3,4,3,4,5,9,10,11], k = 3 Output: true Explanation: Array can be divided into [1,2,3] , [2,3,4] , [3,4,5] and [9,10,11].
Example 3:
Input: nums = [1,2,3,4], k = 3 Output: false Explanation: Each array should be divided in subarrays of size 3.
Constraints:
1 <= k <= nums.length <= 1051 <= nums[i] <= 109
Note: This question is the same as 846: https://leetcode.com/problems/hand-of-straights/
Solutions
-
class Solution { public boolean isPossibleDivide(int[] nums, int k) { Map<Integer, Integer> cnt = new HashMap<>(); for (int v : nums) { cnt.put(v, cnt.getOrDefault(v, 0) + 1); } Arrays.sort(nums); for (int v : nums) { if (cnt.containsKey(v)) { for (int x = v; x < v + k; ++x) { if (!cnt.containsKey(x)) { return false; } cnt.put(x, cnt.get(x) - 1); if (cnt.get(x) == 0) { cnt.remove(x); } } } } return true; } } -
class Solution { public: bool isPossibleDivide(vector<int>& nums, int k) { unordered_map<int, int> cnt; for (int& v : nums) ++cnt[v]; sort(nums.begin(), nums.end()); for (int& v : nums) { if (cnt.count(v)) { for (int x = v; x < v + k; ++x) { if (!cnt.count(x)) { return false; } if (--cnt[x] == 0) { cnt.erase(x); } } } } return true; } }; -
class Solution: def isPossibleDivide(self, nums: List[int], k: int) -> bool: cnt = Counter(nums) for v in sorted(nums): if cnt[v]: for x in range(v, v + k): if cnt[x] == 0: return False cnt[x] -= 1 if cnt[x] == 0: cnt.pop(x) return True -
func isPossibleDivide(nums []int, k int) bool { cnt := map[int]int{} for _, v := range nums { cnt[v]++ } sort.Ints(nums) for _, v := range nums { if _, ok := cnt[v]; ok { for x := v; x < v+k; x++ { if _, ok := cnt[x]; !ok { return false } cnt[x]-- if cnt[x] == 0 { delete(cnt, x) } } } } return true } -
function isPossibleDivide(nums: number[], k: number): boolean { if (nums.length % k !== 0) { return false; } const cnt = new Map<number, number>(); for (const x of nums) { cnt.set(x, (cnt.get(x) || 0) + 1); } nums.sort((a, b) => a - b); for (const x of nums) { if (cnt.get(x)! > 0) { for (let y = x; y < x + k; y++) { if ((cnt.get(y) || 0) === 0) { return false; } cnt.set(y, cnt.get(y)! - 1); } } } return true; } -
class Solution { public boolean isPossibleDivide(int[] nums, int k) { if (nums.length % k != 0) { return false; } TreeMap<Integer, Integer> tm = new TreeMap<>(); for (int x : nums) { tm.merge(x, 1, Integer::sum); } while (!tm.isEmpty()) { int x = tm.firstKey(); for (int y = x; y < x + k; ++y) { int t = tm.merge(y, -1, Integer::sum); if (t < 0) { return false; } if (t == 0) { tm.remove(y); } } } return true; } } -
class Solution { public: bool isPossibleDivide(vector<int>& nums, int k) { if (nums.size() % k) { return false; } map<int, int> mp; for (int x : nums) { ++mp[x]; } while (!mp.empty()) { int x = mp.begin()->first; for (int y = x; y < x + k; ++y) { if (!mp.contains(y)) { return false; } if (--mp[y] == 0) { mp.erase(y); } } } return true; } }; -
class Solution: def isPossibleDivide(self, nums: List[int], k: int) -> bool: if len(nums) % k: return False cnt = Counter(nums) sd = SortedDict(cnt) while sd: x = next(iter(sd)) for y in range(x, x + k): if y not in sd: return False if sd[y] == 1: del sd[y] else: sd[y] -= 1 return True -
func isPossibleDivide(nums []int, k int) bool { if len(nums)%k != 0 { return false } tm := treemap.NewWithIntComparator() for _, x := range nums { if v, ok := tm.Get(x); ok { tm.Put(x, v.(int)+1) } else { tm.Put(x, 1) } } for !tm.Empty() { x, _ := tm.Min() for y := x.(int); y < x.(int)+k; y++ { if v, ok := tm.Get(y); ok { if v.(int) == 1 { tm.Remove(y) } else { tm.Put(y, v.(int)-1) } } else { return false } } } return true } -
function isPossibleDivide(nums: number[], k: number): boolean { if (nums.length % k !== 0) { return false; } const tm = new TreeMap<number, number>(); for (const x of nums) { tm.set(x, (tm.get(x) || 0) + 1); } while (tm.size()) { const x = tm.first()![0]; for (let y = x; y < x + k; ++y) { if (!tm.has(y)) { return false; } if (tm.get(y)! === 1) { tm.delete(y); } else { tm.set(y, tm.get(y)! - 1); } } } return true; } type Compare<T> = (lhs: T, rhs: T) => number; class RBTreeNode<T = number> { data: T; count: number; left: RBTreeNode<T> | null; right: RBTreeNode<T> | null; parent: RBTreeNode<T> | null; color: number; constructor(data: T) { this.data = data; this.left = this.right = this.parent = null; this.color = 0; this.count = 1; } sibling(): RBTreeNode<T> | null { if (!this.parent) return null; // sibling null if no parent return this.isOnLeft() ? this.parent.right : this.parent.left; } isOnLeft(): boolean { return this === this.parent!.left; } hasRedChild(): boolean { return ( Boolean(this.left && this.left.color === 0) || Boolean(this.right && this.right.color === 0) ); } } class RBTree<T> { root: RBTreeNode<T> | null; lt: (l: T, r: T) => boolean; constructor(compare: Compare<T> = (l: T, r: T) => (l < r ? -1 : l > r ? 1 : 0)) { this.root = null; this.lt = (l: T, r: T) => compare(l, r) < 0; } rotateLeft(pt: RBTreeNode<T>): void { const right = pt.right!; pt.right = right.left; if (pt.right) pt.right.parent = pt; right.parent = pt.parent; if (!pt.parent) this.root = right; else if (pt === pt.parent.left) pt.parent.left = right; else pt.parent.right = right; right.left = pt; pt.parent = right; } rotateRight(pt: RBTreeNode<T>): void { const left = pt.left!; pt.left = left.right; if (pt.left) pt.left.parent = pt; left.parent = pt.parent; if (!pt.parent) this.root = left; else if (pt === pt.parent.left) pt.parent.left = left; else pt.parent.right = left; left.right = pt; pt.parent = left; } swapColor(p1: RBTreeNode<T>, p2: RBTreeNode<T>): void { const tmp = p1.color; p1.color = p2.color; p2.color = tmp; } swapData(p1: RBTreeNode<T>, p2: RBTreeNode<T>): void { const tmp = p1.data; p1.data = p2.data; p2.data = tmp; } fixAfterInsert(pt: RBTreeNode<T>): void { let parent = null; let grandParent = null; while (pt !== this.root && pt.color !== 1 && pt.parent?.color === 0) { parent = pt.parent; grandParent = pt.parent.parent; /* Case : A Parent of pt is left child of Grand-parent of pt */ if (parent === grandParent?.left) { const uncle = grandParent.right; /* Case : 1 The uncle of pt is also red Only Recoloring required */ if (uncle && uncle.color === 0) { grandParent.color = 0; parent.color = 1; uncle.color = 1; pt = grandParent; } else { /* Case : 2 pt is right child of its parent Left-rotation required */ if (pt === parent.right) { this.rotateLeft(parent); pt = parent; parent = pt.parent; } /* Case : 3 pt is left child of its parent Right-rotation required */ this.rotateRight(grandParent); this.swapColor(parent!, grandParent); pt = parent!; } } else { /* Case : B Parent of pt is right child of Grand-parent of pt */ const uncle = grandParent!.left; /* Case : 1 The uncle of pt is also red Only Recoloring required */ if (uncle != null && uncle.color === 0) { grandParent!.color = 0; parent.color = 1; uncle.color = 1; pt = grandParent!; } else { /* Case : 2 pt is left child of its parent Right-rotation required */ if (pt === parent.left) { this.rotateRight(parent); pt = parent; parent = pt.parent; } /* Case : 3 pt is right child of its parent Left-rotation required */ this.rotateLeft(grandParent!); this.swapColor(parent!, grandParent!); pt = parent!; } } } this.root!.color = 1; } delete(val: T): boolean { const node = this.find(val); if (!node) return false; node.count--; if (!node.count) this.deleteNode(node); return true; } deleteAll(val: T): boolean { const node = this.find(val); if (!node) return false; this.deleteNode(node); return true; } deleteNode(v: RBTreeNode<T>): void { const u = BSTreplace(v); // True when u and v are both black const uvBlack = (u === null || u.color === 1) && v.color === 1; const parent = v.parent!; if (!u) { // u is null therefore v is leaf if (v === this.root) this.root = null; // v is root, making root null else { if (uvBlack) { // u and v both black // v is leaf, fix double black at v this.fixDoubleBlack(v); } else { // u or v is red if (v.sibling()) { // sibling is not null, make it red" v.sibling()!.color = 0; } } // delete v from the tree if (v.isOnLeft()) parent.left = null; else parent.right = null; } return; } if (!v.left || !v.right) { // v has 1 child if (v === this.root) { // v is root, assign the value of u to v, and delete u v.data = u.data; v.left = v.right = null; } else { // Detach v from tree and move u up if (v.isOnLeft()) parent.left = u; else parent.right = u; u.parent = parent; if (uvBlack) this.fixDoubleBlack(u); // u and v both black, fix double black at u else u.color = 1; // u or v red, color u black } return; } // v has 2 children, swap data with successor and recurse this.swapData(u, v); this.deleteNode(u); // find node that replaces a deleted node in BST function BSTreplace(x: RBTreeNode<T>): RBTreeNode<T> | null { // when node have 2 children if (x.left && x.right) return successor(x.right); // when leaf if (!x.left && !x.right) return null; // when single child return x.left ?? x.right; } // find node that do not have a left child // in the subtree of the given node function successor(x: RBTreeNode<T>): RBTreeNode<T> { let temp = x; while (temp.left) temp = temp.left; return temp; } } fixDoubleBlack(x: RBTreeNode<T>): void { if (x === this.root) return; // Reached root const sibling = x.sibling(); const parent = x.parent!; if (!sibling) { // No sibiling, double black pushed up this.fixDoubleBlack(parent); } else { if (sibling.color === 0) { // Sibling red parent.color = 0; sibling.color = 1; if (sibling.isOnLeft()) this.rotateRight(parent); // left case else this.rotateLeft(parent); // right case this.fixDoubleBlack(x); } else { // Sibling black if (sibling.hasRedChild()) { // at least 1 red children if (sibling.left && sibling.left.color === 0) { if (sibling.isOnLeft()) { // left left sibling.left.color = sibling.color; sibling.color = parent.color; this.rotateRight(parent); } else { // right left sibling.left.color = parent.color; this.rotateRight(sibling); this.rotateLeft(parent); } } else { if (sibling.isOnLeft()) { // left right sibling.right!.color = parent.color; this.rotateLeft(sibling); this.rotateRight(parent); } else { // right right sibling.right!.color = sibling.color; sibling.color = parent.color; this.rotateLeft(parent); } } parent.color = 1; } else { // 2 black children sibling.color = 0; if (parent.color === 1) this.fixDoubleBlack(parent); else parent.color = 1; } } } } insert(data: T): boolean { // search for a position to insert let parent = this.root; while (parent) { if (this.lt(data, parent.data)) { if (!parent.left) break; else parent = parent.left; } else if (this.lt(parent.data, data)) { if (!parent.right) break; else parent = parent.right; } else break; } // insert node into parent const node = new RBTreeNode(data); if (!parent) this.root = node; else if (this.lt(node.data, parent.data)) parent.left = node; else if (this.lt(parent.data, node.data)) parent.right = node; else { parent.count++; return false; } node.parent = parent; this.fixAfterInsert(node); return true; } search(predicate: (val: T) => boolean, direction: 'left' | 'right'): T | undefined { let p = this.root; let result = null; while (p) { if (predicate(p.data)) { result = p; p = p[direction]; } else { p = p[direction === 'left' ? 'right' : 'left']; } } return result?.data; } find(data: T): RBTreeNode<T> | null { let p = this.root; while (p) { if (this.lt(data, p.data)) { p = p.left; } else if (this.lt(p.data, data)) { p = p.right; } else break; } return p ?? null; } count(data: T): number { const node = this.find(data); return node ? node.count : 0; } *inOrder(root: RBTreeNode<T> = this.root!): Generator<T, undefined, void> { if (!root) return; for (const v of this.inOrder(root.left!)) yield v; yield root.data; for (const v of this.inOrder(root.right!)) yield v; } *reverseInOrder(root: RBTreeNode<T> = this.root!): Generator<T, undefined, void> { if (!root) return; for (const v of this.reverseInOrder(root.right!)) yield v; yield root.data; for (const v of this.reverseInOrder(root.left!)) yield v; } } class TreeMap<K = number, V = unknown> { _size: number; tree: RBTree<K>; map: Map<K, V> = new Map(); compare: Compare<K>; constructor( collection: Array<[K, V]> | Compare<K> = [], compare: Compare<K> = (l: K, r: K) => (l < r ? -1 : l > r ? 1 : 0), ) { if (typeof collection === 'function') { compare = collection; collection = []; } this._size = 0; this.compare = compare; this.tree = new RBTree(compare); for (const [key, val] of collection) this.set(key, val); } size(): number { return this._size; } has(key: K): boolean { return !!this.tree.find(key); } get(key: K): V | undefined { return this.map.get(key); } set(key: K, val: V): boolean { const successful = this.tree.insert(key); this._size += successful ? 1 : 0; this.map.set(key, val); return successful; } delete(key: K): boolean { const deleted = this.tree.deleteAll(key); this._size -= deleted ? 1 : 0; return deleted; } ceil(target: K): [K, V] | undefined { return this.toKeyValue(this.tree.search(key => this.compare(key, target) >= 0, 'left')); } floor(target: K): [K, V] | undefined { return this.toKeyValue(this.tree.search(key => this.compare(key, target) <= 0, 'right')); } higher(target: K): [K, V] | undefined { return this.toKeyValue(this.tree.search(key => this.compare(key, target) > 0, 'left')); } lower(target: K): [K, V] | undefined { return this.toKeyValue(this.tree.search(key => this.compare(key, target) < 0, 'right')); } first(): [K, V] | undefined { return this.toKeyValue(this.tree.inOrder().next().value); } last(): [K, V] | undefined { return this.toKeyValue(this.tree.reverseInOrder().next().value); } shift(): [K, V] | undefined { const first = this.first(); if (first === undefined) return undefined; this.delete(first[0]); return first; } pop(): [K, V] | undefined { const last = this.last(); if (last === undefined) return undefined; this.delete(last[0]); return last; } toKeyValue(key: K): [K, V]; toKeyValue(key: undefined): undefined; toKeyValue(key: K | undefined): [K, V] | undefined; toKeyValue(key: K | undefined): [K, V] | undefined { return key != null ? [key, this.map.get(key)!] : undefined; } *[Symbol.iterator](): Generator<[K, V], void, void> { for (const key of this.keys()) yield this.toKeyValue(key); } *keys(): Generator<K, void, void> { for (const key of this.tree.inOrder()) yield key; } *values(): Generator<V, undefined, void> { for (const key of this.keys()) yield this.map.get(key)!; return undefined; } *rkeys(): Generator<K, undefined, void> { for (const key of this.tree.reverseInOrder()) yield key; return undefined; } *rvalues(): Generator<V, undefined, void> { for (const key of this.rkeys()) yield this.map.get(key)!; return undefined; } }