微信拼手氣紅包實現(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]
   }
}

 

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