刷题笔记,有自己写的也有参考了别人的,非完全原创。
11.Container With Most Water
#Container With Most Water
#第一版
class Solution(object):
def maxArea(self, height):
maxA=0#最大容积
i=0#头坐标
j=len(height)-1#尾坐标
while i != j:
cur=min(height[i],height[j])*(j-i)
maxA=max(maxA,cur)
if height[i]>height[j]:
j-=1
else:
i+=1
return maxA
if __name__=='__main__':
test=Solution()
print(test.maxArea([1001,58,2,5488,5]))
思路:从头尾两边开始向内找,因此底边必然逐渐减小,在此情况下,当且仅当短板一侧变高时,才存在总面积更大的可能。因此每次查找后,保留长坂一侧并抛弃短板一侧,继续向内查找下一个数据。
网上看到的一个比较直观的动图。
出处:http://www.jianshu.com/p/23e8e3e53abf
12.Integer to Roman
#Given an integer, convert it to a roman numeral.
#Input is guaranteed to be within the range from 1 to 3999.
#映射表
#I=1;V=5;X=10;L=50;C=100;D=500;M=1000
#每两个阶段的之间有一个减法的表示,比如900=CM(C写在M前面表示M-C)
#1~9: {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
#10~90: {"X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};
#100~900: {"C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"};
#1000~3000: {"M", "MM", "MMM"}.
#第一版
class Solution(object):
def intToRoman(self, num):
if num<1 or num>3999:
return 'wrong'
intl=[1000,900,500,400,100,90,50,40,10,9,5,4,1]
roml=['M','CM','D','CD','C','XC','L','XL','X','IX','V','IV','I']
res=''
i=0
while num>0:
while num>=intl[i]:
num-=intl[i]
res+=roml[i]
i+=1
return res
if __name__=='__main__':
test=Solution()
print(test.intToRoman(456))
13.Roman to Integer
#Given a roman numeral, convert it to an integer.
#Input is guaranteed to be within the range from 1 to 3999.
#映射表
#I=1;V=5;X=10;L=50;C=100;D=500;M=1000
#每两个阶段的之间有一个减法的表示,比如900=CM(C写在M前面表示M-C)
#1~9: {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
#10~90: {"X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};
#100~900: {"C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"};
#1000~3000: {"M", "MM", "MMM"}.
#第一版
class Solution(object):
def romanToInt(self, s):
cov={'M':1000,'CM':900,'D':500,'CD':400,'C':100,'XC':90,'L':50,'XL':40,'X':10,'IX':9,'V':5,'IV':4,'I':1}
num=0
while len(s)>=2:
if s[0]+s[1] in cov.keys():#判断'CM'这类两个字符的情况,每次读取最左边的两位
num+=cov[s[0]+s[1]]
s=s[2:]
else:
num+=cov[s[0]]
s=s[1:]
if s!='':
num+=cov[s[0]]
return num
#第二版
#规律:如果左边的字母表示的数字小于右边的字母,则用右边的数字减去左边的数字;反之,则需要进行加法。
class Solution(object):
def romanToInt(self, s):
cov={'M':1000,'D':500,'C':100,'L':50,'X':10,'V':5,'I':1}
num=0
i=len(s)-1
pre=0#存储上一个字母表示的数值
while i>=0:#从右向左读
if cov[s[i]]<pre:#如果当前字母的值小于上一个字母
num-=cov[s[i]]
else:
num+=cov[s[i]]
pre=cov[s[i]]
i-=1
return num
if __name__=='__main__':
test=Solution()
print(test.romanToInt('CMXXX'))
14.Longest Common Prefix
#Write a function to find the longest common prefix string amongst an array of strings.
#第一版
class Solution(object):
def longestCommonPrefix(self,strs):
i=0#定位字符串
j=0#定位字符串中的字母
res=''
try:
while True:
comm=strs[0][j]
for i in range(len(strs)):
if strs[i][j]!=comm:
return res
res+=comm
j+=1
except IndexError:#索引超出序列范围,通过捕获错误跳出循环
return res
#第二版
class Solution(object):
def longestCommonPrefix(self,strs):
if strs==[]:
return ''
lenth=len(strs[0])#记录最短字符串
for temp in strs:
lenth=min(len(temp),lenth)
i=0#定位字符串
j=0#定位字符串中的字母
res=''
while j in range(lenth):
comm=strs[0][j]
for i in range(len(strs)):
if strs[i][j]!=comm:
return res
res+=comm
j+=1
return res
15.3Sum
#Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0?
#Find all unique triplets in the array which gives the sum of zero.
#第一版
#要在查找过程中就去重,否则会超时,注意target(即nums[i])去重的处理
class Solution(object):
def threeSum(self,nums):
nums.sort()#对sums从小到大排序
res=[]
for i in range(len(nums)-2):
if i!=0 and nums[i]==nums[i-1]:#去重复项,i!=0能保证[-2,-2,...,4...]这类情(重复项出现在第0位)时,[-2,-2,4]能被找到
continue
target=-nums[i]#取nums[i]的相反数为target,在索引范围为[i+1,length-1]的list中查找两数之和为target
j=i+1
k=len(nums)-1
while j<k:#从两端开始向中间寻找
if nums[j]+nums[k]==target:
res.append([nums[i],nums[j],nums[k]])
j+=1
k-=1
while j<k and nums[j]==nums[j-1]:#去重复项
j+=1
while j<k and nums[k]==nums[k+1]:#去重复项
k-=1
elif nums[j]+nums[k]<target:#当前和偏小时,增大较小一项nums[j]
j+=1
else:#当前和偏大时,减小较大一项nums[k]
k-=1
return res
#测试
test=Solution()
print(test.threeSum([0,0,0,0,0]))
16.3Sum Closest
和15题一样的思路,改变一下判断条件
#Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers.
#You may assume that each input would have exactly one solution.#第一版
class Solution(object):
def threeSumClosest(self,nums,target):
nums.sort()
res=nums[0]+nums[1]+nums[-1]
dif=abs(nums[0]+nums[1]+nums[-1]-target)
for i in range(len(nums)-2):
lo=i+1
hi=len(nums)-1
if i!=0 and nums[i]==nums[i-1]:
continue
while lo<hi:
sum3=nums[lo]+nums[hi]+nums[i]
if sum3==target:
return sum3
if abs(sum3-target)<dif:#sum3是否为当前最接近值,是则更新dif和res
dif=abs(sum3-target)
res=sum3
if sum3>target:#和偏大,下一次减小hi一项
hi-=1
else:#和偏小,下次增大lo一项
lo+=1
return res
#测试
test=Solution()
print(test.threeSumClosest([0,0,0],1))
17.Letter Combinations of a Phone Number
#Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers.
#You may assume that each input would have exactly one solution.
#第一版
class Solution(object):
def letterCombinations(self,digits):
if digits=='':
return[]
self.mapp=[' ',' ','abc','def','ghi','jkl','nmo','pqrs','tuv','wxyz']
#mapp加self修饰,为实例变量,不加self为局部变量,则在letterCB中无法引用
res=['']
for d in digits:
res=self.letterCB(int(d),res)#调用实例方法letterCB
return res
def letterCB(self,digit,oldlist):
return[elem+lett for lett in self.mapp[digit] for elem in oldlist]
#newlist=[]
#for lett in self.mapp[digit]:
#for elem in oldlist:
#newlist.append(elem+lett)
#return newlist
#测试
if __name__=='__main__':
test=Solution()
print(test.letterCombinations('23'))
18.4Sum
#Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target?
#Find all unique quadruplets in the array which gives the sum of target.
#第一版
class Solution(object):
def fourSum(self,nums, target):
numlen=len(nums)
sumdict={}#存放sums中所有数字的两两之和
res=set()#不含重复项
if numlen<4:
return []
nums.sort()#排序
#在sumdict中存储键值对,两数之和:[(下标元组1),(元组2),...]
#y从x+1开始搜索保证不会出现一个数使用了两次的情况
for x in range(numlen-1):
for y in range(x+1,numlen):
if nums[x]+nums[y] not in sumdict:
sumdict[nums[x]+nums[y]]=[(x,y)]
else:
sumdict[nums[x]+nums[y]].append((x,y))#存在不同两数之和相等的情况
#对当前sums[i]和sum[j],查找target-nums[i]-nums[j]是否在sumdict中
#由于每个数只能用一次,因此j只用搜索到numlen-2
#k[0],k[1]对应上面循环中的x,y。
for i in range(numlen-3):
for j in range(i+1,numlen-2):
Temp=target-nums[i]-nums[j]
if Temp in sumdict:
for k in sumdict[Temp]:#sumdict[Temp]为列表[(下标元组1),(元组2),...]
if k[0]>j:#k[0]>j保证不会有数字被重复使用
res.add((nums[i],nums[j],nums[k[0]],nums[k[1]]))
return [list(t) for t in res]#res转为列表
#测试
if __name__=='__main__':
test=Solution()
print(test.fourSum([1,0,-1,0,-2,2],0))
019 Remove Nth Node From End of List
#Given a linked list, remove the nth node from the end of list and return its head.
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
#第一版
class Solution(object):
def removeNthFromEnd(self,head,n):
pre=head
cur=head
for i in range(n):#cur向前走n步,保证当cur是倒数第i个节点时,pre是倒数第n+i个节点
cur=cur.next
if cur!=None:
while cur.next!=None:#向前移动直到cur指向最后一个结点,此时cur指向倒数第n+1个节点
pre=pre.next
cur=cur.next
pre.next=pre.next.next#删除pre的下一个节点,即倒数第n个节点
else:#cur为空时,表明删除的是头节点
head=head.next
return head
020 Valid Parentheses
#Given a string containing just the characters '(', ')', '{', '}', '[' and ']',
#determine if the input string is valid.
#The brackets must close in the correct order,
#"()" and "()[]{}" are all valid but "(]" and "([)]" are not.
#第一版
#若当前字符是右括号,则与当前栈顶匹配,有效则弹出栈顶,无效则返回False
#若当前字符是左括号,则入栈
#栈空为有效字符串
#第一个字符要单独处理
class Solution(object):
def isValid(self,s):
bdict={'}':'{',']':'[',')':'('}
brac=[]
for curb in s:
if curb in bdict and brac==[]:#第一个字符为右括号
return False
if curb in bdict and bdict[curb]!=brac.pop():#先弹出栈顶再进行判断,匹配成功时不需要额外处理,因为栈顶在比较时已经弹出
return False
if curb not in bdict:
brac.append(curb)
return len(brac)==0
#测试
test=Solution()
print(test.isValid('()'))