为什么练习算法很关键?不要像我刚开始解决问题时那样天真。尽管我认为偶尔破解一些算法很有趣,但我从来没有花太多时间练习它,只是为了解决问题而不是别的,也许有时解决问题马马虎虎,但不明白为什么。对我自己来说,我一直在想,说到底,整天解决一个算法有点太生硬了,在实际的日常工作环境中没有实际用处,也不会给我带来什么任何事情从长远来看有多少好处。“知道如何解决算法会让你在求职过程中获得竞争优势”但事实上,作为一名程序员,每天的工作中都会出现复杂的问题,大公司必须找到一个标准化的流程来收集求职者来解决问题洞察力和对细节的关注能力。这意味着知道如何解决算法会给你在求职过程中带来竞争优势,因为即使是鲜为人知的公司也倾向于采用类似的评估方法。在我开始更加一致地解决算法后不久,我发现有大量资源可供练习,学习解决这些问题的最有效策略,并为面试做好心理准备。(如牛客网、力扣、领口等)除了练习面试题外,这些网站通常会按公司对算法进行分组,嵌入活跃的博客,让人们分享面试经验的详细总结,有时甚至会提供模拟面试题作为计划的高级部分。如果您一开始真的很难解决问题,请不要失望,这是完全正常的。即使是非常有经验的Python程序员,如果没有足够的训练,也会发现很多算法很难在短时间内解决。也不要失望,如果您的面试没有达到您的预期,那么您才刚刚开始处理算法。有些人会连续几个月每天准备解决一些问题并定期排练,然后才能完成面试。为了在培训过程中为您提供帮助,下面我选择了10种在电话编程面试中反复出现的算法(主要围绕字符串操作和数组)。这些问题的程度主要是比较简单,但是很容易遇到,所以请把它们作为一个很好的起点。字符串运算数反转#给定一个整数,返回反转后的数#该数可以是负数也可以是整数defsolution(x):string=str(x)ifstring[0]=='-':returnint('-'+string[:0:-1])else:returnint(string[::-1])print(solution(-289))print(solution(123))Output:-132543averagewordlength#foragivensentences,返回平均字长。#记得先去掉标点符号。sentence1="Hiall,mynameisTom...我来自澳大利亚。"sentence2="我需要努力学习更多关于Python的算法!"defsolution(sentence):forpin"!?',;.":sentence=sentence.replace(p,'')words=sentence.split()returnround(sum(len(word)forwordinwords)/len(words),2)print(solution(sentence1))print(solution(sentence2))Output:4.24.08一个需要你应用的算法使用字符串的一些简单计算非常普遍,因此熟悉.replace()和.split()等方法很重要,在这种情况下,它们帮助我删除不需要的字符并创建长度易于测量和求和的单词列表.AddString#给定两个以字符串表示的非负整数num1和num2,返回num1和num2的和。#不得使用任何内置的BigInteger库或将输入直接转换为整数。num1='364'num2='1836'#Approach1:defsolution(num1,num2):eval(num1)+eval(num2)returnstr(eval(num1)+eval(num2))print(solution(num1,num2))#Approach2#给定一个长度为1的字符串,ord()函数在参数为unicode对象时返回一个表示字符#的Unicode代码点的整数,或者在参数为8位字符串值时返回一个字节。defsolution(num1,num2):n1,n2=0,0m1,m2=10**(len(num1)-1),10**(len(num2)-1)foriinnum1:n1+=(ord(i)-ord("0"))*m1m1=m1//10foriinnum2:n2+=(ord(i)-ord("0"))*m2m2=m2//10returnstr(n1+n2)print(解(num1,num2))Output:22002200我发现这两种方法同样好:第一种是简洁的,使用直观的eval()方法动态评估基于字符串的输入,第二种巧妙地使用ord()函数重构这两种方法通过通过字符的Unicode代码点将字符串作为实际数字。如果我真的必须在两者之间做出选择,我可能会选择第二种方法,因为它一开始看起来更复杂,但在解决需要更高级字符串操作的算法时通常很方便。查找第一个唯一字符#给定一个字符串,找到其中的第一个非重复字符并返回其索引。#如果不存在则返回-1。#Note:所有输入字符串都已小写。#Approach1defsolution(s):frequency={}foriins:ifinotinfrequency:frequency[i]=1else:frequency[i]+=1foriinrange(len(s)):iffrequency[s[i]]==1:return返回-1print(solution('alphabet'))print(solution('barbados'))print(solution('crunchy'))print('---')#Approach2importcollectionsdefsolution(s):#buildhashmap:characterandhowoftenitappearscount=collections.Counter(s)#<--givesbackadictionarywithwordsoccurrencecount#Counter({'l':1,'e':3,'t':1,'c':1,'o':1,'d':1})#findtheindexforidx,chinenumerate(s):ifcount[ch]==1:returnidxreturn-1print(solution('alphabet'))print(solution('barbados'))print(solution('crunchy'))输出:121---121也在这种情况下,提供了两种可能的解决方案,我想如果你不熟悉算法,第一种方法看起来会更熟悉,因为它是一个从空字典开始的简单计数器。但是,从长远来看,理解第二种方法会对你有更大帮助,因为在这个算法中,我不是自己构建字符计数器,而是使用collection.Counter和enumerate而不是range(len(s)),这可以帮助你识别的特征索引更优雅。validpalindrome#给定一个非空字符串s,你最多可以删除一个字符。判断是否可以做成回文。#字符串只包含小写字母az。s='sadkas'defsolution(s):foriinrange(len(s)):t=s[:i]+s[i+1:]ift==t[::-1]:returnTrue返回==s[::-1]solution(s)Output:True“有效回文”问题是一个真正的经典问题,您可能会在许多不同的情况下一遍又一遍地发现它。在这种情况下,任务是通过删除最多一个匹配其对立字符的字符来检查天气。当s='sadkas'时,函数通过排除'k'返回True,我们得到单词'sadas',这是一个回文。数组单调数组#给定一个整数数组,请判断该数组是否单调。A=[6,5,4,4]B=[1,1,1,3,3,4,3,2,4,2]C=[1,1,2,3,7]defsolution(nums):return(all(nums[i]<=nums[i+1]foriinrange(len(nums)-1))orall(nums[i]>=nums[i+1]foriinrange(len(nums)-1)))print(solution(A))print(solution(B))print(solution(C))Output:TrueFalseTrue这是另一个非常常见的问题,上面提供的解决方案非常优雅,因为它可以写在一行中.一个数组是单调的,当且仅当它是单调递增或单调递减的,并且是一个评估数组。上面的算法使用了all()函数,如果可迭代对象中的所有项都为True,则该函数返回True,否则返回False。如果可迭代对象为空,all()函数也会返回True。移动零#给定一个数组num,编写一个函数将所有零移动到它的末尾,同时保持#non-zero元素的相对顺序。array1=[0,1,0,3,12]array2=[1,7,0,0,8,0,10,12,0,4]defsolution(nums):foriinnums:if0innums:nums.remove(0)nums.append(0)returnnumssolution(array1)solution(array2)输出:[1,3,12,0,0][1,7,8,10,12,4,0,0,0,0]当当您使用数组时,.remove()和.append()方法是无价的盟友。在这个问题中,我使用它们首先删除属于原始数组的每个零,然后将其附加到同一个数组的末尾。填空#给定一个包含None值的数组,用数组中最新的nonNone值填充None值array1=[1,None,2,3,None,None,5,None]defsolution(array):valid=0res=[]foriinnums:ifiisnotNone:res.append(i)valid=ielse:res.append(valid)returnressolution(array1)Output:[1,1,2,3,3,3,5,5]两次解决方案两者都必须包含边缘情况(为简单起见,此处省略)。从表面上看,这是一个易于构建的算法,但您需要牢记您试图通过for循环和if语句实现的目标,并且您应该习惯None值。匹配的词和不匹配的词#给定两个句子,返回出现在一个句子中但不是#anotherword的词数组;返回具有共同单词的单词数组。sentence1='Wearereallypleasedtomeetyouinourcity'sentence2='Thecitywashitbyareallyheavystorm'defsolution(sentence1,sentence2):set1=set(sentence1.split())set2=set(sentence2.split())returnssorted(list(set1^set2)),sorted(list(set1&set2))print(solution(sentence1,sentence2))Output:(['The','We','a','are','by','heavy','hit','in','meet','our','pleased','storm','to','was','you'],['city','really'])是直观的,但该算法利用了一些非常常见的设置操作,如set()、intersection()或&和symmetric_difference()或^,它们对于使您的解决方案更加优雅非常有用。素数数组#给定k个小于n的数,返回其中的素数集合#注:任务是写一个程序打印一个区间内的所有素数。#定义:素数是大于1的自然数,除了1和它本身没有约数。n=35defsolution(n):prime_nums=[]fornuminrange(n):ifnum>1:#allprimenumbersaregreaterthan1foriinrange(2,num):if(num%i)==0:#ifthemodulus==0ismeansthatthenumbercanbedividedbyanumberprecedingitbreakelse:prime_nums.append(num)returnprime_numssolution(n)Output:[2,3,5,7,11,13,17,19,23,29,31]我想用另一个经典问题来结束这篇文章。如果您熟悉素数定义和模运算,则可以轻松找到解决方案,即通过valleyrange(n)(模运算)。结论在这篇文章中,我分享了面试中常见问题的10个Python算法的解决方案。如果您正在准备与一家知名技术公司的面试,本文是您在继续处理更复杂的问题之前熟悉常见算法模式的一个很好的起点。另请注意,本文中提供的练习(及其解决方案)是对按扣和领扣存在的问题的部分重新解释。我远非该领域的专家,因此我提供的解决方案仅供参考。
