资讯专栏INFORMATION COLUMN

记一次优惠券最优使用算法

Lowky / 3014人阅读

摘要:记一次优惠券最优使用算法先说一下业务背景。公司做的一个投资的,投资金额可以用优惠券抵扣。但是无法获取具体使用了哪张优惠券简单就是很难获得优惠券的穷举法数据太多,不可控。但是这种面额的优惠券出现几率几乎没有请教期待有大神给出更好的算法

记一次优惠券最优使用算法

先说一下业务背景。公司做的一个投资的APP,投资金额可以用优惠券抵扣。红包面额(100,50,30,10)

优惠券使用规则:

优先使用大面额的红包,即优先使用张数最少的红包组合

优先使用有限制的红包,即优先使用有限制红包张数占比最大的组合

优先使用即将过期的红包,即优先使用平均有效期最短的组合

选择红包面额之和最大的组合(面额总值≤投资额*1%)

算法尝试

前面三个都可以通过数据库检索排序实现生成一个数组,最后一个就要使用程序算法实现了。
一开始有想过背包法、穷举法。

背包法:说实在的,没看懂(比较尴尬),实现是可以实现。但是无法获取具体使用了哪张优惠券(简单就是很难获得优惠券的Id)

穷举法:数据太多,不可控。

优惠券最优算法1.0

算出用户本次投资最大使用优惠券总额(redAmount)、获取用户的优惠券列表(redCoupons)(已按前三规则排序)直接上代码:

    public function dealCoupon()
    {
        $redCoupons =[]; $restRedAmount = 100;

        $redCouponIdLists = []; $restRedAmounts = [];
        $arrCount = count($redCoupons);
        for ($i=0; $i<$arrCount; $i++) {
            list($redCouponIdList, $restRedAmount) = getBestCoupon($redCoupons, $restRedAmount);
            if ($restRedAmount == 0) {
                $bestCouponIdList = $redCouponIdList;
                break;
            }

            $redCouponIdLists[] = $redCouponIdList;
            $restRedAmounts[] = $restRedAmount;
            array_shift($redCoupons);
        }

        if (empty($bestCouponIdList)) {
            $pos = array_search(min($restRedAmounts), $restRedAmounts);
            $bestCouponIdList = $redCouponIdLists[$pos];
        }

    }

    /**
     * 红包最优算法
     */
    private function getBestCoupon($redCoupons, $restRedAmount)
    {
        $redCouponAmount = 0;
        foreach ($redCoupons as $redCoupon) {
            if ($restRedAmount >= $redCoupon->getAmount()) {
                $redCouponAmount   = $redCouponAmount + $redCoupon->getAmount());
                $redCouponIdList[] = $redCoupon->getCouponId();
                $restRedAmount     = $restRedAmount - $redCoupon->getAmount();

                if ($restRedAmount == 0) break;
            }
        }

        return [$redCouponIdList, $restRedAmount];
    }
实例解析:用户投资9000,用户有优惠券(50,30,30,30,30)

用50块尝试,最多80

用第一个30尝试,最多90,已经最优,中断程序(否则继续向下类推)

问题

因为每次算完就把该红包从数组中推出,这样还是存在问题。例如投资1600,用户有(100,50,30,30)。这样就不会出现最优。

解决(算法2.0)

不把计算过优惠券推出,需要每次把要计算那张优惠券多带带拿出来

这样程序复杂了很多,但还是可以实现的

这样还是会出现算法1.0的问题,不过这种按照顺序取优惠券很难不出现问题。但是这种面额的优惠券出现几率几乎没有

请教

期待有大神给出更好的算法

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/23215.html

相关文章

  • 【FAILED】一次Python后端开发面试的经历

    摘要:正确的思路是等概率随机只取出共个数,每个数出现的概率也是相等的随机输出把一段代码改成,并增加单元测试。代码本身很简单,即使没学过也能看懂,改后的代码如下但是对于单元测试则仅限于听过的地步,需要用到,好像也有别的模块。 在拉勾上投了十几个公司,大部分都被标记为不合适,有两个给了面试机会,其中一个自己觉得肯定不会去的,也就没有去面试,另一个经历了一轮电话面加一轮现场笔试和面试,在此记录一下...

    kohoh_ 评论0 收藏0
  • 一次腾讯霸面---前端

    摘要:客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。地址必须和一个网络掩码对应使用缺一不可。网络掩码的主要作用是告诉计算机如何从地址中析取网络标识和主机标识。 霸面的是前端实习生岗位,当时听同学说前端缺人,还特意设了一个霸面区,就去溜了个弯儿,毕竟不试试,怎么知道自己有多菜呢o( ̄︶ ̄)o一面技术面,面试官关注的点一直在数据结构、算法、计...

    ralap 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<