字符串映射 --- 同构/异构

简介: 字符串映射 --- 同构/异构

1.有效的字母异位词(242-易)



题目描述:给定两个字符串 st ,编写一个函数来判断 t 是否是 s 的字母异位词(字母相同位置不同)。进阶问题的核心点在于「字符是离散未知的」


示例

输入: s = "anagram", t = "nagaram"
输出: true
输入: s = "rat", t = "car"
输出: false


思路:本题核心是记录出现字母的次数(数组或者hashmap),当两个字符串出现字母类别相同且数量相等,则为异位词。有两种思路:


  • hashmap键值对进行记录是比较经典的方法。
  • 也可以直接用数组记录字符出现的次数。


代码实现

class Solution {
    // hashmap
    public boolean isAnagram1(String s, String t) {
        if (s.length() != t.length()) {
            return false;
        }
        HashMap<Character, Integer> map = new HashMap<>();
        for (char cs : s.toCharArray()) {
            map.put(cs, map.getOrDefault(cs, 0) + 1);
        }
        for (char ct : t.toCharArray()) {
            map.put(ct, map.getOrDefault(ct, 0) - 1);
            if (map.get(ct) == -1) {
                return false;
            }
        }
        return true;
    }
    // 数组计数(推荐)
    public boolean isAnagram(String s, String t) {
        if (s.length() != t.length()) {
            return false;
        }
        // 记录字母出现的次数
        int[] counts = new int[26]; 
        for (char cs : s.toCharArray()) {
            counts[cs - 'a']++;
        }
        for (char ct : t.toCharArray()) {
            counts[ct - 'a']--;
        }
        for (int num : counts) {
            if (num != 0) {
                return false;
            }
        }
        return true;
    }
}


ps:这个比较耗时,hashmap初始容量16,感觉扩容耗时!!


拓展:字母的异位词分组(T49)


思路:如何知道两个单词是异位词?排序或者计数!


  • 排序:将排序后的字符串作为键(先转成字符数组,根据ascii码进行排序)
  • 计数:自定义编码作为键


注意:map的key必须是String类型!不能是字符数组,原因是String重写了HashCode()和equalls()map.values()获取map的所有值。


代码实现:

class Solution {
    // 排序法(对每个字母进行重排序)
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<String, ArrayList<String>> map = new HashMap<>();
        for (String str : strs) {
            char[] chs = str.toCharArray();
            Arrays.sort(chs);
            // 特别注意:要将字符数组转化为字符串,因为String实现了equals和hashCode方法
            String key = String.valueOf(chs);
            if (!map.containsKey(key)) {
                map.put(key, new ArrayList<>());
            }
            map.get(key).add(str);
        }
        return new ArrayList(map.values());
    }
    // 计数法(两个数互为异位词:字母出现的次数相同)
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<String, ArrayList<String>> map = new HashMap<>();
        for (String str : strs) {
            char[] chs = str.toCharArray();
            int[] counts = new int[26];
            for (char c : chs) {
                counts[c - 'a']++;
            }
            // 将字符数组编码为字符串,比如将 [b,a,a,a,b,c] 编码成 a3b2c1
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < 26; i++) {
                if (counts[i] != 0) {
                    sb.append((char)('a' + i));
                    sb.append(counts[i]);
                }
            }
            String key = sb.toString();
            if (!map.containsKey(key)) {
                map.put(key, new ArrayList<>());
            }
            map.get(key).add(str);
        }
        return new ArrayList(map.values());
    }
}


6.同构字符串(205-易)



题目描述如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的。


每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序!。不同字符不能映射到同一个字符上相同字符只能映射到同一个字符上,字符可以映射到自己本身


示例

输入:s = "egg", t = "add"
输出:true
输入:s = "foo", t = "bar"
输出:false


思路:本题映射的关键是每个字符只能映射到一个字符(单映射,即s通过映射可以得到t),且映射位置不能错。解决方案:


  • 常规解法:建立两个hashmap进行映射,如示例中,t 中的字符 a 和 r 虽然有唯一的映射 o,但对于 s 中的字符 o来说其存在两个映射 {a,r},故不满足条件。但这种方法效率比较低。
  • 记录一个字符串上次出现的位置,如果两个字符串中字符上次出现的位置不一致,一定不是同构;否则,更新该字符上次出现的位置。


代码

public boolean isIsomorphic(String s, String t) {
    Map<Character, Character> s2t = new HashMap<Character, Character>();
    Map<Character, Character> t2s = new HashMap<Character, Character>();
    int len = s.length();
    for (int i = 0; i < len; ++i) {
        char x = s.charAt(i), y = t.charAt(i);
        if ((s2t.containsKey(x) && s2t.get(x) != y) || (t2s.containsKey(y) && t2s.get(y) != x)) {
            return false;
        }
        s2t.put(x, y);
        t2s.put(y, x);
    }
    return true;
}
public boolean isIsomorphic(String s, String t) {
    // 记录两个字符串每个字符上一次出现的位置(一共256个字符)
    int[] preIndexOfS = new int[256];
    int[] preIndexOfT = new int[256]; 
    for (int i = 0; i < s.length(); i++) {
        char sc = s.charAt(i), tc = t.charAt(i);
        if (preIndexOfS[sc] != preIndexOfT[tc]) {
            return false;
        }
        // 字符相同,更新位置
        preIndexOfS[sc] = i + 1;
        preIndexOfT[tc] = i + 1;
    }
    return true;
}


7.单词规律(290-易)



题目描述:给定一种规律 pattern 和一个字符串 str ,判断 str 是否遵循相同的规律。


这里的 遵循 指完全匹配,例如, pattern 里的每个字母和字符串 str 中的每个非空单词之间存在着双向连接的对应规律。


示例

输入: pattern = "abba", str = "dog cat cat dog"
输出: true


思路:基本思路与上题相同,创建两个hash表,建立双向映射(字符串和字符之间的映射)。注意:字符串的比较用equals,String对equals进行了重写,实际是比较的内容!


代码

public boolean wordPattern(String pattern, String s) {
    HashMap<Character, String> map1 = new HashMap<>();
    HashMap<String, Character> map2 = new HashMap<>();
    String[] ss = s.split(" ");
    if (pattern.length() != ss.length) {
        return false;
    }
    int i = 0;
    for (char ch : pattern.toCharArray()) {
        if (map1.containsKey(ch) && !map1.get(ch).equals(ss[i]) ||
        map2.containsKey(ss[i]) && !map2.get(ss[i]).equals(ch)) {
            return false;
        }
        map1.put(ch, ss[i]);
        map2.put(ss[i], ch);
        i++;
    }
    return true;
}


相关文章
|
6月前
|
存储 数据中心 云计算
逻辑存储和物理存储各代表什么?区别是什么?
逻辑存储和物理存储各代表什么?区别是什么?
|
29天前
|
自动驾驶 物联网 5G
|
6月前
|
算法 测试技术 C#
【多数组合 数学 字符串】2514. 统计同位异构字符串数目
【多数组合 数学 字符串】2514. 统计同位异构字符串数目
|
6月前
|
C++
同构字符串(C++)
同构字符串(C++)
37 0
|
6月前
【代数学习题3】从零理解数域扩张与嵌入 —— 同构、商环、分裂域与同态映射
【代数学习题3】从零理解数域扩张与嵌入 —— 同构、商环、分裂域与同态映射
318 0
|
监控
数据标准应用(一):落标映射关系
数据标准创建完成后,需要指定其关联的资产对象才能发挥应用价值。数据标准和资产对象的映射关系当前可以通过落标映射规则来管理;生成映射关系后,对象是否遵循了映射到的标准定义则通过落标监控评估来判断。本文为您介绍落标映射关系的分类和管理方式。
1287 0
|
前端开发 程序员 C#
【C#】通过扩展对象的方式,对字符串等数据类型进行数据进一步处理
在本篇文章中,我们讲一起了解下对象扩展的使用 在实际项目开发中,对象扩展使用的场景还是挺多的,比如:需要对时间值进行再处理,或者字符串中的斜杠(/)转为反斜杠(\)
112 0
|
存储 缓存 固态存储
数据混合存储 | 学习笔记
快速学习数据混合存储
数据混合存储 | 学习笔记
ETL(九):同构关联(源限定符转换组件的使用)(五)
ETL(九):同构关联(源限定符转换组件的使用)(五)
ETL(九):同构关联(源限定符转换组件的使用)(五)
ETL(九):同构关联(源限定符转换组件的使用)(二)
ETL(九):同构关联(源限定符转换组件的使用)(二)
ETL(九):同构关联(源限定符转换组件的使用)(二)