Welcome to Subscribe On Youtube
Formatted question description: https://leetcode.ca/all/1153.html
1153. String Transforms Into Another String
Level
Hard
Description
Given two strings str1
and str2
of the same length, determine whether you can transform str1
into str2
by doing zero or more conversions.
In one conversion you can convert all occurrences of one character in str1
to any other lowercase English character.
Return true
if and only if you can transform str1
into str2
.
Example 1:
Input: str1 = “aabcc”, str2 = “ccdee”
Output: true
Explanation: Convert ‘c’ to ‘e’ then ‘b’ to ‘d’ then ‘a’ to ‘c’. Note that the order of conversions matter.
Example 2:
Input: str1 = “leetcode”, str2 = “codeleet”
Output: false
Explanation: There is no way to transform str1 to str2.
Note:
1 <= str1.length == str2.length <= 10^4
- Both
str1
andstr2
contain only lowercase English letters.
Solution
First consider some base cases. If either str1
or str2
is null
, return false
. If str1
and str2
are the same, return true
. Otherwise, if all lowercase letters occur in str2
, return false
since conversions will definitely cause duplicates in str1
and make it impossible to transform str1
into str2
.
Then loop over str1
and for each letter, store the indices in str1
. If there exists two indices such that the letters at the two indices in str1
are the same but the letters at the two indices in str2
are different, return false
since it is impossible to convert two same letters into two different letters. If no such indices exist, return true
.
-
class Solution { public boolean canConvert(String str1, String str2) { if (str1 == null || str2 == null || str1.length() != str2.length()) return false; if (str1.equals(str2)) return true; Set<Character> set = new HashSet<Character>(); int length = str1.length(); for (int i = 0; i < length; i++) set.add(str2.charAt(i)); if (set.size() == 26) return false; Map<Character, List<Integer>> map = new HashMap<Character, List<Integer>>(); for (int i = 0; i < length; i++) { char c = str1.charAt(i); List<Integer> list = map.getOrDefault(c, new ArrayList<Integer>()); list.add(i); map.put(c, list); } for (char c = 'a'; c <= 'z'; c++) { List<Integer> list = map.getOrDefault(c, new ArrayList<Integer>()); int size = list.size(); for (int i = 1; i < size; i++) { int prevIndex = list.get(i - 1), currIndex = list.get(i); if (str2.charAt(prevIndex) != str2.charAt(currIndex)) return false; } } return true; } }
-
class Solution { public: bool canConvert(string str1, string str2) { if (str1 == str2) { return true; } int cnt[26]{}; int m = 0; for (char& c : str2) { if (++cnt[c - 'a'] == 1) { ++m; } } if (m == 26) { return false; } int d[26]{}; for (int i = 0; i < str1.size(); ++i) { int a = str1[i] - 'a'; int b = str2[i] - 'a'; if (d[a] == 0) { d[a] = b + 1; } else if (d[a] != b + 1) { return false; } } return true; } };
-
class Solution: def canConvert(self, str1: str, str2: str) -> bool: if str1 == str2: return True if len(set(str2)) == 26: return False d = {} for a, b in zip(str1, str2): if a not in d: d[a] = b elif d[a] != b: return False return True
-
func canConvert(str1 string, str2 string) bool { if str1 == str2 { return true } s := map[rune]bool{} for _, c := range str2 { s[c] = true if len(s) == 26 { return false } } d := [26]int{} for i, c := range str1 { a, b := int(c-'a'), int(str2[i]-'a') if d[a] == 0 { d[a] = b + 1 } else if d[a] != b+1 { return false } } return true }