leetcode算法入门系列学习11(递归 / 回溯)『 组合 | 全排列 | 字母大小写全排列 』

不积跬步,无以至千里

  • 【= 组合 =】
    • 题目描述
    • 解题思路
    • 解题方法
  • [= 全排列 =]
    • 题目描述
    • 解题思路
    • 解题方法
  • [= 字母大小写全排列 =]
    • 题目描述
    • 解题思路
    • 解题方法

【= 组合 =】

题目描述

传送门

解题思路

求得n个数中k个数的组合集合
关于题解 可以参考这个
关于回溯算法 你该了解这些!!!

解题方法

  • PHP
 function combine($n, $k) {
     
    $result = []; 
    $this->backtrack($n,$k,1,[], $result);
    return $result;
 }

 function backtrack($n,$k,$start,$path,&$result) {
     
    if(count($path) == $k) {
     
        $result[] = $path;
        return;
    }
    //剪枝:如果循环起始位置之后的个数已经不满足我们需要的个数了
    //就没必要在继续检索了,减少不必要的循环
    for ($i=$start;$i<=$n-($k-count($path))+1;$i++) {
     
        $path[] = $i;
        $this->backtrack($n,$k,$i+1,$path,$result);
        array_pop($path);
    }
 }

leetcode算法入门系列学习11(递归 / 回溯)『 组合 | 全排列 | 字母大小写全排列 』_第1张图片

  • GO
var res [][]int

func combine(n int, k int) [][]int {
     
	res = [][]int{
     }
	backtrack(n, k, 1, []int{
     })
	return res
}

func backtrack(n, k, start int, path []int) {
     
	if len(path) == k {
     
		temp := make([]int, k)
		copy(temp, path)
		res = append(res, temp)
		return
	}
	for i := start; i <= n-(k-len(path))+1; i++ {
     
		path = append(path, i)
		backtrack(n, k, i+1, path)
		path = path[:len(path)-1]
	}
}

leetcode算法入门系列学习11(递归 / 回溯)『 组合 | 全排列 | 字母大小写全排列 』_第2张图片

[= 全排列 =]

题目描述

传送门

解题思路

经典回溯算法题:相较于上题较简单
回溯中参数为原始数组nums,以及当前数组arr
回溯的终止条件为,当前arr的个数已经等于原始数组nums
回溯的处理,循环遍历原始数组nums,当前值不存在arr中时,将该值放入arr中,递归调用
由于上面的行为会找到最终答案,所以,在处理完上面请求时,将arr进行出栈操作,继续遍历

解题方法

  • PHP

function permute($nums) {
     
    $res = [];
    $this->backtrack($nums,[],$res);
    return $res;
}

function backtrack($nums, $arr, &$res) {
     
    if(count($arr) == count($nums)) {
     
        $res[] = $arr;
        return; 
    }
    foreach($nums as $v) {
     
        if(!in_array($v,$arr)) {
     
            $arr[] = $v;
            $this->backtrack($nums, $arr, $res);
            array_pop($arr);
        }
    }
}

leetcode算法入门系列学习11(递归 / 回溯)『 组合 | 全排列 | 字母大小写全排列 』_第3张图片

  • GO
var res [][]int
func permute(nums []int) [][]int {
     
    res = [][]int{
     }
	backtrack(nums,len(nums), []int{
     })
	return res
}

func backtrack(nums[]int, numLen int, path []int) {
     
	if len(nums)==0{
     
		temp := make([]int, len(path))
		copy(temp, path)
		res = append(res, temp)
		return
	}
	for i:=0;i<numLen;i++ {
     
		cur :=nums[i]
		path = append(path,cur)
		nums = append(nums[:i],nums[i+1:]...)
		backtrack(nums, len(nums), path)
		nums = append(nums[:i], append([]int{
     cur},nums[i:]...)...)
		path = path[:len(path)-1]
	}
}

leetcode算法入门系列学习11(递归 / 回溯)『 组合 | 全排列 | 字母大小写全排列 』_第4张图片

[= 字母大小写全排列 =]

题目描述

传送门

解题思路

1、从左往右依次遍历字符
2、判断是否为数字。如果是数字则直接拼接
3、如果是字母,将当前遍历过的字符串复制两份,第一份末尾添加lowercase(s),第二份末尾拼接upper(s)

解题方法

  • PHP
private $res = [];

/**
 * @param String $s
 * @return String[]
 */
function letterCasePermutation($s) {
     
    $this->back($s, 0, "", strlen($s));
    return $this->res;
}

function back($s, $start, $temp, $len) {
     
    for($j=$start; $j<$len; $j++) {
     
        if(is_numeric($s[$j])) {
     
            // 是数字
            $temp .= $s[$j];
        } else {
     
            // 是字母
            if(strtolower($s[$j]) == $s[$j]) {
     
                // 小写->大写
                $this->back($s,$j+1, $temp . strtoupper($s[$j]), $len);
            } else {
     
                // 大写->小写
                $this->back($s, $j+1, $temp . strtolower($s[$j]), $len);
            }
            $temp .= $s[$j];
        }
    }
    if(strlen($temp) == $len) $this->res[] = $temp;
}

leetcode算法入门系列学习11(递归 / 回溯)『 组合 | 全排列 | 字母大小写全排列 』_第5张图片

  • GO
func letterCasePermutation(s string) []string {
     
    res := []string{
     ""}
	for i := 0; i < len(s); i++ {
     
		if (s[i] >= 'A' && s[i] <= 'Z') || (s[i] >= 'a' && s[i] <= 'z') {
     
            // 是字母
			tmp := make([]string, len(res))
			//复制当前数组
			copy(tmp, res)
			for j, _ := range res {
     
				res[j] = res[j] + strings.ToLower(string([]byte{
     s[i]}))
				tmp[j] = tmp[j] + strings.ToUpper(string([]byte{
     s[i]}))
			}
			res = append(res, tmp...)
		} else {
     
			//如果是数字,则直接再末尾加上该数字即可
			for j, _ := range res {
     
				res[j] = res[j] + string([]byte{
     s[i]})
			}
		}
	}
	return res
}

leetcode算法入门系列学习11(递归 / 回溯)『 组合 | 全排列 | 字母大小写全排列 』_第6张图片== 终于 ~~~完成了 ~~~==

你可能感兴趣的:(leetcode,算法,leetcode,算法,php,go)