-
思路:
1.每个数都可以经过一次修改(注意:不是加一或者减一),所以每个数最多只需要修改一次。
2.所有下标为奇数的数需要改成一样的;所有下标为偶数的数也需要改成一样的。
3.所以,我们只需要统计所有下标为奇数的数里面频率最高的找出来,然后把其它数改成和它一样;下标为偶数的也同样处理。
4.最后统计两者之和。
5.统计一堆数里面频率最高的数,可以用哈希表实现。
6.但是,相邻的数又不能相等,所以当找出来的奇数和偶数下标对应的频率出现最高的数是相等的情况,我们需要让 奇数下标 的数选择次大的数,或者让偶数下标的数选择次大的数。 -
程序
class Solution { public: int min(int a, int b) { return a < b ? a : b; } int minimumOperations(vector<int>& nums) { int len = nums.size(); int hash[2][100005]; int result = 0; int maxIdx[2]; int secMax[2]; int cnt[2]; memset(hash,0,sizeof(hash)); for(int i = 0; i < len; ++i){ ++hash[i&1][nums[i]];//下标为奇数的放入hash[1],下标为偶数的放入hash[0]; } for(int i = 0; i<2; ++i){ maxIdx[i] = -1; secMax[i] = -1; cnt[i] = 0; //因为1 <= nums[i] <= 10^5 所以j从1到100000 for(int j = 1; j<100001; ++j){ if(maxIdx[i] == -1 || hash[i][j] > hash[i][maxIdx[i]]){ secMax[i] = maxIdx[i]; maxIdx[i] = j; }else if(secMax[i] == -1 || hash[i][j] > hash[i][secMax[i]]){ secMax[i] = j; } cnt[i] += hash[i][j];// (奇)偶数下标的总个数 } } int even[2] = {maxIdx[0],secMax[0]}; int odd[2] = {maxIdx[1],secMax[1]}; result = 100000; for(int i = 0;i<2;++i){ for(int j = 0;j<2;++j){ if(even[i] != odd[j]){ result = min(result,cnt[0]-hash[0][even[i]]+cnt[1]-hash[1][odd[j]]); //为啥不能这样呢? //result = cnt[0]-hash[0][even[i]] + cnt[1]-hash[1][odd[j]]; } } } return result; } };
回答程序中的问题:
因为当奇数和偶数下标对应的频率出现最高的数是相等的情况下,需要让奇数下标的数选择次多的数,或者让偶数下标的数选择次多的数。但是不知道奇数下标的数选择最多的数和偶数下标的数选择次多的数的组合与奇数下标的数选择次多的数和偶数下标的数选择最多的数的组合那种情况操作数最小所以取最小值。
- 总结学习
- 哈希表:又学到了一种哈希表的使用场景和使用技巧。
- 通过i&1表示奇偶数 结果为0 偶数;结果为1 奇数;
for(int i = 0; i < len; ++i){
++hash[i&1][nums[i]];//下标为奇数的放入hash[1],下标为偶数的放入hash[0];
}