第一行输入两个正整数和
,用空格隔开。
第二行输入个正整数
,用空格隔开。
一个整数,代表最小的操作次数。
5 2 2 3 1 3 4
1
选择第二个数,使得其加2,数组变成[2,5,1,3,4],不存在两个相同的元素。
我们可以知道,如果数组中所有的数字都不相同,那么就不用进行调整了。
如果数组里面有重复出现的数字,就需要操作这些数字,而且我们只需要操作重复的数字。
显然,我们调整的时候,应该从小到大进行调整,于是,考虑用贪心法。
具体方法是:
对整个数组从小到大排序。
使用两个数据结构,一个结构是集合 set,存储当前已经调整后的数。另外一个是 map<int,int>,map中任意一个 key 和value对的含义是:操作每个 key 的值的时候,操作了 value 次,最后它的值为 key + value* k, 随后我们将 key + value* k 放入到 set 中。
用 ret 表示最终调整的总次数。
依次遍历数组中的数,对于每个数(用 key 表示),
最后的答案是3.2 步骤中所有数的操作次数之和。
最终整个操作的时间复杂度有排序和调整两部分组成,其为:
整个代码如下:
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
vector<int> v(n, 0);
unordered_set<int> us;
for (auto& e : v)cin >> e;
sort(v.begin(), v.end());
unordered_map<int, int> umap;
int64_t ret = 0;
for (auto& e : v) {
if (us.count(e) == 0) {
us.insert(e);
umap[e] = 0;
continue;
}
int cnt = umap[e] + 1;
while (us.count(cnt * k + e))
cnt++;
ret += cnt;
umap[e] = cnt;
us.insert(cnt * k + e);
}
std::cout << ret << std::endl;
}
// 64 位输出请用 printf("%lld")
/*
很简单的一道题,使用一个哈希表来存储<数,最小不重复数需增加的次数t>.每次
有新的数获取的时候,就需要查找这个数是否在哈希表中,如果有,那么就将原先的t+1,
当前的数加上t+1.在设置一个count来统计当前数增加的次数。没有出现过的数t统一为0.
*/
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
int main() {
int n, k;
cin>>n>>k;
vector<int> nums(n, 0);
unordered_map<int, int> ump;
long long ans = 0;
for(int i = 0; i < n; ++i) {
int num;
cin>>num;
while(ump.find(num) != ump.end()) {
ump[num] += 1;
ans += ump[num];
num += ump[num] * k;
}
ump[num] = 0;
}
cout << ans;
return 0;
}
// 64 位输出请用 printf("%lld") n, k = list(map(int, input().split()))
nums = list(map(int, input().split()))
num_dic = {}
for num in nums:
if num not in num_dic:
num_dic[num] = 0
num_dic[num] += 1
res = 0
for num in list(num_dic.keys()):
if num_dic[num] > 1:
last_val = num
last_res = 0
while num_dic[num] > 1:
val = last_val
cur_res = last_res
while val in num_dic.keys():
cur_res += 1
val += k
num_dic[val] = 1
num_dic[num] -= 1
res += cur_res
last_val = val
last_res = cur_res
print(res)