问题描述:
数学课上,老师出了一道题目,要求在给定的一些数字中找出两个数,使得它们的和为N,前提是这些数据中保证有答案,并且只有一个答案。例如给定5个数字:3、4、5、7、10,从中选择两个数使它们的和为11,可以选择4和7,这个问题该如何解决呢?
def twosum(num,target):
res=[]
newsum=num[:]
newsum.sort()
left=0
right=len(newsum)-1
while left<right:
if newsum[left]+newsum[right]==target:
for i in range(len(num)):
if newsum[left]==num[i]:#newsum是有序数组,num是原始数组
res.append(i)#将下标加入结果集
break
for i in range(len(num)-1,-1,-1):
if newsum[right]==num[i]:
res.append(i)#将下标加入结果集
break
res.sort()
break
elif newsum[left]+newsum[right]>target:
right-=1
elif newsum[left]+newsum[right]<target:
left+=1
return(res[0]+1,res[1]+1)
print(twosum([3,4,5,7,10],11))
#输出:(2,4)
def twosum(num,target):
dict={}
for i in range(len(num)):
m=num[i]
if target-m in dict:
return(dict[target-m]+1,i+1)
dict[m]=i
print(twosum([3,4,5,7,10],11))
#输出:(2,4)
在第一种算法的基础上,我们研究更加高效的算法,哈希函数
是怎样解决这个问题的。
数据有序
,接着为了寻找答案,左右指针在不停地移动原始数组
中寻找这两个数据的位置给定两个字符串,一个是单词模式字符串,另一个是目标字符串,检查目标字符串中单词出现的规律是否符合单词模式字符串中的规律。
注意:
映射关系分为一对一关系,一对多关系和多对多关系。
寻找映射关系的问题本质上也是查找问题,既然是查找问题,考虑使用哈希算法。
def wordpattern(wordpattern,input):
word=input.split(' ')
if len(word)!=len(wordpattern):#长度不等
return False
hash={}#记录模式字符串和目标字符串的对应关系
used={}#记录目前已经使用过的字符串
for i in range(len(wordpattern)):
if wordpattern[i] in hash:#第二次出现该映射关系,检查是否一致
if hash[wordpattern[i]]!=word[i]:
return False
else:#首次出现映射关系
if word[i] in used:#检查该单词是否使用过
return False
hash[wordpattern[i]]=word[i]#若首次出现,加入哈希表
used[word[i]]=True
return True
print(wordpattern([1,2,1,2],"a b a a"))
#输出:False
问题描述:
小明在和小朋友玩猜数字游戏,这个游戏的玩法是这样的。一个人写下数字让另外一个人猜,当每次答题方猜完之后,出题方会给答题方一个提示,告诉他刚才有多少位数字和确切位置都猜对了(称为"Bulls",公牛),还有多少位数字猜对了但位置不对(称为”Cows",奶牛)。答题方将会根据出题方的提示继续猜,直到猜出秘密数字位置。
注意:
def gethint(secret,guess):#参数类型是字符串
secret_list={}
guess_list={}
A=0
B=0
for i in range(len(secret)):
if secret[i]==guess[i]:
A+=1
else:
if secret[i] in secret_list:
secret_list[secret[i]]=secret_list[secret[i]]+1
else:
secret_list[secret[i]]=1
if guess[i] in guess_list:
guess_list[guess[i]]=guess_list[guess[i]]+1
else:
guess_list[guess[i]]=1
for digt in secret_list:#按照出现的字符依此查找
if digt in guess_list:
B+=min(secret_list[digt],guess_list[digt])
return str(A)+"A"+str(B)+"B"#字符串拼接
print(gethint("2019","9021"))
#输出:1A3B
问题描述:
英语课上,英语老师为了让同学们掌握常见的词根来帮助理解和记忆单词,发明了一个游戏。这个游戏的玩法是这样的,给定一个有许多词根组成的字典和一个句子,你需要将句子中的所有继承词用词跟替换掉。如果继承词中有许多形成它的词语,则用最短的词根替换它。例如,字典为[“cat”,“bat”,“rat”],句子为”The cattle was ratted by the battery",经过替换,输出句子为“the cat was rat by the bat"。试写一个程序来解决这个问题。
该代码虽然能够解决问,但效率太低,对于每一个词根,需要在所有单词中截取相应位数的子字符串,加入词根的量很多或者单词的数量很多,双重循环
的效率很低。在这个过程中,可以把用单词去匹配词根的过程通过哈希
来优化。
def replacewords(dict,sentence):
sentence=sentence.split()
for item in dict:
for i in range(len(sentence)):
n=len(item)
if item==sentence[i][:n]:
sentence[i]=item
return ' '.join(sentence)
print(replacewords(["cat","bat","rat"],"the cattle was rattled by the battery"))
每个词根的首字母为键
,把每一个词放到该键对应一个的值里,这里的值是一个集合,同时记录下集合里最大词根的长度
。enumerate()函数
来遍历句子,它会把索引
放到第一个变量,把元素
放到第二个变量。collections类中的defaultdict()方法
来为字典提供默认值。import collections
def replacewords(dict,sentence):
d=collections.defaultdict(set)
s=collections.defaultdict(int)
sentence=sentence.split()#句子的列表
for w in dict:
print (w[0])#词根的首字母
d[w[0]].add(w)#添加到集合中,词根的首字母作为键,词跟为值(集合,可以多个)存入
s[w[0]]=max(s[w[0]],len(w))#所有词根中最大的长度
for i,w in enumerate(sentence):
for j in range(s[w[0]]):#取相关词根的最大长度
if w[:j+1] in d[w[0]]:#判断所找单词是否在词根集合里
sentence[i]=w[:j+1]
break
return ' '.join(sentence)
print(replacewords(["cat","bat","rat"],"the cattle was rattled by the battery"))