剁手党必看——转转红包使用规则与最优组合计算全解析

  • 1、省钱攻略基础之“了解平台红包使用规则”

  • 2、举个栗子

  • 3、最优红包组合计算方法进化过程

    • 3.1、初代“笛卡尔乘积”版

    • 3.2、二代“边算边比较Map聚合”版

    • 3.3、三代“边算边比较数组索引定位”版

  • 4、总结

1、省钱攻略基础之“了解平台红包使用规则”

规则一:红包大类别分为“商品红包”、“叠加券”、“邮费红包”三种。

规则二:每个SKU(同一个商品ID),商品红包、叠加券、邮费红包最多每种使用一张。

规则三:商品红包和叠加券都有可能设定使用门槛金额,门槛金额是商品促销优惠后金额(如果有促销),邮费红包使用门槛基于商品红包和叠加券优惠后金额计算。

规则四:门槛金额高的红包优惠不一定高于门槛低的(虽然大概率如此)。

规则五:绝大多数红包都有使用限制条件,与商品相关的:分类、归属的业务、卖家、包含的服务、特定的商品范围、商品发布时间;与场景相关:终端类型、卖场;与买卖家相关:是否是“新客户”、买卖家是否被风控等等。

规则六:商品红包和叠加券小类分为:满额减和满额折,其中满额折红包又有最大优惠金额如满10元8.8折最多优惠1000元,此时如果商品10000元最多也只能减1000元;邮费红包分为定额红包和免邮红包。

2、举个栗子

在开始计算最大优惠前,我们先举个例子具象化实际场景,此处忽略“规则五”计算过程,直接给出符合红包使用限制的商品与红包关系;由于邮费红包门槛金额基于商品红包和叠加券后金额较为复杂,且不影响最优红包解题思路,此处忽略邮费红包,仅以商品红包为例。

场景如下:

5个商品分别为:P1=10元、P2=20元、P3=30元、P4=40元、P5=50元。

5个商品红包:R1=满10元减5元、R2=满20元减12元、R3=满30元减10元、R4=满90元减60元、R5=满100元减80元。商品与红包的关系如下表格:

3、最优红包组合计算方法进化过程

3.1、初代“笛卡尔乘积”版

首先,将每个红包的可用商品聚合:

R1->P2、P3、P4、P5 R2->P1、P3、P4、P5 R3->P1、P2、P4、P5 R4->P1、P2、P3、P5 R5->P1、P2、P3、P4

将每个红包的可用商品进行排列组合得到下表(黄色为该组合不符合红包门槛):

将上表改写成矩阵:

计算纵列笛卡尔积:

计算各组合红包的优惠情况,按红包优惠金额倒序,取红包最大优惠组合情况, 得到:P5商品使用R2;P1P2P3P4使用R5,得到最大优惠金额80+12=92元。

该版本核心思想:计算出所有商品使用红包的组合情况,并行计算各组合的优惠金额,按优惠金额倒序取最大优惠。存在的问题:商品和红包数量增加时组合数呈指数级增长,计算笛卡尔积时很容易OOM。

3.2、二代“边算边比较Map聚合”版

一代算法最大的问题是将所有组合全部排列好后再进行价格计算和比较,导致内存占用过大;二代算法核心思想是“边排列组合边计算边比较”保留最优解,计算耗时到达规定阈值时停止,取已算组合中的最优。这一代算法中,用到了HashMap作为记录商品使用红包的标记指针,数据结构如下:

//用于记录每个商品上,各大类可用红包的列表
private Map<ERedMetaBigType, List<RedBaseInfoInput>> prodRed = Maps.newHashMap();//用于记录该商品在各大类红包列表List<RedBaseInfoInput>上使用红包的列表index位置private Map<ERedMetaBigType, Integer> pointer = Maps.newHashMap();

指针移动抽象示例(黄色为此轮组合指针位置):

移动一次指针就形成一个新的组合,根据根据标记将使用相同红包的商品“聚合” 如组合2:R5<P1,P2,P3,P4> R3

//使用Map结构记录
Map<ERedMetaBigType, Map<Long, List<EngineInput>>> oneType2RedId2Prods = Maps.newEnumMap(ERedMetaBigType.class);

优点:不需要将所有组合都排列出后再计算比较,超过规定时间可以中断降级处理。缺点:每次移动指针后,都需要使用Map结构将红包商品重新“聚合”后才能计算红包门槛和优惠,频繁生产销毁Map和List对象,GC压力大。

3.3、三代“边算边比较数组索引定位”版

三代主要通过数据结构与虚拟逻辑关系,减少上一代算法大量生成中间临时Map导致GC压力大问题。使用数组Long[] infoArray存储商品列表,此时infoArray数组下标就含有了商品ID的含义,同理,Long[] redArray存储红包列表,redArray数组下标就含有了红包ID的含义。使用byte[][] infoRedRel二维数组用于存储商品红包关系,数组值0表示此轮计算未使用,1表示此轮计算使用,-1表示该商品不可使用此红包。关系数组如下:

拥有这个二维数组后,就可以通过修改这个位数数组的值(不包含-1不可用的),实现红包使用组合的变更。

此时聚合商品不再需要使用Map生成新的结构存储,只需要遍历红包列表数组,根据数组下标去infoRedRel维数组中获取数组值,然后去infoArray取商品即可。

4、总结

本文简述了最优红包组合的整体演进,下表是二代和三代在不同红包总量、商品数量、商品可用红包数量时,200ms完成计算组合数的情况对比(30次均值)如下图:

通过二代三代的对比,我们不难发现,在面对大量计算时除了要注意JVM内存使用情况外(一代FullGC或溢出),还需要关注对象生成销毁的数量与频率,因为在面临大量计算时对象生成和GC也将成为性能瓶颈,三代相较二代,完成计算的组合数在5倍以上,这其间的差距都是因为二代Map对象的生成和销毁。


关于作者

马宝山,  转转交易中台Java开发工程师

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/8462.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

介绍 ffmpeg.dll 文件以及ffmpeg.dll丢失怎么办的五种修复方法

ffmpeg.dll 是一个动态链接库文件&#xff0c;属于 FFmpeg运行库。它在计算机上扮演着非常重要的角色&#xff0c;因为它提供了许多应用程序和操作系统所需的功能和组件。当 ffmpeg.dll 文件丢失或损坏时&#xff0c;可能会导致程序无法正常运行&#xff0c;甚至系统崩溃。下面…

数据结构-线性表-链表-2.3-4

试编写在带头结点的单链表L中删除一个最小值结点的高效算法&#xff08;假设最小值结点是唯一的&#xff09;。 使用四个指针&#xff0c;p,pre,minp,minpre 用p从头至尾扫描单链表&#xff0c;pre指向*p结点的前驱&#xff0c;用minp保存最小结点的指针&#xff08;初始认为…

C#读sqlite数据库

using System.Data.SQLite;//若没有库需要在Nugut下载 private void ReadDatabase() { //判断有无数据库 if (!File.Exists(dbPath)) { SQLiteConnection.CreateFile(dbPath); MessageBox.Show(…

紫外激光打标机适合在哪些材料表面进行标记

紫外激光打标机适合在多种材料表面进行标记&#xff0c;特别是那些对热敏感或者需要高精度、高清晰度标记的材料。以下是一些常见的适用材料&#xff1a; 1. 塑料&#xff1a;紫外激光打标机在塑料材料上表现尤为出色&#xff0c;因为紫外激光的短波长和高能量密度使得它能够在…

Python | Leetcode Python题解之第70题爬楼梯

题目&#xff1a; 题解&#xff1a; class Solution:def climbStairs(self, n: int) -> int:a, b 1, 1for _ in range(n - 1):a, b b, a breturn b

TCP长连接短链接

1、短连接 短连接是指通讯双方有数据交互时&#xff0c;就建立一个连接&#xff0c;数据发送完成后&#xff0c;则断开此连接&#xff0c;即每次连接只完成一项业务的发送。 2、长连接 长连接是指在一个连接上可以连续发送多个数据包&#xff0c;在连接保持期间&#xff0c;…

Nginx启动后IP加端口不能正常访问

背景介绍 新增NGINX配置文件后&#xff0c;重启nginx无法使用IP端口访问服务&#xff0c;域名可以访问服务。NGINX启动不报错&#xff0c;测试nginx配置文件nginx -t也没问题。 定位问题思路与步骤 查看NGINX配置文件 发现NGINX配置文件中的user是www user www www;查看N…

Linux中通过命令执行Shell脚本不生效问题

Linux中通过命令执行Shell脚本不生效问题 文章目录 Linux中通过命令执行Shell脚本不生效问题1. 执行.sh设置export不生效问题2. 可能导致的原因3. 解决方法1. 通过点(.)来执行shell脚本2. 通过source来执行shell脚本 1. 执行.sh设置export不生效问题 执行命令./script.sh后发现…

深度学习实战77-基于CNN+BiLSTM的异常用电行为的识别算法研究与实战

大家好,我是微学AI,今天给大家介绍一下深度学习实战77-基于CNN+BiLSTM的异常用电行为的识别算法研究与实战。 在智能电网的快速发展背景下,电力系统的安全稳定运行显得尤为重要。异常用电行为,如非法窃电、设备故障导致的非正常耗电等,不仅影响电网的经济效益,还可能威胁…

ORA-51803: Vector dimension count must match the dimension count 错误解决

ORA-51803: Vector dimension count must match the dimension count 错误解决 0. 错误信息1. 解决方法 0. 错误信息 错误信息如下&#xff0c; oracledb.exceptions.DatabaseError: ORA-51803: Vector dimension count must match the dimension count specified in the col…

C语言(操作符)2

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸各位能阅读我的文章&#xff0c;诚请评论指点&#xff0c;关注收藏&#xff0c;欢迎欢迎~~ &#x1f4a5;个人主页&#xff1a;小羊在奋斗 &#x1f4a5;所属专栏&#xff1a;C语言 本系列文章为个人学习笔记&#x…

[C++]智能指针的实现:auto_ptr, shared_ptr, weak_ptr

auto_ptr 简介 交换资源的管理权&#xff0c;将被拷贝资源置空&#xff0c;很危险&#xff0c;一般被禁用 代码实现 namespace memory {template<typename T>class auto_ptr{public:auto_ptr(T* ptr):_ptr(ptr){}auto_ptr(auto_ptr<T>& ap){_ptr ap._ptr;…

快速话术本(常用文本快速复制工具)EXE成品+软件源码

功能介绍 经常性需要重复性的输入几个不同的文本&#xff0c;来回复制很麻烦&#xff0c;这个小工具可以帮你解决&#xff0c;把要经常输入的文本添加进去&#xff0c;点击即可复制~ 链接&#xff1a;https://pan.baidu.com/s/1TqtJ_Xb10k4j3dxSRjz47Q?pwdsl4l 提取码&…

38.分布式文件系统 - Minio

文章目录 分布式文件系统MinIO安装和启动docker中MinIO的使用podman 虚拟机里使用Docker启minio配置&#xff08;成功访问&#xff09; Java连接minio 分布式文件系统 MinIO 官网&#xff1a;[https://min.io] 中文&#xff1a;[https://www.minio.org.cn/] [http://docs.mi…

Guid转换为字符串

在理想情况下&#xff0c;任何计算机和计算机集群都不会生成两个相同的GUID。GUID 的总数达到了2128&#xff08;3.41038&#xff09;个&#xff0c;所以随机生成两个相同GUID的可能性非常小&#xff0c;但并不为0。GUID一词有时也专指微软对UUID标准的实现。 (1). GUID&#…

如何避免在抓取Google时被屏蔽?代理IP的7个使用误区

在当今数字化时代&#xff0c;数据采集和网络爬取已成为许多企业和个人必不可少的业务活动。对于爬取搜索引擎数据&#xff0c;特别是Google&#xff0c;使用代理IP是常见的手段。然而&#xff0c;使用代理抓取Google并不是一件轻松的事情&#xff0c;有许多常见的误区可能会导…

【FFmpeg】Filter 过滤器 ① ( FFmpeg 过滤器简介 | 过滤器概念 | 过滤器用法 | 过滤器工作流程 | 过滤器文档 | 过滤器分类 )

文章目录 一、FFmpeg 过滤器 Filter 简介1、FFmpeg 过滤器概念2、FFmpeg 过滤器用法3、FFmpeg 过滤器工作流程4、FFmpeg 过滤器文档 二、FFmpeg 过滤器 分类1、过滤器分类 - 根据处理数据类型分类2、过滤器分类 - 根据编码器位置分类3、过滤器分类 - 根据功能分类 FFmpeg 相关文…

typescript的入门到吐槽:看了typescript,发现前端真的卷,

typescript TypeScript 是一种由微软开发的自由和开源的编程语言。它是 JavaScript 的一个超集&#xff0c;而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。 TypeScript 与 JavaScript 的区别 其实就是对JavaScript的封装&#xff0c;把一个弱类型语言封…

刨析YOLOv8的改进模块

1、YOLOv5回顾 这里粗略回顾一下,这里直接提供YOLOv5的整理的结构图吧:Backbone:CSPDarkNet结构,主要结构思想的体现在C3模块,这里也是梯度分流的主要思想所在的地方;PAN-FPN:双流的FPN,必须香,也必须快,但是量化还是有些需要图优化才可以达到最优的性能,比如cat前后…

淘宝扭蛋机小程序,开启你的惊喜探索之旅!

亲爱的淘宝用户们&#xff0c;我们非常高兴地宣布&#xff0c;全新的淘宝扭蛋机小程序即将上线&#xff01;这是一款集合了趣味、惊喜与购物乐趣于一体的创新应用&#xff0c;让你在淘宝的海洋里&#xff0c;找到那份独特的快乐。 一、淘宝扭蛋机小程序是什么&#xff1f; 淘…