leetcode 2809.使数组和小于等于x的最少时间

题目

给你两个长度相等下标从 0 开始的整数数组 nums1 和 nums2 。每一秒,对于所有下标 0 <= i < nums1.length ,nums1[i] 的值都增加 nums2[i] 。操作 完成后 ,你可以进行如下操作:

  • 选择任一满足 0 <= i < nums1.length 的下标 i ,并使 nums1[i] = 0 。

同时给你一个整数 x 。

请你返回使 nums1 中所有元素之和 小于等于 x 所需要的 最少 时间,如果无法实现,那么返回 -1 。

示例 1:

输入:nums1 = [1,2,3], nums2 = [1,2,3], x = 4
输出:3
解释:
第 1 秒,我们对 i = 0 进行操作,得到 nums1 = [0,2+2,3+3] = [0,4,6] 。
第 2 秒,我们对 i = 1 进行操作,得到 nums1 = [0+1,0,6+3] = [1,0,9] 。
第 3 秒,我们对 i = 2 进行操作,得到 nums1 = [1+1,0+2,0] = [2,2,0] 。
现在 nums1 的和为 4 。不存在更少次数的操作,所以我们返回 3 。

示例 2:

输入:nums1 = [1,2,3], nums2 = [3,3,3], x = 4
输出:-1
解释:不管如何操作,nums1 的和总是会超过 x 。

提示:

  • 1 <= nums1.length <= 103
  • 1 <= nums1[i] <= 103
  • 0 <= nums2[i] <= 103
  • nums1.length == nums2.length
  • 0 <= x <= 106

思路

这每日一题有点难啊,不愧是困难难度,优化了好久也才959/1272,求大佬教教为啥

AA宏注释掉就是提交到leetcode的,AA不注释就是本地调试的,有兴趣的可以自己调试下。

首先明确一点,虽然题目说是可以清零,但是这个题目是小于等于而不是等于x,所以不会出现不清零的情况,所以直接清零就好了。

先写个结构体存n1/n2,这个比率我愿称之为n1的阳寿比,这个比率越大,在某些情况下,说明这个n1的阳寿太长了,得赶紧砍掉,这样就可以保证整个数组成长曲线是最低的,在数字特别大的情况下,这个比率可以优先删除大的数字。

之所以写了两个while,是因为在某些情况下,无脑删除整个数组最大的数有可能会比砍阳寿更快,因为有些初始值大且增长值也较大的,在增长起来之前,初始值清楚就可以达到sum<x的目的,因此得做一遍检查。

代码

#include <stdio.h>
#include <limits.h>
#define AA
#ifdef AA
#define print printf
#else
#define print
#endif

typedef struct Node {
    int n1;
    int n2;
    double n1Divn2; // 用于存储 n1 与 n2 的除法结果
}Node_t;

int cntSum(Node_t* num, int size){
    int sum = 0;
    for (int i = 0; i < size; i++){
        sum += num[i].n1;
    }
    return sum;
}

void frashRatio(Node_t* nums, int size)
{
    for (int i = 0; i < size; i++){
        nums[i].n1Divn2 = nums[i].n2 != 0 ? (double)(nums[i].n1) / nums[i].n2 : 0;
    }
}



Node_t* searchMaxRatioNode(Node_t* nums, int size)
{
    Node_t* maxRatioNode = &nums[0];
    for (int i = 1; i < size; i++){
        if (nums[i].n1Divn2 > maxRatioNode->n1Divn2)
        {
            maxRatioNode = &nums[i];
        }
        else if((nums[i].n1Divn2 == maxRatioNode->n1Divn2) && (nums[i].n1 <= maxRatioNode->n1))
        {
            maxRatioNode = &nums[i];
        }
    }
    return maxRatioNode;
}

int minimumTime(int* nums1, int nums1Size, int* nums2, int nums2Size, int x) {
    int time = 0;
    int totalNum = 0;
    int size = nums1Size;
    Node_t nums[size]; // 初始化节点数组
    unsigned int tmp_time = 0;

    // 初始化节点数组
    for (int i = 0; i < size; i++) 
    {
        nums[i].n1 = nums1[i];
        nums[i].n2 = nums2[i];
        nums[i].n1Divn2 = (nums2[i] != 0) ? ((double)nums1[i] / nums2[i]) : 0;
    }

    int sum = cntSum(nums, size);
    print("sum = %d\n", sum);
    if (sum <= x) 
        return 0; // 检查初始条件

    while (sum > x) {
        for (int i = 0; i < size; i++) {
            nums[i].n1 += nums[i].n2; // 增加 n2 值
            print("%d ", nums[i].n1);
        }
        frashRatio(nums,size);
        Node_t* maxRatioNode = searchMaxRatioNode(nums, size);
        time++; // 增加时间
        sum = cntSum(nums, size); // 重新计算总和
        print("sum = %d\n", sum);
        for (int i = 0; i < size; i++)
        {
            if((sum - nums[i].n1) <= x)
            {
                goto tag;
            }
        }
        print("clear num[%d].n val = %d\n\n",(maxRatioNode - nums), maxRatioNode->n1);
        maxRatioNode->n1 = 0; // 将选中的节点的 n1 值归零
        // sleep(1);
        if(time > 1000)
        {
            time = -1;
            break;
        }
    }
tag:
    print("opt2\n");
    for (int i = 0; i < size; i++) 
    {
        nums[i].n1 = nums1[i];
        nums[i].n2 = nums2[i];
        nums[i].n1Divn2 = (nums2[i] != 0) ? ((double)nums1[i] / nums2[i]) : 0;
    }
    while (tmp_time < 100) 
    {
        for (int i = 0; i < size; i++) {
            nums[i].n1 += nums[i].n2; // 增加 n2 值
            print("%d ", nums[i].n1);
        }
        tmp_time++; // 增加时间
        sum = cntSum(nums, size); // 重新计算总和
        print("sum = %d\n", sum);
        Node_t *maxnode = &nums[0];
        for (int i = 1; i < size; i++)
        {
            if(maxnode->n1 < nums[i].n1)
            {
                maxnode = &nums[i];
            }
        }
        if((sum - maxnode->n1) <= x)
        {
            break;
        }
        print("clear num[%d].n val = %d\n\n",(maxnode - nums), maxnode->n1);
        maxnode->n1 = 0;
    }
    print("time = %d, tmp_time = %d\n",time, tmp_time);
    if(time == -1 && tmp_time < 999)
    {
        return tmp_time;
    }
    else if(time == -1)
    return time;
    return time < tmp_time ? time : tmp_time;
}
#ifdef AA
int main(void)
{
    int a[] = {1,7,9,4,8,8,1};
    int b[] = {2,2,3,2,0,1,0};
    int size =  sizeof(a)/ sizeof(int);
    int ret = minimumTime(a,size,b,size,20);
    printf("\nret = %d\n",ret);
}
#endif

结果

  • 16
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值