庞果网 合法字符串

题目详情:
用n个不同的字符(编号1 - n),组成一个字符串,有如下2点要求:
    1、对于编号为i 的字符,如果2 * i > n,则该字符可以作为最后一个字符,但如果该字符不是作为最后一个字符的话,则该字符后面可以接任意字符;
    2、对于编号为i的字符,如果2 * i <= n,则该字符不可以作为最后一个字符,且该字符后面所紧接着的下一个字符的编号一定要 >= 2 * i。
问有多少长度为M且符合条件的字符串。
例如:N = 2,M = 3。则abb, bab, bbb是符合条件的字符串,剩下的均为不符合条件的字符串。


输入:n,m  (2<=n,m<=1000000000);
输出:满足条件的字符串的个数,由于数据很大,输出该数Mod 10^9 + 7的结果。


函数头部
int validstring(int n,int m) {

}


代码如下:

import java.math.BigDecimal;
import java.util.LinkedList;
import java.util.Queue;

public class Main {
    public static int validstring(int n,int m) {
        if (n > 2 || m > 1000000000){
            System.err.println("‘n’或者‘m’超出范围了!");
            return 0;
        }
        long count = countValid(n, m);
        return BigDecimal.valueOf(count % (Math.pow(10, 9) + 7)).intValue();
    }
    
    //n个字符m位的全排列组合
    private static long countValid(int n, int m) {
        String v = "";
        long s = 0;
        char[] charArray = buildCharArray(n);
        // 队列用来保存被访问节点的分支节点(邻接点)
        Queue<String> que = new LinkedList<String>();
        que.offer(v);// 起点入队列
        while (!que.isEmpty()) {
            v = que.poll();// 弹出当前顶点
            // 将当前节点的分支节(邻接)点加入到队列中
            for (int i = 0; i < n; i++) {
                String u = v + charArray[i];
                if (u.length() == m) {//m位,则校验是不是符合题目的要求
                    if (checkStr(u, charArray, 0)){
                        System.out.println(u);
                        ++s;
                    }
                } else{
                    que.add(u); // 邻接点入队
                }
            }
        }
        return s;
    }
    
    //校验字符串是否符合规则
    private static boolean checkStr(String str, char[] charArray, int j){
        boolean returnFlag = false;
        int n = charArray.length;
        int m = str.length();
        char c = str.charAt(j);
        Integer i = getCharArrayIndex(charArray, c);
        //如果2 * i > n,则该字符可以作为最后一个字符,但如果该字符不是作为最后一个字符的话,则该字符后面可以接任意字符;
        if (2 * (i + 1) > n){
            if (j == m - 1){
                returnFlag = true;
            }else{
                returnFlag = checkStr(str, charArray, j + 1);
            }
        }else{//如果2 * i <= n,则该字符不可以作为最后一个字符,且该字符后面所紧接着的下一个字符的编号一定要 >= 2 * i。
            if (j == m - 1){
                returnFlag = false;
            }else{
                char d = str.charAt(j + 1);
                int ii = getCharArrayIndex(charArray, d);
                if (ii + 1 < 2 * (i + 1)){
                    returnFlag = false;
                }else{
                    returnFlag = checkStr(str, charArray, j + 1);
                }
            }
        }
        return returnFlag;
    }
    
    private static Integer getCharArrayIndex(char[] charArray, char c){
        Integer returnIndex = null;
        for (int i = 0; i < charArray.length; i++){
            char d = charArray[i];
            if (d == c){
                returnIndex = i;
            }
        }
        return returnIndex;
    }
    
    //产生1-n的随机字符
    private static char[] buildCharArray(int n){
        StringBuffer returnValue = new StringBuffer();
        for (int i = 0; i < n; i++){
            char c = 'a';
            c = (char)(c + i);
            returnValue.append(c);
        }
        return returnValue.toString().toCharArray();
    }

    //start 提示:自动阅卷起始唯一标识,请勿删除或增加。 
    public static void main(String args[]) 
    { 
           System.out.println(validstring(2, 10) + " 次");
    } 
    //end //提示:自动阅卷结束唯一标识,请勿删除或增加。
}


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值