题目:2441
给你一个 不包含 任何零的整数数组 nums
,找出自身与对应的负数都在数组中存在的最大正整数 k
。
返回正整数 k
,如果不存在这样的整数,返回 -1
。
示例 1:
输入:nums = [-1,2,-3,3] 输出:3 解释:3 是数组中唯一一个满足题目要求的 k 。
什么,没有读懂题目,那么就再读一遍,慢慢去领悟,然后就会发现,还是不明白。
不过问题不大,按照示例一为例,假如我们找到数组元素-1,那么如果还能找到1(-(-1)),也就是-1的相反数,那么满足题意了,而进一步满足最终要求,需要找到最大值,示例一就是-3对应的3了,是不是就明白了。
那么这个时候就有同学会想到,啊没错就是暴力枚举,确实是没毛病就是有点慢,而且这个枚举也不是无脑就能直接枚举,需要进一步思考。
我们可以考虑一下一次for循环来确定要找的负数,例如示例一中我们可以先找-1,然后再来一个for循环去找后面的数有没有和它是相反数,如果找到就记录下来,找不到就再次循环即可,然后每一次第二层for循环结束后我们就比较记录的值哪个是最大的即可,也就是要求的k。
那么话不多说我们来看代码如何实现:
#define MAX(a, b) ((a) > (b) ? (a) : (b))
int findMaxK(int* nums, int numsSize) {
int k = -1;
for (int i = 0; i < numsSize; i++) {
int temp = -1;
for (int j = 0; j < numsSize; j++) {
if (nums[j] == -nums[i]) {
temp = j;
break;
}
}
if (temp != -1) {
k = MAX(k, nums[i]);
}
}
return k;
}
不过这个时候我们也可以分析一下时间复杂度,确实是平方,效率还是太低了,因为我们并不知道正负数会在哪些地方出现,所以效率比较低。
但是呢,如果我们知道正负数会在哪些地方,是不是就能优化了呢,没错可以排序加双指针。
我们可以用C语言典中典库函数qosrt()来进行排序,对于这个排序如何实现,可以看之前我的排序文章或者自行搜索用法,这里就只说一下如何实现。那么排好序后,负数和正数都分配在两边了,这样我们可以用指针j从大到小对数组nums进行遍历,同时用指针i从小到大查找值等于−nums[j] 的元素,然后我们来在小分析一下,因为是升序排序,所以−nums[j]的值会随着j的值变小而增大,所以如果找到了nums[i] == -nums[j],就证明找到最大值,如果找不到就返回-1即可,那么我们来看一下代码是如何实现的:
static int cmp(const void *pa, const void *pb) {
return *(int *)pa - *(int *)pb;
}
int findMaxK(int* nums, int numsSize) {
qsort(nums, numsSize, sizeof(int), cmp);
for (int i = 0, j = numsSize - 1; i < j; j--) {
while (i < j && nums[i] < -nums[j]) {
i++;
}
if (nums[i] == -nums[j]) {
return nums[j];
}
}
return -1;
}
这个时候不难发现,时间复杂度是O(nlogn),比上面的暴力枚举确实是优化了不少,主要是在于把负数和正数分开来想比较重要,当然孰能生巧,最终每位同学都能学会这种思想的。