暑假算法刷题日记 Day 9

今天我们主要刷的是哈希表相关的题目

041 、有效的字母异位词

题目描述

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。

注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。

思路1

我一开始用的哈希表来做,思路是用map记录s中所有的字符及其个数,遍历t字符串,在map中给每个遍历到的字符减一,如果某个字符减为0就remove。如果遍历到的字符不在map中,说明某个字符在两个字符串中的个数是不一样的,return false,最后遍历完成,如果map中还有元素,说明不同,如果没有,说明二者是异位词

class Solution {
   public boolean isAnagram(String s, String t) {
       Map<Character,Integer> mps = new HashMap<>();
       int lens=s.length();
       int lent=t.length();
       for(int i=0;i<lens;i++){
           mps.put(s.charAt(i),mps.getOrDefault(s.charAt(i),0)+1);
       }
       for(int i=0;i<lent;i++){
           if(mps.get(t.charAt(i))!=null){
               mps.put(t.charAt(i),mps.get(t.charAt(i))-1);
               if(mps.get(t.charAt(i))==0)mps.remove(t.charAt(i));
           }else return false;
       }
       if(mps.isEmpty())return true;
       else return false;
       
   }
}

思路2

后来看题解发现还有一种更简洁的思路,就将字符串的字符排序,如果是异位词,排序后肯定是相同的字符串

class Solution {
   public boolean isAnagram(String s, String t) {
       char[] sc = s.toCharArray();
       Arrays.sort(sc);
       
       char[] tc = t.toCharArray();
       Arrays.sort(tc);
       
       if(Arrays.equals(sc,tc))return true;
       else return false;
       
   }
}

042 、赌金信

题目描述

给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。

如果可以,返回 true ;否则返回 false 。

magazine 中的每个字符只能在 ransomNote 中使用一次。

思路

这个题就更适合用哈希表来做了,我们可以和刚才相同的思路
我一开始用的哈希表来做,思路是用map记录s中所有的字符及其个数,遍历t字符串,在map中给每个遍历到的字符减一,如果某个字符减为0就remove。如果遍历到的字符不在map中,说明某个字符在两个字符串中的个数是不一样的,return false,最后遍历完成,如果map中还有元素,说明不同,如果没有,说明二者是异位词
不一样的地方是,最后的map可以不是空的

class Solution {
   public boolean canConstruct(String ransomNote, String magazine) {
       Map<Character,Integer> mps = new HashMap<>();
       int lens=magazine.length();
       int lent=ransomNote.length();
       for(int i=0;i<lens;i++){
           mps.put(magazine.charAt(i),mps.getOrDefault(magazine.charAt(i),0)+1);
       }
       for(int i=0;i<lent;i++){
           if(mps.get(ransomNote.charAt(i))!=null){
               mps.put(ransomNote.charAt(i),mps.get(ransomNote.charAt(i))-1);
               if(mps.get(ransomNote.charAt(i))==0)mps.remove(ransomNote.charAt(i));
           }else return false;
       }
       return true;
       
   }
}

043 、字母异位词分组

题目描述

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。

字母异位词 是由重新排列源单词的所有字母得到的一个新单词。

示例 1:

输入: strs = [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”]
输出: [[“bat”],[“nat”,“tan”],[“ate”,“eat”,“tea”]]

思路

这个题我一开始也是用哈希表来做的,不过时间复杂度太高了,没办法ac。看了题解后使用排序+哈希表,还是很巧妙的。
以字符串排序后的string作为key,以所有排序后为string的字符串的list作为value

class Solution {
   public List<List<String>> groupAnagrams(String[] strs) {
       Map<String,List<String>> map=new HashMap<>();
       for(String s:strs){
           char[] c=s.toCharArray();
           Arrays.sort(c);
           String temp=new String(c);
           List list=map.getOrDefault(temp,new ArrayList<String>());
           list.add(s);
           map.put(temp,list);
       }
       List<List<String>> ans=new ArrayList<List<String>>(map.values());
       return ans;
   }
}

044 、找到字符串中所有字母异位词

题目描述

给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。

思路

我一开始使用哈希表来做的,这样的复杂度是O(m*n),会超时间

for(int i=0;i<lens-lenp+1;i++){
    if(isAnagram( s.substring(i,i+lenp),p)){
       ans.add(i);
       }
 }

看完答案后发现要用滑动窗口来做,这么明显的滑动窗口我竟然没看出来真是罪过啊

class Solution {
   int[] pcnt=new int[26];
   int[] cnt=new int[26];
   public boolean check(){
       for(int i=0;i<26;i++){
           if(cnt[i]!=pcnt[i])return false;
       }
       return true;
   }
   public List<Integer> findAnagrams(String s, String p) {
       for(int i=0;i<p.length();i++)pcnt[p.charAt(i)-'a']++;
       List<Integer> ans=new ArrayList<Integer>();
       int lens=s.length();
       int lenp=p.length();
       int l=0,r=0;
       for(r=0;r<lens;r++){
           cnt[s.charAt(r)-'a']++;

           while(r-l+1==lenp){
               if(check())ans.add(l);
               cnt[s.charAt(l++)-'a']--;
           }
       }
       return ans;
   
}}

结语

最近刚开始用java刷算法题,好不习惯啊,好多操作细节需要重新学习,哎
请添加图片描述

  • 16
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值