面试题-三色球问题

本文作者 TomorrowWu,原创文章,转载注明出处,博客地址 https://segmentfault.com/u/to... 第一时间看后续精彩文章。觉得好的话,顺手分享到朋友圈吧,感谢支持。

最近看了一道关于三色球的面试题,虽然很简单,但是还是考研编码能力的,下面做个对比

题目

有红、黄、绿三种颜色的球,其中红球3个,黄球3个,绿球6个。现将这12个球混放在一个盒子里,从中任意摸出8个球,编程计算摸出球的各种颜色搭配。

看到题目,显然是排列组合问题,下面看代码

优化前

func computeMatch1(redCount, yellowCount, greenCount, total int) int {
    if redCount < 0 || yellowCount < 0 || greenCount < 0 || total <= 0 || total > redCount+yellowCount+greenCount {
        return 0
    }
    num := 0
    for r := 0; r <= redCount; r++ {
        for y := 0; y <= yellowCount; y++ {
            for g := 0; g <= greenCount; g++ {
                if r+y+g == total {
                    //log.Printf("red:%v yellow:%v green:%v", r, y, g)
                    num++
                }
            }
        }
    }
    return num
}

测试结果

为精确测出算法计算的时间,注释掉了log.Printf()代码

func Test_computeMatch1(t *testing.T) {
    t1 := time.Now()
    n := computeMatch1(3000,3000,6001,12000)
    duration := time.Since(t1)
    t.Logf("排列组合数量:%v 时长:%v",n,duration)
}

//结果
排列组合数量:3 时长:32.450475506s

代码未优化,三层for循环,且不管要求摸出多少球,遍历次数都一样,时间复杂度是O(n)=a*b*c,在球数比较大时,运算时间惊人

优化后

func computeMatch(redCount, yellowCount, greenCount, total int) int {
    if redCount < 0 || yellowCount < 0 || greenCount < 0 || total <= 0 || total > redCount+yellowCount+greenCount {
        return 0
    }

    num := 0
    for r := 0; r <= redCount; r++ {
        if yellowCount+greenCount < total-r {
            continue
        }
        if r == total {
            num++
            //log.Printf("red:%v yellow:%v green:%v", r, 0, 0)
            break
        } else if r < total {
            for y := 0; y <= yellowCount; y++ {

                if r+y == total {
                    num++
                    //log.Printf("red:%v yellow:%v green:%v", r, y, 0)
                    break
                } else if r+y < total {
                    needGreen := total - r - y
                    if needGreen > 0 && greenCount >= needGreen {
                        //log.Printf("red:%v yellow:%v green:%v", r, y, total-r-y)
                        num++
                    }
                }
            }
        }
    }
    return num
}

测试结果

func Test_computeMatch(t *testing.T) {
    t1 := time.Now()
    n := computeMatch(3000,3000,6001,12000)
    duration := time.Since(t1)
    t.Logf("排列组合数量:%v 时长:%v",n,duration)
}
//结果
排列组合数量:3 时长:106.502µs

总结

  1. 第一点主要是解题思路,能迅速将问题对应到数学上的排列组合问题,初步思路就是三层for循环
  2. 第二点就是代码质量问题,因为三层for循环,循环次数累积相乘,当球数很大时,计算所消耗的时间很可怕,虽然只有3种组合方式,所以就针对题目特点,对第二层循环做了优化,第三层循环可以去掉,具体优化看代码,并不复杂
  3. 第三点就是对函数参数的边界检查,细心

你可能感兴趣的:(笔试,面试,算法)