383. Ransom Note

来源:互联网 发布:弘历筹码分布指标源码 编辑:程序博客网 时间:2024/05/21 17:41

1.题目描述

Given an arbitrary ransom note string and another string containing letters from all the magazines, write a function that will return true if the ransom note can be constructed from the magazines ; otherwise, it will return false.

Each letter in the magazine string can only be used once in your ransom note.

note

You may assume that both strings contain only lowercase letters.

canConstruct("a", "b") -> falsecanConstruct("aa", "ab") -> falsecanConstruct("aa", "aab") -> true

2.分析

   这种字符串匹配的算法题,最容易想到的是O(n^2)时间复杂度的双层for循环的字符比对算法,首先不说时间复杂度的要求,就单纯从本题来讲,真的需要那么复杂的匹配吗?根据题目大意是,前一个字符串能不能根据后一个字符串构造出来,并没有限制字符在字符串中出现的顺序。所以只要保证后一个字符串中都包含有前一个字符串中所有字符,就能保证后一个字符串能够构造出前一个字符串,而且前提条件是字符串中只包含小写字符。这样分析下来,解题就很简单,我们只需要使用一定的空间开销就能降低时间上的开销。

    我们创建一个长度为26的int数组,用于统计后一个字符串中每一个字符出现的次数,然后遍历前一个字符串的字符,根据int数组存值判断是否存在,若不存在,则不能构造。

3.代码实现

    完整实现如下:

public class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
       
        // 边界处理,字符串为空的处理 
        if(ransomNote==null){
            return true;
        }
        if(magazine==null){
            return false;
        }
        
        int[]result = new int[26];
        int len1 = ransomNote.length();
        int len2 = magazine.length();
        
        for(int i=0;i<len2;i++){
            result[magazine.charAt(i)-'a']++; // 统计后一个字符串中每一个出现的字符次数
        }
        for(int j=0;j<len1;j++){
           if(--result[ransomNote.charAt(j)-'a']<0){ // 根据前一个字符串中字符的出现来判断能否构造
               return false;
           }
        }
        return true;
    }
}

4.总结

这题我最开始,没有理解题意,以为要考虑字符出现顺序且出现连续,把问题想得过于复杂,在不考虑时间复杂度为O(n^2)的情况下,实现起来也是各种边界处理,一些情况没有考虑全面等问题。其实看完别人题解,自己再回头看题,发现是自己想复杂了,题目已经大大简化了。所以理解题意真的很重要,其次像类似于这种easy难度题目,大多都采用这种方法。使用辅助空间,既能降低时间开销,又能使代码实现很便捷。无论是怎样的解题途径,还是多总结吧!

原创粉丝点击