1.无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。
示例一:
输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例二:
输入: "bbbbb" 输出: 1 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例三:
输入: "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。本题我的思路是对字符串进行遍历,声明一个tmp空字符串,如果当前遍历字符未在tmp中,则将该字符加入tmp中,若在tmp中,则利用python字符串自带的index函数找到该字符上一次出现的位置,然后将其后面的字符串与当前字符进行拼接,然后继续进行下一个字符的遍历。代码如下:
tmp = '' max_ = 0 for i in xrange(len(s)): if s[i] not in tmp: tmp+=s[i] else: max_ = max(max_,len(tmp)) idx = tmp.index(s[i]) tmp = tmp[idx+1:]+s[i] if i==len(s)-1: max_=max(max_,len(tmp)) return max_
2.最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""。
示例一:
输入: ["flower","flow","flight"] 输出: "fl"
示例二:
输入: ["dog","racecar","car"] 输出: "" 解释: 输入不存在公共前缀。
说明:
所有输入只包含小写字母 a-z 。
本题我的思路用到了两个循环,第一个循环用来遍历第一个字符串的字符,然后将当前遍历到的字符加入到最长公共前缀中,然后内部嵌套一个循环,对余下的字符串进行匹配,如果匹配成功,继续下一个字符的匹配,如果匹配失败,返回当前的最长公共前缀。代码如下:if not strs: return '' tmp = '' for i in xrange(len(strs[0])): tmp+=strs[0][i] for j in xrange(1,len(strs)): if tmp!=strs[j][:i+1]: return tmp[:i] return tmp
3.字符串的排列
给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的排列。
换句话说,第一个字符串的排列之一是第二个字符串的子串。
示例一:
输入: s1 = "ab" s2 = "eidbaooo" 输出: True 解释: s2 包含 s1 的排列之一 ("ba").
示例二:
输入: s1= "ab" s2 = "eidboaoo" 输出: False
注意:
-
1.输入的字符串只包含小写字母
2.两个字符串的长度都在 [1, 10,000] 之间
s1 = [str(s) for s in s1] def qpl(s,start,end): tmp = [] if start == end: tmp.append(''.join(s)) return tmp for i in range(start,end+1): s[i],s[start]=s[start],s[i] tmp += qpl(s,start+1,end) s[i],s[start]=s[start],s[i] return tmp li = qpl(s1,0,len(s1)-1) while li: tmp = li.pop() if tmp in s2: return True return False但是这种方法问题有点大,实现需要的空间复杂度和时间复杂度都相当高,其实我们并不需要遍历出每一种排列的结果,我们只需要知道这个字符串中,有多少种字符,以及每一个字符包含多少个就行了。那这个就相当简单了。代码如下:
d1= {} for x in s1: d1[x]=d1.get(x,0)+1 l1 = len(s1) l2 = len(s2) d2 = {} for x in s2[:l1]: d2[x]=d2.get(x,0)+1 if d2==d1: return True else: for i in xrange(l2-l1): d2[s2[i]]=d2.get(s2[i])-1 if d2.get(s2[i])==0: d2.pop(s2[i]) d2[s2[i+l1]]=d2.get(s2[i+l1],0)+1 if d1==d2: return True return False
4.字符串相乘
给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。
示例一:
输入: num1 = "2", num2 = "3" 输出: "6"
示例二:
输入: num1 = "123", num2 = "456" 输出: "56088"
说明:
-
1.num1 和 num2 的长度小于110。
2.num1 和 num2 只包含数字 0-9。
3.num1 和 num2 均不以零开头,除非是数字 0 本身。
4.不能使用任何标准库的大数类型(比如 BigInteger)或直接将输入转换为整数来处理。
def mul(s1,s2): l1 = len(s1) l2 = len(s2) cin = 0 if l2>l1: s1,s2=s2,s1 l1,l2=l2,l1 rs = [] for i in range(l1-1,-1,-1): res = [] for j in range(l2-1,-1,-1): tmp = long(s2[j])*long(s1[i])+cin cin = tmp/10 res = [tmp%10]+res if j==0 and cin!=0: res = [cin]+res res+=[0]*(l1-i-1) rs.append(long(''.join([str(x) for x in res]))) return sum([int(x) for x in rs])后来发现其实可以存储相乘后每一位的结果,最后一位乘以最后一位就是最后一位的结果,而最后一位和倒数第二位,与另一个数的最后一位和倒数第二位的乘积,都属于倒数第二位的结果,而且还要加上前一位的进位。不过这样想来思路就很清晰,只需要将res[i+j+1]+=int(num1[i])*int(num2[j]),然后加上进位就行了,通过的代码如下:
if num1=='0' or num2=='0': return '0' l1 = len(num1) l2 = len(num2) k = [0]*(l1+l2) for i in range(l1-1,-1,-1): for j in range(l2-1,-1,-1): k[i+j+1]+=int(num1[i])*int(num2[j]) cin = 0 for i in range(l1+l2-1,-1,-1): k[i] += cin cin = k[i]/10 k[i] = k[i]%10 for i in range(l1+l2): if k[i]!=0: return ''.join([str(x) for x in k[i:]])
5.翻转字符串里的单词
给定一个字符串,逐个翻转字符串中的每个单词。
示例一:
输入: "the sky is blue" 输出: "blue is sky the"
示例二:
输入: " hello world! " 输出: "world! hello" 解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
示例三:
输入: "a good example" 输出: "example good a" 解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
说明:
-
1.无空格字符构成一个单词。
2.输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
3.如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
res = [] tmp = '' for i in range(len(s)): print s[i] if i==len(s)-1 and s[i]!=' ': tmp+=s[i] res.append(tmp) elif s[i]!=' ': tmp+=s[i] else: if tmp!='': res.append(tmp) tmp = '' re = '' while res: tmp = res.pop() re += tmp+' ' return re[:-1]但其实本题还有更简便的解法,利用python str的split函数,即可非常轻松完成这个任务。代码如下:
return ' '.join(s.split()[::-1])
6.简化路径
以 Unix 风格给出一个文件的绝对路径,你需要简化它。或者换句话说,将其转换为规范路径。
在 Unix 风格的文件系统中,一个点(.)表示当前目录本身;此外,两个点 (..) 表示将目录切换到上一级(指向父目录);两者都可以是复杂相对路径的组成部分。更多信息请参阅:Linux / Unix中的绝对路径 vs 相对路径
请注意,返回的规范路径必须始终以斜杠 / 开头,并且两个目录名之间必须只有一个斜杠 /。最后一个目录名(如果存在)不能以 / 结尾。此外,规范路径必须是表示绝对路径的最短字符串。
示例一:
输入:"/home/" 输出:"/home" 解释:注意,最后一个目录名后面没有斜杠。
示例二:
输入:"/../" 输出:"/" 解释:从根目录向上一级是不可行的,因为根是你可以到达的最高级。
示例三:
输入:"/home//foo/" 输出:"/home/foo" 解释:在规范路径中,多个连续斜杠需要用一个斜杠替换。
示例四:
输入:"/a/./b/../../c/" 输出:"/c"
示例五:
输入:"/a/../../b/../c//.//" 输出:"/c"
示例六:
输入:"/a//b////c/d//././/.." 输出:"/a/b/c"本题按照题目的意思,我最初的想法是遍历当前字符串,如果不是'/'符号,则将当前字符加入tmp,如果遇到'/'符号,则对tmp进行处理,如果tmp不是'..',tmp入栈,清空tmp。如果tmp是'..',弹出栈顶元素,然后清空tmp,如果遍历到最后一个字符,则将当前tmp压栈,然后返回栈。但是后来发现有更简单的方法,即不用一个一个遍历字符,直接靠'/'对字符串进行分割,然后对每一个子串进行处理,返回栈即可。代码如下:
res = [] x = path.split('/') for i in x: if i == '' or i == '.': continue elif i == '..': if res: res.pop() else: res.append(i) return '/'+'/'.join(res)
7.复原IP地址
给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。
示例一:
输入: "25525511135" 输出: ["255.255.11.135", "255.255.111.35"]本题思路就是通过递归,遍历字符串中的每一个位置,然后插入'.',一共需要插入3个点,然后将符合规则的分割方法添加到res,最后返回res即可。代码如下:
def restoreIpAddresses(self, s): res = [] def isval(s): a = int(s) if 0<=a<=255 and (len(s)==1 or s[0]!='0'): return True return False def dfs(a,s,k): if k==3: if isval(s): res.append(a+s) return else: for i in range(1,min(4,len(s))): tmp=s[:i] if isval(tmp): dfs(a+tmp+'.',s[i:],k+1) dfs('',s,0) return res
最近其实一直在刷leetcode的题目,感觉自己的编程能力也有一定的提升,希望能保持这种刷题热情,让自己更加优秀。