2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > 剑指offer--最长不含重复字符的子字符串and丑数问题

剑指offer--最长不含重复字符的子字符串and丑数问题

时间:2019-05-19 06:48:21

相关推荐

剑指offer--最长不含重复字符的子字符串and丑数问题

题目1:

请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。

示例 1:

输入: "abcabcbb"

输出: 3

解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

思路一:这里我是有两个思路的,第一次写的时候想着直接暴力列出所有的子字符串,应该也可以通过,但是事实证明会超时,主要是时间复杂度太高了,首先暴力列出所有的子字符串都已经有了O(N^2)的时间复杂度,后面判断是否含有重复还要花费O(N)的复杂度,不通过也很正常,不过这里还是把代码贴过来,用来学习找到所有的子字符串又是有点帮助的。

代码1:

class Solution:def lengthOfLongestSubstring(self, s: str) -> int:超时if s=="":return 0result=[]LengthList=[]#x+1表示子串的长度,下面的i是依次滑动来切字符串for x in range(len(s)):for i in range(len(s)-x):result.insert(0,s[i:i+x+1]) def isrep(s):a=set(s)if len(a)==len(s):return False#没有重复return True#有重复for item in result:if not isrep(item):return len(item)break

思路二:真正的思路还是要想方法降低时间复杂度,这里采用双指针加上哈希表来降低复杂度,循环完整个字符串。首先ij肯定都是在字符串的开头的,然后j开始遍历整个字符串,将遍历过的s[j]存入到哈希表中,对应的值是当前访问j的索引。如果下次又碰到了相同的字符串,那就可以在哈希表中检测到它,将i指针的位置修改为哈希表中的上一次s[j]的索引,这样就能确保i+1到j(当前的索引位置)中间是没有重复元素的,每次还将res(存储结果的值)和当前的j-i相比,最后得到最大长度。

代码中也有注释

代码2:

class Solution:def lengthOfLongestSubstring(self, s: str) -> int:#上面一种方法的时间复杂度太高,运行超时,想办法降低时间复杂度,双指针加哈希表,判断是否重复并即使更新左指针#我们可以使用哈希表来记录上一次访问该字符的索引,通过判断哈希表中是否有该字符来更新左指针的位置#不断的更新左指针i,因为如果一个字符出现了第二次,i就要换为最新的索引值,这样才能确保i+1到j的范围内是没有重复字符的#然后不断的更新res结果,res和j-i一直不同的比较#i的初值设为-1,不影响j-i的值dic,i,res={},-1,0#通过j遍历循环字符串for j in range(len(s)):if s[j] in dic:i=max(i,dic[s[j]])#更新左指针i值到不重复的位置#如果不在那就正常的遍历,存值dic[s[j]]=jres=max(res,j-i)return res

题目二丑数:

我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。

示例:

输入: n = 10

输出: 12

解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。

思路:加入现在知道了n之前的丑数,那如果我们想要找到n+1个丑数,必然是前面的n个丑数中的某个数乘2或3或5得到的,也可以表示为xa*2,xb*3,xc*5,abc索引的大小未知但是都是前面丑数的索引。所有的丑数肯定是前面的丑数分别乘2,3,5得到的,那就是每个数都要乘2或者3或者5,但是如果从第一个丑数都每个数乘三个这样算的话,加入我们从丑数1开始,现在要计算第7个丑数,那丑数1后面得到的乘积就是2,3,5,但是2,3,5都比6小,这就造成了混乱。所以这里我们使用三个指针a代表是乘2,b代表是乘3,c代表是乘5,也可以理解为a之前的那些丑数都已经没有了乘2的机会,但是可能有乘3或者5的机会,这样就不会造成混乱,每个数都有三个机会,用完一个机会该机会对应的指针就指向下一个数,确保不会发生混乱。

代码:

class Solution:def nthUglyNumber(self, n: int) -> int:#丑数n肯定是前面所有的丑数中的xa*2,xb*3,xc*5所得到的(abc是不分大小的),下一个丑数肯定是三个数的最小值#这里采用动态规划,三个指针,初始都是从第一个丑数开始的,在n之前的数,每个数都有机会分别乘2,3,5#但是我们还不能直接每个数从1234568就开始分别乘2,3,5,如果这样的话,丑数1分别乘这三个数#就得到2,3,5,丑数有数又是他们三个中的最小值,这样的话就和后面真实的丑数比较的时候造成#混乱;#所以我们还是给每个丑数分别乘三个指针(a,b,c)的三次机会,只不过a-1之前的数表示已经没有 #机会和a相乘了,n+1个丑数是xa*2,xb*3,xc*5的最小值,如果是xa*2的话,那a对应的指针就要向 #后移一位,确保a前面的数都已经用过了乘2的机会,这样分别相乘,不分abc的大小,可以确保乘出 #来的三个数必然有一个是满足条件的,不会造成混乱#动态规划列表dp表示当前的丑数集合,dp[n]表示第n+1个丑数dp=[1]*n# dp[0]=1#第一个丑数是1a,b,c=0,0,0#指针都从第一个丑数开始#从第二个丑数开始算for i in range(1,n):num1,num2,num3=dp[a]*2,dp[b]*3,dp[c]*5dp[i]=min(num1,num2,num3)#找到下一个丑数,是这三个乘积的最小值,但是abc的大小顺序是不一定的#找到对应的是哪个指针乘积得到的,相应的位置加一,注意这里的if 判断只能使用三个if,因为可能存在两个指针同时都得到dp[i]的情况#为了避免重复,如果同时满足条件那就同时加1if dp[i]==num1:a+=1if dp[i]==num2:b+=1if dp[i]==num3:c+=1#返回dp[n-1]return dp[-1]

力扣

具体的题解可以看力扣题库里面的k神解释,附带ppt

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。