拼贴纸问题

问题描述

给定一个字符串str,给定一个字符串数组arr;
arr里的每一个字符串代表一张贴纸,可以把单个字符剪开使用,
目的是拼出字符串str,求至少需要多少张贴纸可以拼出字符串str。
例:str = "babac",arr = {"ba", "c", "abcd"}
至少需要两张贴纸,分别是“ba”和“abcd”,使用这两张贴纸,把每个字符单独剪开,
有2个a,2个b,1个c,可以拼出babac,所以结果是2。

题解

/**
 * @author IT00ZYQ
 * @date 2021/4/10 19:31
 **/
public class 拼贴纸 {

    public static int way1(String str, String[] arr) {
        // 将每个贴纸以数组的形式存储
        int[][] map = new int[arr.length][26];
        for (int i = 0; i < arr.length; i++) {
            for (char c : arr[i].toCharArray()) {
                map[i][c - 'a'] ++;
            }
        }
        return wayFunc1(str, map);
    }

    /**
     * @param rest 当前剩余的需要拼的字符,可变变量
     * @param map 每个贴纸的字符及其数量
     * @return 拼出rest字符串需要的最少贴纸数
     */
    private static int wayFunc1(String rest, int[][] map) {
        // 需要拼的字符串已经为空字符串,不再需要任何贴纸
        if ("".equals(rest)) {
            return 0;
        }
        // 将rest字符串也转化成数组
        int[] restMap = new int[26];
        for (char c : rest.toCharArray()) {
            restMap[c - 'a'] ++;
        }

        int minNext = Integer.MAX_VALUE;
        // 遍历所有贴纸
        for (int i = 0; i < map.length; i++) {
            // 只寻找包含rest字符串首字符的贴纸
            if (map[i][rest.charAt(0) - 'a'] == 0) {
                continue;
            }
            // 将rest - arr[i]剩余的字符串保存到sb中
            StringBuilder sb = new StringBuilder();
            for (int j = 0; j < 26; j++) {
                for (int k = 0; k < restMap[j] - map[i][j]; k++) {
                    sb.append((char)(j+'a'));
                }
            }
            // rest - arr[i]剩下的字符串需要的最少贴纸数
            minNext = Math.min(wayFunc1(sb.toString(), map), minNext);
        }
        // 当minNext为Integer.MAX_VALUE表示贴纸无法拼出字符串rest
        // 直接返回-1
        return minNext == Integer.MAX_VALUE ? -1 : (minNext + 1);
    }

    public static void main(String[] args) {
        String str = "abcccccdddddbbbaaaaa";
        String[] arr = {"aaaa", "bbaa", "ccddd"};

        System.out.println(way1(str, arr));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

it00zyq

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值