数据结构与算法


1 数字排列组合

1.1 描述

Golang 实现,将四个数进行排列组合。

1.2 题目

有 1、2、3、4 这四个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?

1.3 题目解决思路

可填在百位、十位、个位的数字都是 1、2、3、4。组成所有的排列后再去掉不满足条件的排列。

1.4 代码具体实现

  1.固定层数for循环:暴力枚举算法

  适用场景:题目位数固定(本题固定三位数);

  数据范围极小,只求快速通过。属于专用算法

package main
import (
	"fmt"
)
func main() {
	totalCount := 0
	/*以下为三重循环*/
	for i := 1; i < 5; i++ {
		for j := 1; j < 5; j++ {
			for k := 1; k < 5; k++ {
				/*确保 i 、j 、k 三位互不相同*/
				if i != k && i != j && j != k {
					totalCount++
					fmt.Println("第", totalCount, "方案", "i =", i, "j =", j, "k =", k)
				}
			}
		}
	}
	
	fmt.Println("共", totalCount, "种方案")
}
算法思路:回溯法(全排列选取3个元素)
核心算法:回溯(深度优先搜索DFS),从4个数字中选出3个进行排列,保证元素不重复,这是通用排列算法,数字数量、选取位数任意修改都可以复用。
选择一个未使用数字放入当前位置
标记该数字已被使用
递归填充下一位
递归回溯,撤销标记,尝试其他数字
凑够3位即为一组合法解
Go完整回溯代码
package main

import "fmt"

// 回溯函数
func backtrack(nums []int, used []bool, path []int, length int, result *[][]int) {
	// 终止条件:path长度等于3,找到一组解
	if len(path) == length {
		temp := make([]int, len(path))
		copy(temp, path)
		*result = append(*result, temp)
		return
	}

	for i := 0; i < len(nums); i++ {
		// 数字已经被选用,跳过
		if used[i] {
			continue
		}
		used[i] = true          // 选择
		path = append(path, nums[i])
		backtrack(nums, used, path, length, result)
		path = path[:len(path)-1] // 回溯撤销选择
		used[i] = false
	}
}

// 获取排列结果
func permutation(nums []int, pickNum int) [][]int {
	var result [][]int
	used := make([]bool, len(nums))
	backtrack(nums, used, []int{}, pickNum, &result)
	return result
}

func main() {
	nums := []int{1, 2, 3, 4}
	res := permutation(nums, 3)

	fmt.Println("所有无重复三位数组合:")
	count := 0
	for _, v := range res {
		num := v[0]*100 + v[1]*10 + v[2]
		fmt.Printf("%d ", num)
		count++
	}
	fmt.Printf("\n总数量:%d\n", count)
}
算法复杂度分析
时间复杂度:A_n^k = \dfrac{n!}{(n-k)!},本题n=4,k=3,运算24次。
空间复杂度:O(n),used数组和递归栈开销。
执行输出
所有无重复三位数组合:
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
对比说明
三层for循环属于暴力枚举,只适用于固定3位,属于特例写法。
回溯DFS是标准排列算法,属于通用解法,选2位、选4位、任意数组都能直接使用,面试算法标准答案。
如果你需要,我可以补充去重版本(存在重复数字时使用)。

文章作者: 罗宇
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 罗宇 !
  目录