算法训练 第二周

一、赎金信

算法训练 第二周_第1张图片
本题给出了两个字符串ransomNote和magazine,需要让我们判断ransomNote中的字符能不能由magazine中的字符构成,也就是说我们需要将所有ransomNote中的字符找到一个在magazine中与这个字符相同的字符,且每个字符只能使用一次,这主要考查了我们对hash表的应用。

1.数组模拟hash表

我们先创建一个大小为26的int数组arr,然后遍历magazine中的每个字符,将每个字符的ascll码值减去97后作为数组arr的下标,将此下标对应的值加一,然后再遍历ransomNote中的字符,将每个字符的ascll码值减去97后作为数组arr的下标,将此下标对应的值减一,如果减一之后这个值小于0那么就说明magazine中没有对应的字符与之匹配,直接返回false,如果遍历完ransomNote就说明它可以由magazine中的字符构成,直接返回true,具体代码如下:

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        int[] arr = new int[26];
        for(int i = 0; i < magazine.length(); i++){
            arr[Integer.valueOf(magazine.charAt(i)) - 97]++;
        }
        for(int i = 0; i < ransomNote.length(); i++){
            arr[Integer.valueOf(ransomNote.charAt(i)) - 97]--;
            if(arr[Integer.valueOf(ransomNote.charAt(i)) - 97] < 0){
                return false;
            }
        }
        return true;
    }
}

复杂度分析

  • 时间复杂度:O(m+n),其中 m 是字符串 ransomNote 的长度,n 是字符串 magazine 的长度。
  • 空间复杂度:O(1),因为本题只需要创建的额外数组大小为26,是常数阶。

2.hashmap

我们也可以用java自带的hashmap来实现这个过程,具体代码如下:

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        HashMap<Character,Integer> map = new HashMap<>();
        for(int i = 0; i < magazine.length(); i++) {
            if(!map.containsKey(magazine.charAt(i))) {
                map.put(magazine.charAt(i),1);
            } else {
                map.put(magazine.charAt(i),map.get(magazine.charAt(i)) + 1);
            }
        }
        for(int i = 0; i < ransomNote.length(); i++) {
            if(map.containsKey(ransomNote.charAt(i)) && map.get(ransomNote.charAt(i)) > 0) {
                map.put(ransomNote.charAt(i),map.get(ransomNote.charAt(i)) - 1);
            } else {
                return false;
            }
        }
        return true;
    }
}
  • 时间复杂度:O(m+n)。
  • 空间复杂度:O(1)。

你可能感兴趣的:(算法,哈希算法)