算法期中1000. 分组

Description
对于一个整数数列A[0], A[1], …, A[N-1]进行分组,要求每组1到2个数,并且同组之和不能大于w. 求最少可以分成多少组.

1 <= N <= 100000, 1 <= A[i] <= w <= 1000000000.

请实现下面Solution类中计算minPartition(A, w)的函数.

class Solution {
public:
       int minPartition(vector<int> A, int w) {

       }
};

例1:当A = {2, 5, 4, 3}, w = 5, minPartition(A, w)返回3. 将2和3放一组,4和5各自单独作为一组,共3组.

例2:当A = {2, 5, 4, 3}, w = 7, minPartition(A, w)返回2. 将2和5放一组,3和4一组,共2组.

注意:你只需要提交Solution类的代码,你在本地可以编写main函数测试程序,但不需要提交main函数的代码. 注意不要修改类和函数的名称.

解析:
当时没想出来,一直想啥动态规划。之后和室友交流下,其实思路很简单。自己居然把排序等一般的方法都忘了,思维太局限了。leetcode要认真打了啊。。。
把A从小至大排序。找到能和最小的数字匹配的最大的数字的下标,这些数字一一配对,处理一下,即可得最大的对数。然鹅我的思路还是WA,参考了别人的代码才发现自己的疏漏。第一个函数是我的错误代码,第二个是正确的。
正确思路举例:w = 8,序列为2 4 5 6 7
先把数组从小到大排序,尽可能多划分组,就要求小的和尽量大的一组。
head指针从头取剩余最小的,tail指针从尾部找能和head相加后小于w的最大值。tail每轮循环都要向向前移动一位,即tail–,同时res++,因为tail所指向的数字必须单独列为一组。如果tail所值的数字和head所指的数字相加满足要求,则head++,tail–,res++(因为得到一组)。最终假设还剩下两个数,head指向第一个,tail指向第二个数。① 二者相加符合条件,则head++,tail–并且res++。不满足head < tail,结束。②二者相加不符合条件,则tail–,res++,进入下一轮循环此时head == tail,不符合head < tail,所以结束。但是head 和tail所指的数字仍自成一组,故res++。
代码:

class Solution {
public:
    /*这个方法一直令head = 0
     *是错误的,如2 4 5 6 7, w = 8,
     *当tail到6的时候,2 + 6 <= 8没错
     *但是4 + 5 = 9,中间的就不一定符合要求
     */
    int minPartitionWrong(vector<int> A, int w) {  
        sort(A.begin(), A.end());  // 从小至大排序
        int pairsNum = 0;
        int doublePairsNum;
        int size = A.size();
        for (doublePairsNum = size - 1; doublePairsNum >= 0; doublePairsNum--) {
            int sum = A[doublePairsNum] + A[0]; // 找到符合条件的最大的数下标
            if (sum <= w) break;
        }
        pairsNum = (doublePairsNum + 1) / 2;
        return size - pairsNum;
    }

正确的解答:

    int minPartition(vector<int> A, int w) {
        sort(A.begin(), A.end());  // 从小至大排序
        int tail, head = 0, res = 0;
        int size = A.size();
        for (tail = size - 1; tail >= 0 && head < tail; tail--) {
            if (A[tail] + A[head] <= w) {
                head++;
            }
            res++;
        }
        if (tail == head)
            res++;
        return res;
    }
};                                 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值