LeetCode笔记(11-20)

本文总结了LeetCode上的经典题目解答方法,包括盛水最多的容器、整数转罗马数字、罗马数字转整数、最长公共前缀、三数之和等,并提供了详细的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

刷题笔记,有自己写的也有参考了别人的,非完全原创。

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('()'))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值