Understanding isomorphic strings algorithm

后端 未结 4 1248
梦谈多话
梦谈多话 2021-01-27 08:15

I am understanding the following code to find if the strings are isomorphic or not. The code uses two hashes s_dict and t_dict respectively. I am assum

相关标签:
4条回答
  • 2021-01-27 08:37

    One simple example, your code doesn't work on s='ab',t='aa'.

    Basically you have to have both way to be isomorphic. Your code only checked that t can be modified from s, but not the other way around.

    0 讨论(0)
  • 2021-01-27 08:42

    Thinking about it without maps or dictionaries can help you understand:

    def isIso(x,y):
      if len(x) != len(y):
        return False
      for i in range(len(x)):
        count = 0
        if x.count(x[i]) != y.count(y[i]):
          return False
      return True
    
    0 讨论(0)
  • 2021-01-27 08:56

    Here is a solution for Isomorphic String problem in Python:

    Solution #1 (the fastest one):

    def isometric_strings_translate(str1: str, str2: str) -> bool:
        trans = str.maketrans(str1, str2)
        return str1.translate(trans) == str2
    

    Solution #2 (using set):

    def isometric_strings_set(str1: str, str2: str) -> bool:
        return len(set(zip(str1, str2))) == len(set(str1))
    

    Solution #3 (using dictionary):

    def isometric_strings_dict(str1: str, str2: str) -> bool:
        map = {}
        for s1, s2 in zip(str1, str2):
            if map.setdefault(s1, s2) != s2:
                return False
        return True
    

    Here you can view full code.

    0 讨论(0)
  • 2021-01-27 09:02

    This was kind of fun to look at. Just for kicks, here's my solution using itertools.groupby

    from itertools import groupby
    from collections import defaultdict
    
    def get_idx_count(word):
        """Turns a word into a series of tuples (idx, consecutive_chars)
    
        "aabbccaa" -> [[(0, 2), (3, 2)], [(1, 2)], [(2, 2)]]
        """
        lst = defaultdict(list)
        for idx, (grp, val) in enumerate(groupby(word)):
            lst[grp].append((idx, sum(1 for _ in val)))
        return sorted(list(lst.values()))
    
    def is_isomorphic(a, b):
        return get_idx_count(a) == get_idx_count(b)
    
    is_isomorphic('aabbcc', 'bbddcc')  # True
    is_isomorphic('aabbaa', 'bbddcc')  # False
    

    Rather than building the lists, I feel like I could do something more like:

    from itertools import groupby
    from collections import defaultdict
    
    def is_isomorphic(a, b):
        a_idxs, b_idxs = defaultdict(set), defaultdict(set)
        for idx, ((a_grp, a_vals), (b_grp, b_vals)) in enumerate(zip(groupby(a), groupby(b))):
            if sum(1 for _ in a_vals) != sum(1 for _ in b_vals):
                return False
                # ensure sequence is of same length
            if a_grp in a_idxs and b_idxs[b_grp] != a_idxs[a_grp] or\
               b_grp in b_idxs and a_idxs[a_grp] != b_idxs[b_grp]:
                return False
                # ensure previous occurrences are matching groups
            a_idxs[a_grp].add(idx)
            b_idxs[b_grp].add(idx)
            # save indexes for future checks
        return True
    

    But I haven't had a chance to test that whatsoever. It does, however, have the likelihood of exiting early, rather than having to build all the lists and comparing them at the end. It also skips a few sets of sorting that shouldn't be necessary anyway, except that we're pulling from dicts, so bleh. Pretty sure list.sort is faster than saving to to a collections.OrderedDict. I think.

    0 讨论(0)
提交回复
热议问题