懈怠了,但周五满课,然后周六又有军事理论考试还有篮球比赛,只在昨天又复习了一遍贪心算法/(ㄒoㄒ)/~
简单理解
- 对所给数组进行排序(升序或者降序),然后通过题目取得最大(最小)和次大(次小 的两个书相乘(相加)得到最优解。
题目
1.最大乘积差
两个数对 (a, b) 和 (c, d) 之间的 乘积差 定义为 (a * b) - (c * d) 。
给你一个整数数组 nums ,选出四个 不同的 下标 w、x、y 和 z ,使数对 (nums[w], nums[x]) 和 (nums[y], nums[z]) 之间的 乘积差 取到 最大值 。
实现代码:
int cmp(int *a, int *b){
return *(int *)a - *(int *)b;
}
int maxProductDifference(int* nums, int numsSize){
qsort(nums,numsSize,sizeof(int),cmp);
return nums[numsSize-1]*nums[numsSize-2]-nums[0]*nums[1];
}
- 这道题结合了排序和贪心的思想,通过qsort排序得到有序数组,再根据题目要求运用贪心的思想求出最大乘积差。
2.三角形的最大周长
题目描述:给定由一些正数(代表长度)组成的数组 nums ,返回 由其中三个长度组成的、面积不为零的三角形的最大周长 。如果不能形成任何面积不为零的三角形,返回 0。
实现代码:
int cmp(int*a,int*b){
return *(int*)a-*(int*)b;
}
int largestPerimeter(int* nums, int numsSize){
qsort(nums,numsSize,sizeof(int),cmp);
for(int i=numsSize-1;i>1;--i){
if(nums[i-2]+nums[i-1]>nums[i]){
return nums[i-2]+nums[i-1]+nums[i];
}
}
return 0;
}
- 运用三角形两边之和大于第三边来判断三角形是否符合要求;
3.数组拆分
给定长度为 2n 的整数数组 nums ,你的任务是将这些数分成 n 对, 例如 (a1, b1), (a2, b2), …, (an, bn) ,使得从 1 到 n 的 min(ai, bi) 总和最大。
实现代码:
int cmp(int*a,int*b){
return *(int*)a-*(int*)b;
}
int arrayPairSum(int* nums, int numsSize){
qsort(nums,numsSize,sizeof(int),cmp);
int ans=0;
for(int i = 0;i<numsSize;i+=2){
ans+=nums[i];
}
return ans;
}
- 注意,通过排序直接取奇数数列(数对中的min),即可得到最大总和;
4.救生艇
给定数组 people 。people[i]表示第 i 个人的体重 ,船的数量不限,每艘船可以承载的最大重量为 limit。
每艘船最多可同时载两人,但条件是这些人的重量之和最多为 limit。
返回 承载所有人所需的最小船数
实现代码:
int cmp(int*a,int*b){
return *(int*)a-*(int*)b;
}
int numRescueBoats(int* people, int peopleSize, int limit){
qsort(people,peopleSize,sizeof(int),cmp);
int ans=0;
int i,k=0;
for(i=peopleSize-1;k<=i;){
ans++;
if(people[i]+people[k]<=limit){
i--;
k++;
}
else{
--i;
}
}
return ans;
}
- 两个边界(k和i)随着判断结束移动;
5.摆动排序Ⅱ
给你一个整数数组 nums,将它重新排列成 nums[0] < nums[1] > nums[2] < nums[3]… 的顺序。
你可以假设所有输入数组都可以得到满足题目要求的结果。
实现代码:
int cmp(int *a, int *b){
return *(int *)a - *(int *)b;
}
void wiggleSort(int* nums, int numsSize){
int *ret = (int*)malloc(sizeof(int)*numsSize);
for(int i=0;i<numsSize;i++){
ret[i]=nums[i];
}
qsort(ret,numsSize,sizeof(int),cmp);
int returnSize=numsSize-1;
for(int i=1;i<numsSize;i+=2){
nums[i]=ret[returnSize--];
}
for(int i=0;i<numsSize;i+=2){
nums[i]=ret[returnSize--];
}
return nums;
}
- 实现摆动的方法是先创建一个数组,并对其排序,然后根据题目先把大的数插入偶数列,再依次插入奇数列
6.分发饼干
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。
对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。
实现代码:
int cmp(int*a,int*b){
return *(int*)a-*(int*)b;
}
int findContentChildren(int* g, int gSize, int* s, int sSize){
qsort(g,gSize,sizeof(int),cmp);
qsort(s,sSize,sizeof(int),cmp);
int j=sSize-1,ans=0;
for(int i=gSize-1;i>=0&&j>=0;i--){ // i>=0&&j>=0,不要忘记=
if(g[i]>s[j]){
continue;
}
else{
j--;
ans++;
}
}
return ans;
}
- 注意不要越界
7.最小操作使数组递增
给你一个整数数组 nums (下标从 0 开始)。每一次操作中,你可以选择数组中一个元素,并将它增加 1 。
比方说,如果 nums = [1,2,3] ,你可以选择增加 nums[1] 得到 nums = [1,3,3] 。
请你返回使 nums 严格递增 的 最少 操作次数。
我们称数组 nums 是 严格递增的 ,当它满足对于所有的 0 <= i < nums.length - 1 都有 nums[i] < nums[i+1] 。一个长度为 1 的数组是严格递增的一种特殊情况
实现代码:
int minOperations(int* nums, int numsSize){
int pre = nums[0]+1;
int ans=0;
for(int i=1;i<numsSize;i++){
if(pre < nums[i]){
pre = nums[i]+1;
}
else{
ans += pre - nums[i];
pre++;
}
}
return ans;
}
注意题目要求每一次操作增加1。
8.最小操作数使数组递增
给你一个整数数组 nums (下标从 0 开始)。每一次操作中,你可以选择数组中一个元素,并将它增加 1 。
比方说,如果 nums = [1,2,3] ,你可以选择增加 nums[1] 得到 nums = [1,3,3] 。
请你返回使 nums 严格递增 的 最少 操作次数。
我们称数组 nums 是 严格递增的 ,当它满足对于所有的 0 <= i < nums.length - 1 都有 nums[i] < nums[i+1] 。一个长度为 1 的数组是严格递增的一种特殊情况。
实现代码:
int cmp(int*a,int*b){
return *(int*)a-*(int*)b;
}
int minIncrementForUnique(int* nums, int numsSize){
int ans=0;
qsort(nums,numsSize,sizeof(int),cmp);
for(int i=1;i<numsSize;i++){
if(nums[i]<=nums[i-1]){
int diff = nums[i-1] - nums[i] + 1;
nums[i]+=diff;
ans+=diff;
}
}
return ans;
}
- 通过找到diff并让当前数+=diff,可以把之前的操作数+1体现在后面的数上,不会造成前面的数+1后,后面的数通过+1变小;
9.有效三角形的个数
给定一个包含非负整数的数组 nums ,返回其中可以组成三角形三条边的三元组个数。
实现代码;
int cmp(int*a,int*b){
return *(int*)a-*(int*)b;
}
int triangleNumber(int* nums, int numsSize){
qsort(nums,numsSize,sizeof(int),cmp);
int ans=0,j,k;
for(int i =0;i<numsSize;i++){
j=i+1;
k=j+1;
while(j<numsSize){
while(k<numsSize){
if(nums[i]+nums[j]<=nums[k]){
break;
}
k++;
}
ans += k-j-1; //k和j本身应当相差1;
j++;
if(j==k)k++;
}
}
return ans;
}
- 排序后利用i,j,k三层循环判断满足三角形的个数
总结
这一块好多题,不太会的题型是——最小操作递增,有效三角形个数。