我是码春儿,将不定期分享面试中遇到的及力扣周赛中的题目,后续会有更多职业中的技术与心得体会分享,欢迎大家关注,让我们一起面向代码,春暖花开!
题目描述
给定字母组合(无重复字母)和单词字典,求单词字典中,所有能够组成字母组合的单词对。
输入:
letters:一个字母组合,如 ‘KNEATOW’
dictionary:一个单词字典,如{‘ATE’, ‘EAT’, ‘TEA’, ‘KNOW’, ‘CODE’}
输出:字典中所有能够组成字母组合的单词对,要求不重不漏示例:
输入:
letters: ‘KNEATOW’
dictionary:{‘ATE’, ‘EAT’, ‘TEA’, ‘KNOW’, ‘CODE’}
输出:
[[‘EAT’, ‘KNOW’], [‘ATE’, ‘KNOW’], [‘TEA’, ‘KNOW’]]
解析
单词集合的整数表示
本题的难点在于找到一种合适的方式来表示单词和字母集合,这个表示应该满足以下几个条件:
- 容易计算两个单词是否能够不重不漏地组成所需字母集合
- 在给出字母集合与一个单词时,能快速计算所需的互补单词
- 能快速判断一种字母集合是否在字典中
*存储及调用尽可能高效
基于这几点需求,我们采用二进制来编码,并使用字典来存储候选字母。
二进制操作回顾:12 与 10 的二进制表示分别为1100与1010
- 与操作&:
12 & 10 = 8 (1000) - 或操作|:
12 | 10 = 14 (1110) - 异或操作^:
12 ^ 10 = 6 (110)
由于不需考虑重复字母,我们可以先将字母集合、单词均转化为长度为26的01序列,1表示该位置的字母出现,0则表示未出现。
如vxy包含’v’, ‘x’, 'y’这3个字母,在字母表中排在第22, 24, 25位,
因此可表示为01序列:00000000000000000000010110
转化为10进制为:22
需要注意的是这种转化方式的本质是将每一种单词集合表示为唯一的整数,而非单词序列,即无法考虑顺序,对于yxv、xvy,其整数表示同样为22,因此除了整数以外,还需保留原始单词。
算法思路
- 从字典中筛选出候选单词,其必须不包含重复字母,且所有字母是letters中字母的子集。
- 将得到的候选单词存储为dict,其中key为单词的整数表示,value为该整数对应的所有单词列表(使用字典是为了快速判断一个单词是否在候选单词集中),如:{35651648: [‘ATE’, ‘EAT’, ‘TEA’], 38920: [‘KN