leetcode 383. Ransom Note(赎金票据)

本文探讨了一个具体的字符串构造问题,即如何判断一个字符串(ransomNote)是否能通过另一个字符串(magazine)中的字母组成,同时确保magazine中的每个字母仅被使用一次。文章提供了两种解决方案:一种是通过统计两个字符串中各字母出现的频率进行比较;另一种则是遍历ransomNote中的字符,并在magazine中寻找对应的字符,同时避免重复使用已找到的字符。

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

Given two strings ransomNote and magazine, return true if ransomNote can be constructed by using the letters from magazine and false otherwise.

Each letter in magazine can only be used once in ransomNote.

Example 1:

Input: ransomNote = “a”, magazine = “b”
Output: false
Example 2:

Input: ransomNote = “aa”, magazine = “ab”
Output: false
Example 3:

Input: ransomNote = “aa”, magazine = “aab”
Output: true

题目是赎金,但是好像和赎金也没啥关系,就是字符串。
ransomNote中的字母要由magazine中的字母组成。
magazine中每个字母只能用一次。

思路:

说白了就是判断ransomNote是不是magazine的子串,即由magazine中的字母组成,不限制顺序。
但是magazine中每个字母只能用一次。

英文小写字母总共就26个,只要统计每个字母出现的次数,
ransomNote中每个字母出现的次数只要小于magazine中对应字母的次数,就为true.

public boolean canConstruct(String ransomNote, String magazine) {
    int nr = ransomNote.length();
    int nm = magazine.length();
    int n = Math.max(nr, nm);
    int[] cntr = new int[26];
    int[] cntm = new int[26];
    
    for(int i = 0; i < n; i ++) {
        if(i < nr) cntr[ransomNote.charAt(i)-'a'] ++;
        if(i < nm) cntm[magazine.charAt(i)-'a'] ++;
    }
    
    for(int i = 0; i < 26; i++) {
        if(cntr[i] > cntm[i]) return false;
    }
    return true;
}

还有一种方法,不统计次数,直接依次查找,找不到就返回false.
由于magazine中每个字母只能用一次,一旦这个字母用过就不能再用,假设这个字母的index为 i,
下次再找这个字母,只能从i + 1开始找。

保存每个字母当前找到的index, 下次从index + 1开始找这个字母。

public boolean canConstruct(String ransomNote, String magazine) {
    int[] startIdx = new int[26];
    
    for(char cur : ransomNote.toCharArray()) {
        int index = magazine.indexOf(cur, startIdx[cur - 'a']);
        if(index == -1) return false;
        startIdx[cur-'a'] = index+1;
    }
    return true;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

蓝羽飞鸟

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

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

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

打赏作者

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

抵扣说明:

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

余额充值