You are given a 0-indexed 2D integer array items
of length n
and an integer k
.
items[i] = [profiti, categoryi]
, where profiti
and categoryi
denote the profit and category of the ith
item respectively.
Let's define the elegance of a subsequence of items
as total_profit + distinct_categories2
, where total_profit
is the sum of all profits in the subsequence, and distinct_categories
is the number of distinct categories from all the categories in the selected subsequence.
Your task is to find the maximum elegance from all subsequences of size k
in items
.
Return an integer denoting the maximum elegance of a subsequence of items
with size exactly k
.
Note: A subsequence of an array is a new array generated from the original array by deleting some elements (possibly none) without changing the remaining elements' relative order.
Example 1:
Input: items = [[3,2],[5,1],[10,1]], k = 2 Output: 17 Explanation: In this example, we have to select a subsequence of size 2. We can select items[0] = [3,2] and items[2] = [10,1]. The total profit in this subsequence is 3 + 10 = 13, and the subsequence contains 2 distinct categories [2,1]. Hence, the elegance is 13 + 22 = 17, and we can show that it is the maximum achievable elegance.
Example 2:
Input: items = [[3,1],[3,1],[2,2],[5,3]], k = 3 Output: 19 Explanation: In this example, we have to select a subsequence of size 3. We can select items[0] = [3,1], items[2] = [2,2], and items[3] = [5,3]. The total profit in this subsequence is 3 + 2 + 5 = 10, and the subsequence contains 3 distinct categories [1,2,3]. Hence, the elegance is 10 + 32 = 19, and we can show that it is the maximum achievable elegance.
Example 3:
Input: items = [[1,1],[2,1],[3,1]], k = 3 Output: 7 Explanation: In this example, we have to select a subsequence of size 3. We should select all the items. The total profit will be 1 + 2 + 3 = 6, and the subsequence contains 1 distinct category [1]. Hence, the maximum elegance is 6 + 12 = 7.
Constraints:
1 <= items.length == n <= 105
items[i].length == 2
items[i][0] == profiti
items[i][1] == categoryi
1 <= profiti <= 109
1 <= categoryi <= n
1 <= k <= n
Solution 1: Greedy
We can sort all items by profit from large to small. First choose the first
Next, we consider starting from the
Finally, we return
The time complexity is
class Solution:
def findMaximumElegance(self, items: List[List[int]], k: int) -> int:
items.sort(key=lambda x: -x[0])
tot = 0
vis = set()
dup = []
for p, c in items[:k]:
tot += p
if c not in vis:
vis.add(c)
else:
dup.append(p)
ans = tot + len(vis) ** 2
for p, c in items[k:]:
if c in vis or not dup:
continue
vis.add(c)
tot += p - dup.pop()
ans = max(ans, tot + len(vis) ** 2)
return ans
class Solution {
public long findMaximumElegance(int[][] items, int k) {
Arrays.sort(items, (a, b) -> b[0] - a[0]);
int n = items.length;
long tot = 0;
Set<Integer> vis = new HashSet<>();
Deque<Integer> dup = new ArrayDeque<>();
for (int i = 0; i < k; ++i) {
int p = items[i][0], c = items[i][1];
tot += p;
if (!vis.add(c)) {
dup.push(p);
}
}
long ans = tot + (long) vis.size() * vis.size();
for (int i = k; i < n; ++i) {
int p = items[i][0], c = items[i][1];
if (vis.contains(c) || dup.isEmpty()) {
continue;
}
vis.add(c);
tot += p - dup.pop();
ans = Math.max(ans, tot + (long) vis.size() * vis.size());
}
return ans;
}
}
class Solution {
public:
long long findMaximumElegance(vector<vector<int>>& items, int k) {
sort(items.begin(), items.end(), [](const vector<int>& a, const vector<int>& b) {
return a[0] > b[0];
});
long long tot = 0;
unordered_set<int> vis;
stack<int> dup;
for (int i = 0; i < k; ++i) {
int p = items[i][0], c = items[i][1];
tot += p;
if (vis.count(c)) {
dup.push(p);
} else {
vis.insert(c);
}
}
int n = items.size();
long long ans = tot + 1LL * vis.size() * vis.size();
for (int i = k; i < n; ++i) {
int p = items[i][0], c = items[i][1];
if (vis.count(c) || dup.empty()) {
continue;
}
vis.insert(c);
tot += p - dup.top();
dup.pop();
ans = max(ans, tot + (long long) (1LL * vis.size() * vis.size()));
}
return ans;
}
};
func findMaximumElegance(items [][]int, k int) int64 {
sort.Slice(items, func(i, j int) bool { return items[i][0] > items[j][0] })
tot := 0
vis := map[int]bool{}
dup := []int{}
for _, item := range items[:k] {
p, c := item[0], item[1]
tot += p
if vis[c] {
dup = append(dup, p)
} else {
vis[c] = true
}
}
ans := tot + len(vis)*len(vis)
for _, item := range items[k:] {
p, c := item[0], item[1]
if vis[c] || len(dup) == 0 {
continue
}
vis[c] = true
tot += p - dup[len(dup)-1]
dup = dup[:len(dup)-1]
ans = max(ans, tot+len(vis)*len(vis))
}
return int64(ans)
}
function findMaximumElegance(items: number[][], k: number): number {
items.sort((a, b) => b[0] - a[0]);
let tot = 0;
const vis: Set<number> = new Set();
const dup: number[] = [];
for (const [p, c] of items.slice(0, k)) {
tot += p;
if (vis.has(c)) {
dup.push(p);
} else {
vis.add(c);
}
}
let ans = tot + vis.size ** 2;
for (const [p, c] of items.slice(k)) {
if (vis.has(c) || dup.length === 0) {
continue;
}
tot += p - dup.pop()!;
vis.add(c);
ans = Math.max(ans, tot + vis.size ** 2);
}
return ans;
}