题目
如果可以使用以下操作从一个字符串得到另一个字符串,则认为两个字符串 接近 :
- 操作 1:交换任意两个 现有 字符。
- 例如,
abcde -> aecdb
- 操作 2:将一个 现有 字符的每次出现转换为另一个 现有 字符,并对另一个字符执行相同的操作。
- 例如,
aacabb -> bbcbaa
(所有a
转化为b
,而所有的b
转换为a
)
你可以根据需要对任意一个字符串多次使用这两种操作。
给你两个字符串,
word1
和word2
。如果word1
和word2
接近 ,就返回true
;否则,返回false
。
解题思路
- 两种操作可以无限次使用,所以需要对操作1和操作二进行进一步的扩充;
- 操作一:每个字符出现的次数相等即为接近;
- 操作二:字符出现的次数可以一一对应(字符本身不需要一一对应);
- 排除特殊情况即:字符串长度不相等;
- 逐个进行每个操作判断是否接近,统计各字符出现次数;
- 判断字符串之间是否存在未出现的字符;
- 比对字符的次数(与字符本身无关,建议先排序)。
代码展示
class Solution { public boolean closeStrings(String word1, String word2) { int m = word1.length(); int n = word2.length(); if(m != n){ return false; } Map<Character,Integer> data1 = new HashMap<>(); Map<Character,Integer> data2 = new HashMap<>(); //统计每个字符出现的次数 for (int i = 0; i < m; i++){ char ch1 = word1.charAt(i); char ch2 = word2.charAt(i); data1.put(ch1, data1.getOrDefault(ch1, 0) + 1); data2.put(ch2, data2.getOrDefault(ch2, 0) + 1); } List<Integer> list1 = new ArrayList<>(); List<Integer> list2 = new ArrayList<>(); for (Character ch : data1.keySet()){ Integer ch1 = data1.get(ch); Integer ch2 = data2.get(ch); //判断word2中是否不存在该字符,若不存在则返回false if(ch2 == null){ return false; } else if (!ch1.equals(ch2)){ list1.add(ch1); list2.add(ch2); } } if(!list1.isEmpty()) { list1.sort(null); list2.sort(null); for (int i = 0; i < list1.size(); i++) { //包装类对象不能当作int直接划等号,否则会比对失败 if (!Objects.equals(list1.get(i), list2.get(i))) { return false; } } } return true; } }