dfs_字母的转换

1. 问题描述:

描述

给定一个字符串str,str全部由数字字符组成,如果str中某一个或者某相邻两个字符组成的子串在1~26之间,则这个子串可以转换为一个字母。

规定“1”转换为“A”,“2”转换为“B”……“26”转换为“Z”。求str有多少种不同的转换结果。

输入

字符串str(|str|<20)

输出

可转换结果的数目

样例输入

12345678

样例输出

3

2. 对于这类问题,我们经常是采用dfs算法进行试探,尝试走遍每一条路径,假如这条路径不行那么退回来走另外的一条路,因为它涉及到相邻字符串的问题,所以这里使用到了Java中的substring方法进行字符串的截取,这里在截取字符串的时候特别要注意字符串截取越界的问题。通过对相邻字符串的截取,我们发现很明显这道题目存在着两个平行状态,对应着截取的两个字符串

因为有的路径不能够把数字转换成字母所以这里我们使用if语句进行提前的剪枝,当前这个状态下可以截取字符串才截取,不满足条件那么就不截取字符串,这样就会大大减少搜索的次数

3. 具体的代码如下:(提交到代码平台之后才得了80分,可能是有的情况没有考虑完全导致结果出现部分错误了)

import java.util.Scanner;
public class Main{
    static int count = 0;
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String s = sc.nextLine();
        int n = s.length();
        if(!s.equals("")){
            dfs(s, 0, n);
        }
        System.out.println(count);
        sc.close();
    }
    private static void dfs(String s, int k, int n){
        if(k == n){
            count++;
            return;
        }
        //加上if判断条件是为了在截取字符串的时候不发生字符串的越界的情况

       //因为截取到最后的时候有的可能不能够再截取两个字符串了
        if(k + 1 <= n){
            String left = s.substring(k, k + 1);
            int leftToNum = Integer.parseInt(left);
            if(leftToNum >= 1 && leftToNum <= 26){
                dfs(s, k + 1, n);
            }
        }
        if(k + 2 <= n){
            String right = s.substring(k, k + 2);
            int rightToNum = Integer.parseInt(right);
            //if条件可以进行提前剪枝
            if(rightToNum >= 1 && rightToNum <=26){
                dfs(s, k + 2, n);
            }
        }
    }
}

这道题目的难点在于如何截取字符串的问题,而且在截取的时候如何确保不发生越界的问题,注意截取的时候也有技巧的:首先要截取"1",然后截取"12",不能够一开始就截取"1",然后截取"23",这样会导致后面的总的数量少于正确答案的数量的

下面以123456789为例:

                                                                 ""

                                          1                                          12

                                  2                   23                       3       34(x) 

                           3        34(x)   4         45                4  ....

                       4     ...            5                              5

                    5                    6                               6

                 6                     7                              7

              7                      8                              8

           8                       9                              9

        9

凡是不能够转换成字母的路径都会在if语句里面被剪断了,那么就不会搜索这条路径了

其中我们也可以记录下中间的结果来查看程序转换的结果是否正确 ,这里我们是要List进行记录,当我们增加一个元素退回来之后删除一个元素,这样就会保证每一次List加入的元素是正确的,具体的代码如下:

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main{
    static int count = 0;
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String s = sc.nextLine();
        int n = s.length();
        List<String> rec = new ArrayList<String>();
        char alps[] = new char[26];
        for(int i = 0; i < 26; i++){
            alps[i] = (char)('A' + i);
        }
        if(!s.equals("")){
            dfs(s, 0, n, rec, alps);
        }
        System.out.println(count);
        sc.close();
    }
    private static void dfs(String s, int k, int n, List<String> rec, char alps[]){
        if(k == n){
            count++;
            System.out.println(rec);
            return;
        }
        if(k + 1 <= n){
            String left = s.substring(k, k + 1);
            int leftToNum = Integer.parseInt(left);
            if(leftToNum >= 1 && leftToNum <= 26){
                //使用list记录的过程与前面的过程是一样的加入一个退回来之后删除一个
                rec.add(alps[leftToNum - 1]+ "");
                dfs(s, k + 1, n, rec, alps);
                //回溯
                rec.remove(rec.size() - 1);
            }
        }
        if(k + 2 <= n){
            String right = s.substring(k, k + 2);
            int rightToNum = Integer.parseInt(right);
            if(rightToNum >= 1 && rightToNum <=26){
                rec.add(alps[rightToNum - 1]+ "");
                dfs(s, k + 2, n, rec, alps);
                //回溯
                rec.remove(rec.size() - 1);
            }
        }
    }
}

记录下中间的结果有助于我们更好地理解其中的dfs过程,培养自己对于类似题目的条件发射

猜你喜欢

转载自blog.csdn.net/qq_39445165/article/details/83688316
今日推荐