zoukankan      html  css  js  c++  java
  • Go语言实现列出排列组合

    今天,隔壁坐的小朋友给我一串数字:

    1 6 21 55

    让我观察规律,然后帮他推导公式。

    尼玛,当我是神呢?!!

    想了半天没看出个原委,

    于是看了他那边具体需要才发现他那边是对N个数字进行5个数字的组合,

    有多少种可能性的计算。

    我一想,这不是初中学过的排列组合公式么。

    显然,我忘记了,呵呵。

    只记得大概是叫Pmn

    然后通过搜索引擎看到如下百度百科里面排列组合的几十这里:

    http://baike.baidu.com/item/%E6%8E%92%E5%88%97%E7%BB%84%E5%90%88/706498

    关键是当我用这个公式推导出上面数列里面的55是错的,应该是56.

    小朋友不服啊!说他是一个一个手打出来检查过了的。

    尼玛,不相信科学啊。

    虽然他后面也相信这个公式了。

    但是为了给他普及科学的强大,不要过分相信自己,也因为最近太闲,学得东西太杂,失去方向,于是就来练练Go语言吧。

    我还是想办法去把这些排列组合打印粗来,代码写得难看,算法也是渣渣,但是勉强看吧:

     1 package main
     2 
     3 import (
     4     "fmt"
     5     "strconv"
     6     "strings"
     7 )
     8 
     9 var a []int = []int{1, 2, 3, 4, 5, 6, 7}
    10 var rawLen int
    11 var combineLen int
    12 
    13 func main() {
    14     rawLen = len(a)
    15     combineLen = 4
    16     combine()
    17 }
    18 
    19 func combine() {
    20     fmt.Println("start combine")
    21     arrLen := len(a) - combineLen
    22     for i := 0; i <= arrLen; i++ {
    23         result := make([]int, combineLen)
    24         result[0] = a[i]
    25         //fmt.Println(i, arrLen)
    26         doProcess(result, i, 1)
    27     }
    28 }
    29 
    30 func doProcess(result []int, rawIndex int, curIndex int) {
    31     var choice int = rawLen - rawIndex + curIndex - combineLen
    32     //fmt.Printf("Choice: %d, rawLen: %d, rawIndex : %d, curIndex : %d 
    ", choice, rawLen, rawIndex, curIndex)
    33     var tResult []int
    34     for i := 0; i < choice; i++ {
    35         if i != 0 {
    36             tResult := make([]int, combineLen)
    37             copyArr(result, tResult)
    38         } else {
    39             tResult = result
    40         }
    41         //fmt.Println(curIndex)
    42         tResult[curIndex] = a[i+1+rawIndex]
    43 
    44         if curIndex+1 == combineLen {
    45             PrintIntArr(tResult)
    46             continue
    47         } else {
    48             doProcess(tResult, rawIndex+i+1, curIndex+1)
    49         }
    50 
    51     }
    52 }
    53 
    54 func copyArr(rawArr []int, target []int) {
    55     for i := 0; i < len(rawArr); i++ {
    56         target[i] = rawArr[i]
    57     }
    58 }
    59 
    60 func PrintIntArr(arr []int) {
    61     valuesText := []string{}
    62     for i := range arr {
    63         number := arr[i]
    64         text := strconv.Itoa(number)
    65         valuesText = append(valuesText, text)
    66     }
    67 
    68     fmt.Println(strings.Join(valuesText, ","))
    69 }

    说明:

    a:是用来组合的的所有数字,要保证他们的唯一性,不要出现重复的元素,不一定要保证顺序;

    combineLen:需要组合成的长度

    实现原理的关键点在这一句:

    var choice int = rawLen - rawIndex + curIndex - combineLen

    这句话的意思是什么呢?

    此位置的可用种类 = 原始数组上都 - 原始数组里面当前循环到的位置索引 + 当前结果数组的索引 - 需要合成的数组的长度

    啥意思呢?

    怎么体会呢?

    假设我们是长度为6的数组,我们要做成10个数字的组合,假设在循环原数组的第一个位置,索引为0的时候,我们目标数组的可选数有:

    10 - 0 + 0 - 5 = 5

    也就是0 - 5的索引即6中选择,在唯一元素的数组里面,你可以配合排序去理解,也就是:

    0 1 2 3 4 5 6 7 8 9 

    中第一个位置的可选是 0 1 2 3 4 5中选择,假设6,7,8,9可选,那么后面是无法补齐到5个数字的。

    后面的任意索引都是以此类推。

    以下结果是以5个元素3个数字进行组合的结果:

    这个故事告诉我们,程序行业还是要好好学习数学,最少得初中学历。

  • 相关阅读:
    CSS 常见的8种选择器 和 文本溢出问题
    CSS 的三种样式 内联 内部 外部
    小记
    冠词的用法
    Levenberg–Marquardt algorithm
    classical 和 classic 的区别
    论文时态
    简明 Python 教程
    pytorch中的动态学习率规划器
    如何计算数据集均值和方差
  • 原文地址:https://www.cnblogs.com/adoontheway/p/6047918.html
Copyright © 2011-2022 走看看