【PHP解法==LeetCode(回溯递归1)】17.电话号码的字母组合 && 93. 复原IP地址 && 131. 分割回文串

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010365335/article/details/87928229

目录

17.电话号码的字母组合

93. 复原IP地址

131. 分割回文串


17.电话号码的字母组合

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

示例:

输入:"23"
输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].

分析:如下图,digits = “23”。此时2可以表示为abc,3可以表示为def,则依次相连

解法:递归解法

class Solution {
    //数字->字符:映射数组
    private $letterMap = [
        '',     //0
        '',     //1
        'abc',  //2
        'def',  //3
        'ghi',  //4
        'jkl',  //5
        'mno',  //6
        'pqrs', //7
        'tuv',  //8
        'wxyz'  //9
    ];
    /**
     * @param String $digits
     * @return String[]
     */
    function letterCombinations($digits) {
        $res = [];                                      //初始化结果数组
        $len = strlen($digits);                         //初始化判断,若长度为0,则返回空数组
        if($len == 0) return $res;
        $this->findCombination($digits,$len,0,'',$res); //进行递归回溯操作
        return $res;
    }
    /**
     * [递归回溯寻找最终结果值]
     * @param  [type] $digits [$digits]
     * @param  [type] $len    [$digits数组的长度]
     * @param  [type] $index  [下标]
     * @param  [type] $str    [每一次的连接结果]
     * @param  [type] &$res   [结果数组]
     */
    private function findCombination($digits,$len,$index,$str,&$res){
        if($index == $len){                             //当下标==数组长度时,已经找到了最终结果,记录并返回
            $res[] = $str;
            return ;
        }
        $letters = $this->letterMap[$digits[$index]];   //找到对应下标数字可以转换的对应字母
        $lens = strlen($letters);
        for($i = 0;$i<$lens;++$i){
            $this->findCombination($digits,$len,$index+1,$str.$letters[$i],$res);   //连接上其中一个字母,下标+1,进行下一次循环
        }
        return ;
    }
}

93. 复原IP地址

给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。

示例:

输入: "25525511135"
输出:["255.255.11.135", "255.255.111.35"]

解法:递归回溯,终止条件为ip已经分到第四部分/下标已经到达字符串长度

注意:(1)0开头的字符,只能单独做ip的一个部分

           (2)已经是3个数字的,数字的大小不能超过255

           (3)递归时最后一个部分不用连接“.”

           (4)递归参数(下标,暂存的结果,已经分到第几部分)

class Solution {
    private $res = [];  //初始化结果数组
    private $s,$len;       //记录s和s的长度
    /**
     * @param String $s
     * @return String[]
     */
    function restoreIpAddresses($s) {
        $this->len = strlen($s);
        $this->s = $s;
        if($this->len > 12 || $this->len < 4) return $this->res  //初始化条件判断,ip的数字不能大于12也不能小于4
        $this->findIp(0,'',0);                                   //进行递归遍历
        return $this->res;
    }
    /**
     * [递归回溯寻找正确的IP]
     * @param  [type] $index [下标]
     * @param  [type] $path  [暂存的结果路径]
     * @param  [type] $part  [ip记录到第几部分,一个IP有4个部分]
     */
    private function findIp($index,$path,$part){
        //当ip记录到了第4部分并且下标长度到达$s的长度,即无法继续进行下去,记录结果数组并返回
        if($index == $this->len && $part == 4){
            $this->res[] = $path; 
            return;
        }
        if($part == 4) return;                                  //当$part到达第四部分时,无法再继续进行下去,直接返回
        $connect = $part == 3 ? '':'.';                         //当$part到达3,即最后一个部分时,就不再需要连接小数点“.”
        if($this->s[$index] == '0'){                            //当s在该下标下的字符是0时,则直接进行下一循环,0只能单独占一个部分
            $this->findIp($index+1,$path.'0'.$connect,$part+1); 
        }else{
            $num = '';                                          //继续进行循环,连接往后的3个数字,且不能超过$s的长度
            for($i = $index;$i<$index+3 && $i<$this->len;++$i){
                $num .= $this->s[$i];
                if((int)$num > 255) return;                     //当数字超过255时,直接返回,ip不可能超过255
                $this->findIp($i+1,$path.$num.$connect,$part+1);//进行下次递归回溯
            }
        }
    }
}

131. 分割回文串

给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。

返回 s 所有可能的分割方案。

示例:

输入: "aab"
输出:
[
  ["aa","b"],
  ["a","a","b"]
]

解法:递归回溯,终止条件为下标已经到达字符串长度

注意:(1)只有当字符串是回文的时候,压入暂存的结果数组,再进行递归

           (2)完成递归后,要弹出暂存的结果数组,完成回溯操作,才能压入新的元素

           (3)该题会从头遍历到尾,从1个字符往后慢慢增加

class Solution {
    private $res = [];  //初始化结果数组
    private $s,$len;    //初始化$s和$s的长度
    /**
     * @param String $s
     * @return String[][]
     */
    function partition($s) {
        $this->len = strlen($s);
        $this->s = $s;
        if($this->len == 0) return $this->res;    //初始化判断:当字符串为空时,不存在回文字符串,直接返回空数组
        $this->findPartition(0,[]);               //进行递归回溯
        return $this->res;
    }
    /**
     * [递归回溯寻找合适的回文数组]
     * @param  [type] $index [下标]
     * @param  [type] $path  [暂存满足条件的回文数组]
     */
    private function findPartition($index,$path){
        if($index == $this->len){                   //当下标==字符串长度时,无法继续进行下去,记录结果数组并返回
            $this->res[] = $path;
            return;
        }
        $str = '';                                  //记录可能的回文字符串
        for($i=$index;$i<$this->len;++$i){          //尝试每一种可能
            $str .= $this->s[$i];                   //连接字符串
            if($this->isHuiWen($str)){              //判断该字符串是否是回文字符串
                $path[] = $str;                     //是,则保存路径,并继续递归
                $this->findPartition($i+1,$path);   //下标+1,传递残存的路径
                array_pop($path);                   //回溯:弹出路径,下一次可以插入新的值
            }
        }
    }
    /**
     * [判断字符串是否是回文]
     * @param  [type]  $s [传入的字符串]
     */
    private function isHuiWen($s){
        //从前往后和从后往前都是一样的字符
        for($i = 0,$j = strlen($s)-1;$i<$j;++$i,--$j){
            if($s[$i] != $s[$j])
                return false;
        }
        return true;
    }
}

猜你喜欢

转载自blog.csdn.net/u010365335/article/details/87928229