IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> Go代码实现 拼手气红包(二倍均值法) -> 正文阅读

[数据结构与算法]Go代码实现 拼手气红包(二倍均值法)

前言

仅个人笔记,欢迎交流指正

概念

红包主要有三点限制

  1. 抢到的总额 = 红包的总额,不能多也不能少了
  2. 最小值是0.01元,即每个人都有份
  3. 每个人抢到的红包金额,尽量平均

实现逻辑

  • 假设总金额是M元,N个人,每次抢的金额=(0, (M/N) *2)

  • 比如,金额100,人数10,第一个人抢的金额是 (0,20),抢到的数值,根据正态分布,应该是10左右,远低于10的概率很小,同样远大于10的概率和很小,这里假设第一个人抢到的数值是10;

  • 第二个人抢的金额是(0,90/9*2)=(0,20),同第一个人,第二个人红包金额也应该是10附近;剩下的人,以此类推。

提醒
参考的文章说这个算法不是完美的,假如第一个人抢到15,第二个人的范围是(0,18.89),假如第二个人又抢到很高,那对后面的人是不利的

代码实现

package main

import (
	"errors"
	"math/rand"
)

//RED_PACKET_MIN_MONEY 红包最小金额(单位:分)
const RED_PACKET_MIN_MONEY = 1

//RedPacketModel 红包信息实体
type RedPacketModel struct {
	count          int64   //红包个数
	money          int64   //红包金额(单位:分)
	remainCount    int64   //剩余红包个数
	remainMoney    int64   //剩余红包金额(单位:分)
	bestLuckMoney  int64   //手气最佳金额(单位:分)
	bestLuckIndex  int64   //手气最佳索引位置
	historyRewards []int64 //历史红包记录
}

/*
CreateRedPacket
@Desc 	生成红包
@Param 	count int64	红包个数
@Param 	money int64	红包金额
*/
func CreateRedPacket(count, money int64) (res *RedPacketModel, err error) {
	if count <= 0 || money <= 0 || money < count*RED_PACKET_MIN_MONEY {
		err = errors.New("parameter error")
		return
	}

	res = &RedPacketModel{
		count:          count,
		money:          money,
		remainCount:    count,
		remainMoney:    money,
		bestLuckMoney:  0,
		bestLuckIndex:  0,
		historyRewards: nil,
	}

	return
}

/*
Open
@Desc 	拆红包(二倍均值法)
@Return money 	int64	本地拆红包获得金额
@Return res 	bool	拆红包失败,红包已经被抢光
*/
func (r *RedPacketModel) Open() (money int64, res bool) {
	//检测红包是否被抢光
	if r.Check() {
		return
	}

	//最后一个红包
	if r.remainCount == 1 {
		money = r.remainMoney
	} else {
		//最大可用金额 = 剩余红包金额 - 后续多少个没拆的包所需要的保底金额
		//目的是为了保证后续的包至少都能分到最低保底金额,避免后续未拆的红包出现金额0
		maxCanUseMoney := r.remainMoney - RED_PACKET_MIN_MONEY*r.remainCount

		//2倍均值基础金额
		maxAvg := maxCanUseMoney / r.remainCount

		//2倍均值范围数额
		maxMoney := maxAvg*2 + RED_PACKET_MIN_MONEY

		//随机红包数额
		money = rand.Int63n(maxMoney) + RED_PACKET_MIN_MONEY
	}

	//手气最佳
	if money > r.bestLuckMoney {
		r.bestLuckMoney = money
		r.bestLuckIndex = r.count - r.remainCount
	}

	res = true
	r.remainMoney -= money
	r.remainCount--
	r.historyRewards = append(r.historyRewards, money)
	return
}

/*
Check
@Desc 校验红包是否被抢完
*/
func (r *RedPacketModel) Check() bool {
	return r.remainCount == 0
}

参考

  • 参考:https://www.yisu.com/zixun/310871.html
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-04-30 08:55:25  更:2022-04-30 08:58:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 5:52:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码