Java题目训练——统计每个月兔子的总数和字符串通配符

目录 

一、统计每个月兔子的总数

二、字符串通配符


一、统计每个月兔子的总数

  题目描述:

有一种兔子,从出生后第3个月起每个月都生一只兔子,小兔子长到第三个月后每个月又生一只兔子。 例子:假设一只兔子第3个月出生,那么它第5个月开始会每个月生一只兔子。 一月的时候有一只兔子,假如兔子都不死,问第n个月的兔子总数为多少?

数据范围:1<=n<=31

输入描述:

输入一个int型整数表示第n个月

输出描述:

输出对应的兔子总数

示例

输入:3

输出:2

题目解析:

       找规律,就是一个斐波那契数列,这里采用递归的方式,如果是第1个数或者第2个数,返回1;否则返回这个位置的前两个数之和。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();

        System.out.println(num(n));

    }

    public static int num(int n){
        if(n == 1 || n == 2){
            return 1;
        }
        return num(n - 1) + num(n - 2);
    }
}

二、字符串通配符

题目描述:

问题描述:在计算机中,通配符一种特殊语法,广泛应用于文件搜索、数据库、正则表达式等领域。现要求各位实现字符串通配符的算法。 要求:

实现如下2个通配符:

*:匹配0个或以上的字符(注:能被*和?匹配的字符仅由英文字母和数字0到9组成,下同)

?:匹配1个字符 注意:匹配时不区分大小写。

输入:

通配符表达式;

一组字符串。

输出:

返回不区分大小写的匹配结果,匹配成功输出true,匹配失败输出false

数据范围:字符串长度:1<=s<=100

进阶:时间复杂度:O(n^{2}) ,空间复杂度:O(n) 

输入描述:

先输入一个带有通配符的字符串,再输入一个需要匹配的字符串

输出描述:

返回不区分大小写的匹配结果,匹配成功输出true,匹配失败输出false

示例

示例1

输入:te?t*.*

           txt12.xls

输出:false

示例2

输入:z

           zz

输出:false

示例3

输入:pq

           ppqq

输出:false

示例4

输入:**Z

           0QZz

输出:true

示例5

输入:?*Bc*?

           abcd

输出:true

示例6

输入:h*?*a

           h#a

输出:false

说明:根据题目描述可知能被*和?匹配的字符仅由英文字母和数字0到9组成,所以?不能匹配#,故输出false

示例7

输入:p*p*qp**pq*p**p***ppq

           pppppppqppqqppqppppqqqppqppqpqqqppqpqpppqpppqpqqqpqqp

输出:false

题目解析: 

        本题采用动态规划的思想,一共有三种情况,一种是匹配"*",一种是匹配"?",一种是自身对应匹配,其中匹配"?"和自身对应可以归为一种情况。

        将两个字符串s1(有通配符),s2全都转化为小写,并且创立一个boolean状态数组arr[s1.length()+ 1][s2.length()+ 1],+1是为了设立初始态,并且使下标对应。

        初始态为arr[0][0] = true,s1为"**...",s2为空的话,字符串此位置为"*"并且上一个状态为true时,此时状态为true;s1如果为空的话,直接默认为false。

        首先看匹配"*"的情况,如果s1此时的字符是*,并且s2此时的字符合法,那么有三种状态,第一种是如果*匹配s2的上一个状态,那么这时的状态也是true;第二种是如果不匹配*也true(即s1的上一个状态匹配这时的状态),那么true;第三种是如果*匹配当前字符,状态为true。只要这三种可能有一种为true,就记此时的状态为true。

        其次就是匹配"?"和自身对应的两种情况,只要上一个状态为true,并且这两种情况成立一种就可以记为true。

        最后输出arr[s1.length()][s2.length()]的状态即可。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String s1 = scanner.nextLine();
        String s2 = scanner.nextLine();

        //全部转成小写
        s1 = s1.toLowerCase();
        s2 = s2.toLowerCase();

        int n1 = s1.length();
        int n2 = s2.length();

        //建立状态存储数组
        boolean[][] arr = new boolean[n1 + 1][n2 + 1];

        //两个字符串都为空,初始化为0
        arr[0][0] = true;

        //s1为***...
        //s2为空
        //初始化
        for(int i = 1; i < n1 + 1; i++){
            arr[i][0] = s1.charAt(i - 1) == '*' && arr[i - 1][0];
        }

        //动态规划
        for(int i = 1; i < n1 + 1; i++){
            for (int j = 1; j < n2 + 1; j++) {
                char ch1 = s1.charAt(i - 1);
                char ch2 = s2.charAt(j - 1);
                //为'*'的情况
                if(ch1 == '*' && isTrue(ch2)){
                    //arr[i][j - 1] '*'匹配j - 1成功,所以匹配j也成功
                    //arr[i - 1][j] '*'匹配0次
                    //arr[i - 1][j - 1] '*'匹配当前字符
                    arr[i][j] = arr[i][j - 1] || arr[i - 1][j - 1] || arr[i - 1][j];
                }else {
                    //为'?'的情况
                    //字符自身匹配相等的情况
                    //注意括号范围
                    arr[i][j] = arr[i - 1][j - 1] && (ch1 == ch2 ||(ch1 == '?' && isTrue(ch2)));
                }
            }
        }
        System.out.println(arr[n1][n2]);
    }

    //字符是否符合范围
    public static boolean isTrue(char ch){
        if((ch >='0' && ch <='9')|| (ch >= 'a' && ch <= 'z')){
            return true;
        }
        return false;
    }
}

如有建议或想法,欢迎一起讨论学习~

你可能感兴趣的:(刷题记录,java,开发语言,算法)