代码随想录——贪心9.K次取反后最大化的数组和 && std::sort函数的第三个参数说明
思路
第一想法是排序后先把负数取反消耗k,但是这样有个问题:k还剩余,并且所有元素都为正数的时候,不好找最小值去消耗k
故采用绝对值逆序排序,这样就算全是正数了,它也是单调递减的,最小值就是size()-1位置的元素
static bool cmp(int a,int b){
return abs(a) > abs(b);
}
int largestSumAfterKNegations(vector<int>& nums, int k) {
//第一想法是排序后先把负数取反消耗k,但是这样有个问题:k还剩余,并且所有元素都为正数的时候,不好找最小值去消耗k
//故采用绝对值逆序排序,这样就算全是正数了,它也是单调递减的,最小值就是size()-1位置的元素
sort(nums.begin(),nums.end(),cmp);
int sum = 0;
for(int i=0;i<nums.size();i++){
if(nums[i] < 0 && k > 0){
nums[i] = -nums[i];
k--;
}
}
//k如果大于0——偶数不管,奇数让绝对值最小的取反
if(k % 2 != 0)nums[nums.size()-1] *= -1;
for(int a:nums)sum += a;
return sum;
}
sort函数的第三个参数
如果cmp函数不是static会编译报错:
原因分析
- 成员函数的调用需要对象
默认情况下,class 中的普通成员函数(非 static)隐式地绑定到某个对象实例(this 指针)。也就是说,成员函数在调用时必须通过类的对象来调用,例如:
Solution sol;
sol.cmp(a, b);
- std::sort 的要求
std::sort 接受一个可调用对象(如函数指针或函数对象)作为第三个参数,用于比较两个元素的大小关系。这个比较函数必须是普通的函数,或者是一个 static 函数,因为:
- 普通的成员函数需要一个对象实例(this 指针)才能调用,而 std::sort 只是调用比较函数来比较两个值,它不知道也不管理 this 指针。
- 静态成员函数 (static) 不依赖 this 指针,可以直接通过类名调用,不需要绑定到具体对象上。
如果 cmp 不是 static 的,编译器会报错,因为 std::sort 无法将你的非静态成员函数作为比较函数使用。
- static 的作用
static 修饰的成员函数是属于类本身的,而不是某个对象实例的。这意味着:
- 它不需要依赖对象实例(this 指针)。
- 可以像普通函数一样直接使用。
- 适合像这里这种情况,作为回调函数传递给 std::sort。
解决方案
保持 static 你的代码正确地将 cmp 定义为 static,这是最简单和直接的解决方式:
static bool cmp(int a, int b) {
return abs(a) > abs(b);
}
使用外部普通函数 如果你不想使用 static,可以将 cmp 定义为类外的普通函数:
bool cmp(int a, int b) {
return abs(a) > abs(b);
}
class Solution {
public:
int largestSumAfterKNegations(vector<int>& nums, int k) {
sort(nums.begin(), nums.end(), cmp);
// ... your logic ...
}
};
使用 lambda 表达式 如果不需要重复使用 cmp,可以直接在调用 std::sort 时使用 lambda 表达式:
sort(nums.begin(), nums.end(), [](int a, int b) {
return abs(a) > abs(b);
});
总结
你在这里需要 static 的原因是普通成员函数依赖对象实例,而 std::sort 无法处理这种依赖。如果不想使用 static,可以考虑用普通函数或 lambda 表达式来代替。