前言
刷题坚持每一天,以下题目引用自:力扣(LeetCode)
💎一、题目一
🏆1.题目描述
原题链接:1838. 最高频元素的频数
元素的 频数 是该元素在一个数组中出现的次数。
给你一个整数数组 nums 和一个整数 k 。在一步操作中,你可以选择 nums 的一个下标,并将该下标对应元素的值增加 1 。
执行最多 k 次操作后,返回数组中最高频元素的 最大可能频数 。
示例 1:
输入:nums = [1,2,4], k = 5
输出:3
解释:对第一个元素执行 3 次递增操作,对第二个元素执 2 次递增操作,此时 nums = [4,4,4] 。
4 是数组中最高频元素,频数是 3 。
🏆2.解题思路
🔑思路:
先排序,对于第一个值大于或等于后面的值(值加k)进行计数,不满足条件退出当前循环。比较是否比前一次频率大,保存大值。
🏆3.代码详解
int cmp(const void* q1, const void* q2){
return *(int*)q2 - *(int*)q1;
}
int maxFrequency(int* nums, int numsSize, int k){
qsort(nums, numsSize, sizeof(int), cmp);
int i, j;
int count = 1;
int ans = 0;
for(i = 0; i < numsSize; ++i){
if(i > 0 && nums[i] == nums[i-1]) continue;
int ret = k;
for(j = i+1; j < numsSize; ++j){
if(ret >= nums[i]-nums[j]){
ret -= nums[i]-nums[j];
++count;
}
else break;
}
ans = ans > count ? ans : count;
count = 1;
}
return ans;
}
💎二、题目二
🏆1.题目描述
原题链接:1590. 使数组和能被 P 整除
给你一个正整数数组 nums,请你移除 最短 子数组(可以为 空),使得剩余元素的 和 能被 p 整除。 不允许 将整个数组都移除。
请你返回你需要移除的最短子数组的长度,如果无法满足题目要求,返回 -1 。
子数组 定义为原数组中连续的一组元素。
示例 1:
输入:nums = [3,1,4,2], p = 6
输出:1
解释:nums 中元素和为 10,不能被 p 整除。我们可以移除子数组 [4] ,剩余元素的和为 6 。
🏆2.解题思路
🔑思路:
第一版本暴力求解超时。第二版本C++,哈希+前缀 ,用哈希建做索引存储余数,值存数组索引。当一个连续子数组的余数在hash里出现过时,就用当前索引值减hash里的值,就是去除连续子数组的长度。接着判断取最小的就可以。
🏆3.代码详解
/*超时版本,
超时版本,
超时版本*/
int minSubarray(int* nums, int numsSize, int p){
long long ret = 0;
for(int i = 0; i < numsSize; ++i){
ret += nums[i];
}
if(ret % p == 0) return 0;
long long sum = 0;
int min = 1000000001;
int count = 0;
for(int i = 0; i < numsSize; ++i){
count = 0;
sum = 0;
for(int j = i; j < numsSize; ++j){
sum += nums[j];
++count;
if((ret - sum) != 0 && (ret - sum) % p == 0)
min = min > count ? count : min;
}
}
return min == 1000000001 ? -1 : min;
}
class Solution {
public:
int minSubarray(vector<int>& nums, int p) {
int len = nums.size();
long long ret = 0;
long long sum = 0;
int ans = 1000000001;
unordered_map<int, int> hash;
hash[0] = 0;
for(int i = 0; i < len; ++i) ret += nums[i]%p;
ret %= p;
if(ret % p == 0) return 0;
printf("%d\n", ret);
for (int i = 1; i <= len; ++i) {
sum += nums[i-1]%p;
int x = (sum - ret + p) % p;
if (hash.count(x)){
ans = min(ans, i-hash[x]);
printf("%d,%d\n",i,ans);
}
hash[sum%p] = i;
}
if (ans == len) return -1;
return ans;
}
};
💎三、题目三
🏆1.题目描述
原题链接:1589. 所有排列中的最大和
有一个整数数组 nums ,和一个查询数组 requests ,其中 requests[i] = [starti, endi] 。第 i 个查询求 nums[starti] + nums[starti + 1] + … + nums[endi - 1] + nums[endi] 的结果 ,starti 和 endi 数组索引都是 从 0 开始 的。
你可以任意排列 nums 中的数字,请你返回所有查询结果之和的最大值。
由于答案可能会很大,请你将它对 109 + 7 取余 后返回。
示例 1:
输入:nums = [1,2,3,4,5], requests = [[1,3],[0,1]]
输出:19
解释:一个可行的 nums 排列为 [2,1,3,4,5],并有如下结果:
requests[0] -> nums[1] + nums[2] + nums[3] = 1 + 3 + 4 = 8
requests[1] -> nums[0] + nums[1] = 2 + 1 = 3
总和为:8 + 3 = 11。
一个总和更大的排列为 [3,5,4,2,1],并有如下结果:
requests[0] -> nums[1] + nums[2] + nums[3] = 5 + 4 + 2 = 11
requests[1] -> nums[0] + nums[1] = 3 + 5 = 8
总和为: 11 + 8 = 19,这个方案是所有排列中查询之和最大的结果。
🏆2.解题思路
🔑思路:
链接:什么是差分数组
用差分数组记录区间里值出现的次数,前缀和还原。利用排序把最大的值与出现次数最多的相乘依次循环。求出最大值。
🏆3.代码详解
#define mod 1000000007
int cmp(const void*q1, const void*q2){
return *(int*)q1 - *(int*)q2;
}
int maxSumRangeQuery(int* nums, int numsSize, int** requests, int requestsSize, int* requestsColSize){
int* diff = (int*)malloc(sizeof(int)*numsSize);
long long ans = 0;
memset(diff, 0, sizeof(int)*numsSize);
for(int i = 0; i < requestsSize; ++i){
diff[requests[i][0]]++;
if(requests[i][1]+1 < numsSize){
diff[requests[i][1]+1]--;
}
}
for(int i = 1; i < numsSize; ++i){
diff[i] += diff[i-1];
}
qsort(diff, numsSize, sizeof(int), cmp);
qsort(nums, numsSize, sizeof(int), cmp);
for(int i = 0; i < numsSize; ++i){
ans += ((long long)nums[i] * diff[i]) % mod;
}
return ans%mod;
}
💎四、星球推荐
星球链接:英雄算法联盟
星球里有什么?
【朋友圈】一个极致精准的自律、编程、算法的小圈子。
【算法集训】以月为单位组织算法集训,每天四题,风雨无阻。
【排行榜】每天、每周都会有榜单,激励大家不断进步,不断成长。
【个人规划】每个人都写好自己的规划,也可以查看他人的规划,时刻警醒自己不掉队。
【打卡挑战】每日一题打卡、每日早起打卡、算法集训打卡、规划完成情况打卡。
在星球里做什么?
目前星球人数达到360+,在星球里你能够遇到一群志同道合之人,因为都是花钱进来的,你不会看到任何浑水摸鱼的人,每个人都有自己的每月规划,星主每月都会组织算法集训,每天一起刷题,你可以看到别人的解题报告,取其之长,补己之短。