算法珠玑-变位词的四种解法

本文介绍了如何使用全排列、遍历、排序和哈希表等方法解决判断两个单词是否为变位词的问题,从O(n!)到O(n)的时间复杂度优化过程,探讨了算法优化的可能性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  给定一个英语词典,找出其中所有变位词集合。例如,“pots”、“stops”、和“tops”互为变位词,因为每一个单词都可以通过改变其他单词中字母的顺序得到
  为了将问题简化,我们不需要对比英文词典,判断"otsp"是不是一个合法的单词(这个显然不是),因为这没有太大的意义。因此我们将问题简化为,给定任意两个英文单词word1和word2,判断是否互为变位词。
  这是一个很简单,但是很具有代表性的问题,因为这个问题的解决办法很多,优化空间很大。

暴力破解
  • 首先,我们面对这种题目,如果没有思路,第一个解法就是暴力破解,这也是第一种方法,那么怎么暴力破解呢?答案就是全排列,找出word1组成字母的全排列,判断word2在不在该全排列里面。
# 全排列
#空间复杂度:O(n!),时间复杂度:O(n!)
word1 = 'deposit'
word2 = 'topside'
word3 = 'visited'

res = []
def full_array(word, temp=''):
    if len(word)==0:
        if word not in res:
            res.append(temp)
        return 
        
    for i in range(len(word)):
        temp += word[i]
        full_array(word[:i]+word[i+1:], temp)
        temp = temp[:-1]    
        
def heterotopic_words_full_array(word1, word2):
    if len(word1) != len(word2):
        return 'no'
    full_array(word1)
    return 'yes' if word2 in res else 'no'
遍历
  • 我们接着思考,能不能优化一下?答案也是可以的。我们可以对两个word进行遍历,只要word1的字母出现在word2中,就在word2该字母所在位置进行一次标识,比如置为0,当遍历完成,我们只需要判断word2的所有位置是不是全为0即可。
# 遍历
#空间复杂度:O(n),时间复杂度:O(n^2)
def heterotopic_words_ergodic(word1, word2):
    if len(word1) != len(word2):
        return 'no'    
    word2 = list(word2)
    for c in word1:
        for i in range(len(word2)):
            if c == word2[i]:
                word2[i] = 0
    for c in word2:
        if c != 0:
            return 'no'
    
    return 'yes'

heterotopic_words_ergodic(word1, word2)
排序
  • O(n2)的时间复杂度还是太高了,能不能再优化一下?答案也是可以的。考虑到所有的字母都是按照 ASCII 或者 Unicode 进行编码,所以在内存中,字母对应的其实是一个int型数字(可以用ord(“a”)查看对应数字编码)。也就是说我们可以对两个word进行排序,然后比较两个word是不是相等即可。
# 排序
#空间复杂度:O(n),时间复杂度:O(nlog n)
def heterotopic_words_sort(word1, word2):
    if len(word1) != len(word2):
        return 'no'
    word1 = ''.join(sorted(word1))
    word2 = ''.join(sorted(word2))
    return "yes" if word1==word2 else "no"

heterotopic_words_sort(word1, word3)
排序
  • O(nlogn)的时间复杂度还是有点高了,能不能再优化一下?答案也是可以。考虑到互为变位词的两个单词必然有同样的字母构成,并且相同字母的数量相等,所以我们考虑给每一个字母加上一个标识,每当在word1中遇到,就+1,在word2中遇到,就-1,如果最后遍历一遍之后,该标识对应的value为0,表示该字母在两个单词中的数量是一致的。也就是说,我们需要确定所有字母的value是不是都为0,就能判断两个单词是不是互为变位词。
# 哈希
#空间复杂度:O(n),时间复杂度:O(n)
from collections import defaultdict
def heterotopic_words_hash(word1, word2):
    if len(word1) != len(word2):
        return 'no'
    hash_dict = defaultdict(int)
    for i in range(len(word1)):
        hash_dict[word1[i]] += 1 
        hash_dict[word2[i]] -= 1 
    
    for key in hash_dict.keys():
        if hash_dict[key] != 0:
            return 'no'        
    return 'yes'

heterotopic_words_hash(word1, word3)

  那么时间复杂度到O(n)是不是就到头了呢?我觉得应该不是的,限制程序员的永远是思维,可能过段时间就能提出一种O(log n)的优化方法了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lemon_tttea

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值