zoukankan      html  css  js  c++  java
  • 有1、2、3、4个数字,能组成多少个互不相同 且无重复数字的三位数?都是多少?

    前言

    今天看到一个超级简单的算法题,但是我当时思路往递归,逐级筛选里面想了。结果百度查查答案,超级简单。
    真是惭愧惭愧,不过我还是坚持用递归实现了,因为用递归的方案,可以适用于任何给定数据和指定位数。

    传统解法

    如下所示,因为题目是找1、2、3、4组合的三位数,因此可以用三重循环,遍历所有组合,筛选不重复组合即可。
    但是该方案,如果给定数据改变,组合位数改变,那代码就得大改,所以不是一个通用的好方法。

    func useNormal() []int {
    	var ret []int
    	for i := 1; i < 5; i++ {
    		for j := 1; j < 5; j++ {
    			for k := 1; k < 5; k++ {
    				if i != j && j != k && i != k {
    					ret = append(ret, i*100+j*10+k)
    				}
    			}
    		}
    	}
    	return ret
    }
    

    递归求解

    下面方案是通过递归,依次为某一位分配数字,并将剩余组合依次赋值下一位。
    该方法只需要改变data数据,以及numLen的指定位数就可以灵活地计算所有组合。

    func useRecursion() []int {
    	var (
    		data   = []int{1, 2, 3, 4}
    		numLen = 3
    		tmp    = make([]int, numLen)
    		ret    []int
    	)
    	findNum(data, tmp, numLen, &ret)
    	return ret
    }
    
    func findNum(data, tmp []int, dep int, ret *[]int) {
    	for i, v := range data {
    		if dep--; dep < 0 {
    			sum := 0
    			for i := len(tmp) - 1; i >= 0; i-- {
    				sum = sum*10 + tmp[i]
    			}
    			*ret = append(*ret, sum)
    			return
    		}
    		tmp[dep] = v // 当前选择赋值
    
    		next := make([]int, 0, len(data))
    		next = append(next, data[:i]...)
    		next = append(next, data[i+1:]...)
    		findNum(next, tmp, dep, ret) // 剔除当前元素,进入下一级筛选
    
    		dep++
    	}
    }
    

    完整代码

    执行结果如下,两种方案结果完全一致:

    [123 124 132 134 142 143 213 214 231 234 241 243 312 314 321 324 341 342 412 413 421 423 431 432] 24
    [123 124 132 134 142 143 213 214 231 234 241 243 312 314 321 324 341 342 412 413 421 423 431 432] 24

    package main
    
    import "fmt"
    
    func main() {
    	ret0 := useNormal()
    	fmt.Println(ret0, len(ret0))
    	ret1 := useRecursion()
    	fmt.Println(ret1, len(ret1))
    }
    
    func useNormal() []int {
    	var ret []int
    	for i := 1; i < 5; i++ {
    		for j := 1; j < 5; j++ {
    			for k := 1; k < 5; k++ {
    				if i != j && j != k && i != k {
    					ret = append(ret, i*100+j*10+k)
    				}
    			}
    		}
    	}
    	return ret
    }
    
    func useRecursion() []int {
    	var (
    		data   = []int{1, 2, 3, 4}
    		numLen = 3
    		tmp    = make([]int, numLen)
    		ret    []int
    	)
    	findNum(data, tmp, numLen, &ret)
    	return ret
    }
    
    func findNum(data, tmp []int, dep int, ret *[]int) {
    	for i, v := range data {
    		if dep--; dep < 0 {
    			sum := 0
    			for i := len(tmp) - 1; i >= 0; i-- {
    				sum = sum*10 + tmp[i]
    			}
    			*ret = append(*ret, sum)
    			return
    		}
    		tmp[dep] = v // 当前选择赋值
    
    		next := make([]int, 0, len(data))
    		next = append(next, data[:i]...)
    		next = append(next, data[i+1:]...)
    		findNum(next, tmp, dep, ret) // 剔除当前元素,进入下一级筛选
    
    		dep++
    	}
    }
    

    总结

    凡事有简单方案,也有复杂方案,简单往往不能通用,多想想通用方案,尝试解决一类问题而不是某一个问题。

    作者:janbar
    本文版权归作者和博客园所有,欢迎转载,转载请标明出处。喜欢我的文章请 [关注我] 吧。
    如果您觉得本篇博文对您有所收获,可点击 [推荐] [收藏] ,或到右侧 [打赏] 里请我喝杯咖啡,非常感谢。
  • 相关阅读:
    数据结构与算法(0)--必知必会
    数据结构概览
    Python 数据分析学习路线
    数据分析交互工具--使用jupyter
    Vue项目搭建
    luffy_08
    luffy_07
    luffy_06
    luffy_05
    luffy_04
  • 原文地址:https://www.cnblogs.com/janbar/p/15026491.html
Copyright © 2011-2022 走看看