微信拼手气红包实现(Go,腾讯面试题)

目录

题目描述

解决方案

代码

代码走读


 

题目描述

请实现微信拼手气红包算法,输入红包总额,输出红包抽取后的数值序列,算法考虑公平性、随机性。题目答案要求:总和为金额数,个数为红包数,单个金额不小于0.01,取两位小数。

 

解决方案

如果0.01 * 红包个数大于总金额,这种情况下钱不够分。

对每一个抢到的红包预先分配0.01元,分配后剩下的金额为:总金额 - 0.01 * 红包个数。利用循环将每一个红包随机的从剩下的金额池中选取一个随机数,将该随机数作为抢到的金额与预分配0.01相加即为最终的结果。

为了完全保证公平性,在返回最终序列之前,需要将序列打乱(因为在上述的随机从金额池抽取的过程中,会出现前几个红包将金额池瓜分完,导致后面的红包全部是0.01,因此不能保证完全的公平)。

 

代码

package main

import (
	"bufio"
	"fmt"
	"math/rand"
	"os"
	"strconv"
)

func main() {
	reader := bufio.NewReader(os.Stdin)
	fmt.Print("请输入总金额:")
	amountBytes, _, _ := reader.ReadLine()
	amount, err := strconv.ParseFloat(string(amountBytes), 10)
	if err != nil {
		fmt.Println("请输入合法的总金额格式。")
		return
	}

	fmt.Print("请输入红包个数:")
	numberBytes, _, _ := reader.ReadLine()
	number, err := strconv.Atoi(string(numberBytes))
	if err != nil {
		fmt.Println("请输入整数。")
		return
	}

	pool := amount - float64(number)*0.01
	if pool < 0 {
		fmt.Println("红包不够分")
		return
	}

	pool = pool * 100

	result := make([]float64, 0)
	for i := 0; i < number; i++ {
		if i == number-1 {
			packet := Decimal(pool*0.01 + 0.01)
			result = append(result, packet)
			continue
		}
		packet := rand.Intn(int(pool))
		pool = pool - float64(packet)
		result = append(result, Decimal(float64(packet)*0.01+0.01))
	}

	Suffix(&result)
	fmt.Println(result)
}

func Decimal(value float64) float64 {
	value, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", value), 64)
	return value
}

func Suffix(list *[]float64) {
	length := len(*list)
	if length <= 1 {
		return
	}

	for i := 0; i < length; i++ {
		randIndex := rand.Intn(length)
		(*list)[i], (*list)[randIndex] = (*list)[randIndex], (*list)[i]
	}
}

 

代码走读

package main

import (
   "bufio"
   "fmt"
   "math/rand"
   "os"
   "strconv"
)

func main() {
   // 从控制台读取总金额、红包个数
   reader := bufio.NewReader(os.Stdin)
   fmt.Print("请输入总金额:")
   amountBytes, _, _ := reader.ReadLine()
   amount, err := strconv.ParseFloat(string(amountBytes), 10)
   if err != nil {
      fmt.Println("请输入合法的总金额格式。")
      return
   }

   fmt.Print("请输入红包个数:")
   numberBytes, _, _ := reader.ReadLine()
   number, err := strconv.Atoi(string(numberBytes))
   if err != nil {
      fmt.Println("请输入整数。")
      return
   }

   // 为每一个红包预分配0.01元,然后将剩余的金额放入红包池中
   pool := amount - float64(number)*0.01
   if pool < 0 {
      fmt.Println("红包不够分")
      return
   }

   // 将红包池转换成以分为单位的数字
   pool = pool * 100

   // 为每一个红包分配随机的金额,随机数分布在 0 ~ pool
   result := make([]float64, 0)
   for i := 0; i < number; i++ {
      // 如果是最后一个红包,则将pool内的剩余金额全部分配
      if i == number-1 {
         packet := Decimal(pool*0.01 + 0.01)
         result = append(result, packet)
         continue
      }
      packet := rand.Intn(int(pool))
      pool = pool - float64(packet)
      result = append(result, Decimal(float64(packet)*0.01+0.01))
   }

   // 打乱分配结果
   Suffix(&result)
   fmt.Println(result)
}

// 将一个浮点数保留两位小数
func Decimal(value float64) float64 {
   value, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", value), 64)
   return value
}

// 打乱序列
func Suffix(list *[]float64) {
   length := len(*list)
   if length <= 1 {
      return
   }

   for i := 0; i < length; i++ {
      randIndex := rand.Intn(length)
      (*list)[i], (*list)[randIndex] = (*list)[randIndex], (*list)[i]
   }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章