给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。
输入: "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_
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""。
输入: ["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
给定两个字符串 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
给定两个以字符串形式表示的非负整数 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)或直接将输入转换为整数来处理。
本题一开始我的思路是利用num1和num2中较短的那个,每一位与另一个字符串中的每一位数相乘,然后每一次乘积都储存到一个列表中,而且每一次乘得的乘积还需要向左移位,最后将这个列表求和。其实这个最后是不符合题意的,因为最后我是将列表中的字符串当成了整数进行sum函数运算。不过这种方法在leetcode上无法运行,因为分配的空间不够,导致字符串无法转为整型。最原始的代码如下:
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:]])
给定一个字符串,逐个翻转字符串中的每个单词。
输入: "the sky is blue"
输出: "blue is sky the"
输入: " hello world! "
输出: "world! hello"
解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
输入: "a good example"
输出: "example good a"
解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
1.无空格字符构成一个单词。
2.输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
3.如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
本题按照题目的意思,可以遍历当前字符串,如果当前字符不是空格,则加入tmp数组,如果是空格,将tmp数组加入res数组,然后清空tmp数组,最后反向输出res数组即可。代码如下:
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])
以 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)
给定一个只包含数字的字符串,复原它并返回所有可能的 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的题目,感觉自己的编程能力也有一定的提升,希望能保持这种刷题热情,让自己更加优秀。