题目
给你一个长度为 n
的二维整数数组 items
和一个整数 k
。
items[i] = [profiti, categoryi]
,其中 profiti
和 categoryi
分别表示第 i
个项目的利润和类别。
现定义 items
的 子序列 的 优雅度 可以用 total_profit + distinct_categories2
计算,其中 total_profit
是子序列中所有项目的利润总和,distinct_categories
是所选子序列所含的所有类别中不同类别的数量。
你的任务是从 items
所有长度为 k
的子序列中,找出 最大优雅度 。
用整数形式表示并返回 items
中所有长度恰好为 k
的子序列的最大优雅度。
注意:数组的子序列是经由原数组删除一些元素(可能不删除)而产生的新数组,且删除不改变其余元素相对顺序。
示例 1:
输入:items = [[3,2],[5,1],[10,1]], k = 2 输出:17 解释: 在这个例子中,我们需要选出长度为 2 的子序列。 其中一种方案是 items[0] = [3,2] 和 items[2] = [10,1] 。 子序列的总利润为 3 + 10 = 13 ,子序列包含 2 种不同类别 [2,1] 。 因此,优雅度为 13 + 22 = 17 ,可以证明 17 是可以获得的最大优雅度。
示例 2:
输入:items = [[3,1],[3,1],[2,2],[5,3]], k = 3 输出:19 解释: 在这个例子中,我们需要选出长度为 3 的子序列。 其中一种方案是 items[0] = [3,1] ,items[2] = [2,2] 和 items[3] = [5,3] 。 子序列的总利润为 3 + 2 + 5 = 10 ,子序列包含 3 种不同类别 [1, 2, 3] 。 因此,优雅度为 10 + 32 = 19 ,可以证明 19 是可以获得的最大优雅度。
示例 3:
输入:items = [[1,1],[2,1],[3,1]], k = 3 输出:7 解释: 在这个例子中,我们需要选出长度为 3 的子序列。 我们需要选中所有项目。 子序列的总利润为 1 + 2 + 3 = 6,子序列包含 1 种不同类别 [1] 。 因此,最大优雅度为 6 + 12 = 7 。
思路
求优雅度,要考虑两个因素,一个是利润,一个是种类,先对数组进行逆序排序,取前k个值的总利润,以及种类。对第k+1个,进行判断。考虑是否能增加种类,因为经过排序,利润已经不可能不前面的值大了。在考虑数组有没有重复的种类,没有的话,也无法代替。理由同上如果是没有的种类且目前的取值有重复的种类。替换重复的种类,保留最大优雅度。
解题方法
用一个Set(不重复无序集)来保存目前取值的种类,将排序完的前k个值累加,建立一个栈。用来保存目前最小的种类重复利润。(利用排序完的数组和栈后进先出的特点)。对k+1如果是没有的种类即set添加成功。判断栈是否为空(是否有重复种类)替换保留最大。如果set添加失败或栈不为空,无事发生。
代码
class Solution {
public long findMaximumElegance(int[][] items, int k) {
Arrays.sort(items,(a,b)->b[0]-a[0]);
Set<Integer> cf=new HashSet<>();
Deque<Integer> repo =new ArrayDeque<>();
long ans=0;
long totalProfit=0;
for(int i=0;i<items.length;i++){
int profit=items[i][0];
int kind =items[i][1];
if(i<k){
totalProfit=totalProfit+profit;
if(!cf.add(kind)){
repo.push(profit);
}
}else if(!repo.isEmpty()&&cf.add(kind)){
totalProfit=totalProfit-repo.pop();
totalProfit=totalProfit+profit;
}
ans=Math.max(ans,totalProfit+(long)cf.size()*cf.size());
}
return ans;
}
}