每日一题:与对应负数同时存在的最大正整数(C语言)

题目: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),比上面的暴力枚举确实是优化了不少,主要是在于把负数和正数分开来想比较重要,当然孰能生巧,最终每位同学都能学会这种思想的。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值