移除石子使总数最小
给你一个整数数组 piles ,数组 下标从 0 开始 ,其中 piles[i] 表示第 i 堆石子中的石子数量。另给你一个整数 k ,请你执行下述操作 恰好 k 次:
选出任一石子堆 piles[i] ,并从中 移除 floor(piles[i] / 2) 颗石子。
注意:你可以对 同一堆 石子多次执行此操作。
返回执行 k 次操作后,剩下石子的 最小 总数。
floor(x) 为 小于 或 等于 x 的 最大 整数。(即,对 x 向下取整)。
对于这个题目,最简单的做法,就是直接每次取一次最大值,然后更新一次序列,但是算法时间并不能通过要求,如果排序之后在进行操作,也不能通过,不过下面算法思想是正确的,额可以借鉴。
int max_index(int *p,int size){
int i=1;
int m=p[0];
int po=0;
for(i;i<size;i++){
if(m<p[i]){
m=p[i];
po=i;
}
}
return po;
}
int minStoneSum(int* piles, int pilesSize, int k){
int i=0;
int index;
int sum=0;
for(i;i<k;i++){
index =max_index(piles,pilesSize);
// printf("%d ",index);
piles[index]=piles[index]-floor(piles[index]/ 2);
}
for(i=0;i<pilesSize;i++){
sum=sum+piles[i];
}
return sum;
}
那么,该怎么办呢,于是有了下面这个算法,如果数都不大的话,我们可以直接将数存储在一个大的数组中,并且下标就为其数据值,然后,我们就可以从上往下进行遍历,同时可能出翔相同的值,那么,我们可以统计一下数据元素个数,为零的时候,我们才进行下次遍历。
int minStoneSum(int* piles, int pilesSize, int k){
int hash[10001] = {0};
for (int i = 0; i < pilesSize; i++) {
hash[piles[i]]++;
}
for (int i = 10000; i > 0; i--) {
if (hash[i] > 0) {
hash[i]--;
int temp = i - floor(i / 2);
hash[temp]++;
i++;
k--;
}
if (k == 0) {
break;
}
}
int ans = 0;
for (int i = 0; i < 10001; i++) {
if (hash[i] != 0) {
ans += hash[i] * i;
}
}
return ans;
}