leetcode -- 691. Stickers to Spell Word【动态规划 + 位图使用】

解决一个给定的目标字符串,通过组合不同类型的贴纸上的字母来构成该字符串的问题。每个贴纸可以无限次使用,目标是最小化所需贴纸数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

We are given N different types of stickers. Each sticker has a lowercase English word on it.

You would like to spell out the given target string by cutting individual letters from your collection of stickers and rearranging them.

You can use each sticker more than once if you want, and you have infinite quantities of each sticker.

What is the minimum number of stickers that you need to spell out the target? If the task is impossible, return -1.

Example 1:

Input:

["with", "example", "science"], "thehat"

Output:

3

Explanation:

We can use 2 "with" stickers, and 1 "example" sticker.
After cutting and rearrange the letters of those stickers, we can form the target "thehat".
Also, this is the minimum number of stickers necessary to form the target string.

Example 2:

Input:

["notice", "possible"], "basicbasic"

Output:

-1

Explanation:

We can't form the target "basicbasic" from cutting letters from the given stickers.

Note:

  • stickers has length in the range [1, 50].
  • stickers consists of lowercase English words (without apostrophes).
  • target has length in the range [1, 15], and consists of lowercase English letters.
  • In all test cases, all words were chosen randomly from the 1000 most common US English words, and the target was chosen as a concatenation of two random words.
  • The time limit may be more challenging than usual. It is expected that a 50 sticker test case can be solved within 35ms on average.

    题意

    给定一个字符串集合S,以及一个目标字符串T.求使用S中字符串的最小个数,能够满足T需要的字符数。类似于多目标优化的问题(弄清这一类问题如何求解)
    背包问题(变形)
    给定物品的特点
    给定背包的限制
    求最小的物品的数量。

    分析及解答

    参考:(https://discuss.leetcode.com/topic/106368/rewrite-of-contest-winner-s-solution/7)
    • 位图法】因为待匹配串target的数量最多是15个,因此其子集的数量最多有 2^15个,而int类型占用四个字节,能够容纳标识所有target的子集。所以我们可以将target的子集 映射到 int的整型数中。
    • 【int 与 target子集之间的映射关系】将int类型分解为二进制的形式后,有些位置为0,有些位置为1.表明在target中哪些位置的字符是否保留(1表示保留)。
    • 动态规划】dp中存储的是得到子集i,需要的最少的单词的数量。
    class Solution {
        public int minStickers(String[] stickers, String target) {
            int n = target.length(), m = 1 << n; // if target has n chars, there will be m=2^n-1 subset of characters in target
            int[] dp = new int[m];
            for (int i = 0; i < m; i++) dp[i] = Integer.MAX_VALUE; // use index 0 - 2^n-1 as bitmaps to represent each subset of all chars in target
            dp[0] = 0; // first thing we know is : dp[empty set] requires 0 stickers,
            for (int i = 0; i < m; i++) { // for every subset i, start from 000...000。(起点这里很重要,因为大的集合往往依赖于小的集合)
                if (dp[i] == Integer.MAX_VALUE) continue;
                for (String s : stickers) { // try use each sticker as an char provider to populate 1 of its superset, to do that:
                    int sup = i;//关键代码(下面:在i上面加入一个单词后的效果)
                    for (char c : s.toCharArray()) { // for each char in the sticker, try apply it on a missing char in the subset of target
                        for (int r = 0; r < n; r++) {
                            if (target.charAt(r) == c && ((sup >> r) & 1) == 0) {  //如果target中包含字符c , 并且sup中相应位置没有c。
                                sup |= 1 << r;//在sup中相应位置,加入c,形成新的集合。
                                break;
                            }
                        }
                    }
                   // after you apply all possible chars in a sticker, you get an superset that take 1 extra sticker than subset
                   // would take, so you can try to update the superset's minsticker number with dp[sub]+1;
                    dp[sup] = Math.min(dp[sup], dp[i] + 1);//判断是否需要替换原来sup中的值。
                }
            }
            return dp[m - 1] != Integer.MAX_VALUE ? dp[m - 1] : -1;
        }
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值