python学习日记

前记

写这篇博客的目的是博主觉得自己对python语法不够熟悉。。所以尝试通过leetcode写几道题熟悉一下列表/元组等类型的操作,但是写完感觉算法能力太弱了,写出来的代码不够简洁

一、python的一些基本数据类型

列表

'''
列表:用[]定义,类似于数组;用list()创建
可变的数据类型:append\insert\clear\pop\remove\reverse\opy
'''
lst=['hello','world',98.5,77]
lst1=list("helloworld")
lst2=list(range(1,10,2))
print(lst)
print(lst1)
print(lst2)
print(lst+lst1+lst2)
print(lst*3)
#删除列表
del lst
#列表的遍历:enumerate
lst=['h','hh','hhhh']
for item in lst:
    print(item)
for i in range(0,len(lst)):
    print(lst[i])
for index,item in enumerate(lst,start=1):   #start表示手动设置序列号
    print(index,item)
#列表的一些操作
lst.append('sql')   #在结尾拼接
lst.insert(1,100)   #在1位插入100
lst.remove('h')     #删除h
print(lst)
lst.pop(3)          #将第三位取出
lst.reverse()       #将列表逆序
print(lst)
new_list=lst.copy() #创建新列表
lst.clear()         #清空列表
print(new_list+lst)
#列表的排序操作:不会修改地址
lst=[1,2,3,4,5,6,7,8,9]
lst.sort()
print(lst)
lst.sort(reverse=True)
print(lst)

lst1=['apple','Orange','banana']
lst1.sort()
print(lst1)
lst1.sort(key=str.lower)#转化成小写进行比较
print(lst1)
#修改地址即产生新列表的排序
nwe_lst=sorted(lst1)
print(lst1)
print(nwe_lst)

#列表生成式:lst=[exp for item in range if codition]
import random
del lst
lst=[item for item in range(1,11)]
print(lst)
lst.clear()
lst=[random.randint(1,100) for _ in range(10)]
print(lst)
lst.clear()
lst=[i for i in range(1,10) if i%2==0]
print(lst)

元组

'''
元组:不可变序列,用()创建/用tuple创建
'''
t=('python','hello','world')
lst=['python','hello','world']
#元组支持切片操作
t2=t[0:3:2]
lst2=lst[0:3:2]
print(t2)
print(lst2)

#元组生成式:生成了一个生成器对象,需要用tuple转化为元组
del t
t=(i for i in range(1,4))
print(t)
t=tuple(t)
print(t)

字典

'''
字典:可变序列,有点像指针:索引用的键和对应的值构成成对的关系
特点:元组由于不可变,可以作为键,而列表不可以
'''
d={10:'cat',20:'dog',30:'pet',40:'z00'}
lst1=[10,20,30,40]
lst2=['cat','dog','pet','z00']
zipobj=zip(lst1,lst2)
print(zipobj)           #映射结果是一个映射对象
for key,value in zipobj:
    print(key,'---',value)
#print(list(zipobj))    #将映射对象转化为列表类型
othobj=dict(zipobj)
print(othobj)

#字典的遍历
d={'hello':10,'world':20,'python':30}
print(d['hello'])
print(d.get('java'))
print(d.get('java','NONE'))

for item in d.items():
    print(item)
for key,value in d.items():
    print(key,'---',value)
#字典的相关操作
d={1001:'limei',1002:'wanghua',1003:'zhangfeng'}
lst=list(d.items())
print(lst)
print(d)
#字典生成式
import random
d={item:random.randint(1,100) for item in range(4)}
print(d)
lst1=[1001,1002,1003,1004]
lst2=['chen','yiyi','lili']
dd={key:value for key,value in zip(lst1,lst2)}
print(zip(lst1,lst2))
print(dd)

集合

'''
集合类型:可变数据类型,用{}定义,无序不重复序列
'''
#创建集合
s={10,20,30,40}
#只能存储不可变数据类型,比如说列表就不可以作为集合元素
del s
s=set('HELOWORLD')
s1=set([20,23,55])
s2=set(range(1,10))
print(s)
print(s2)

二、题目

解码方法

1.题目描述

2.思路:先将字符串转化为列表,其中字符’0‘必须跟在一个数字后面并且组成的数字<26;接着使用递归,通过10/20对列表进行分组然后将子列表传给counter函数进行计算解码方法总数,counter函数的具体实现:判断传入列表的长度进行对应的操作
3.代码实现
#自己写的。。但是并没有解决问题
#递归-对长字符串而言使用递归时会导致timeout,效率非常低
class Solution:
    def numDecodings(self, s: str) -> int:
        ls=list(s)
        newls=[]
        i=0
        #如果以ls[0]==0,应该remove
        if int(ls[0])==0:
            return 0
        #先得到列表,再对列表的字符进行分组
        while(i<len(ls)):
            if ls[i]=='0':
                #newls的最末尾的索引不一定会是i-1
                newls[len(newls)-1]=int(newls[len(newls)-1]*10)
                if newls[len(newls)-1]==200 or newls[len(newls)-1]==100:
                    return 0
            elif ls[i]!='0':
                newls.append(int(ls[i]))
            i+=1  
        print(newls)
        #如果只有一个数并且为10/20
        if len(newls)==1 and (newls[0]==10 or newls[0]==20):
            return 1
        #递归得到长度     
        j=0
        count=1
        index=0
        #分为几种情况:中间有10/20且以10/20结尾的;没有10/20;中间有10/20但不以10/20结尾的     
        while j<len(newls):
            if newls[j]==10 or newls[j]==20:
                #以10/20开头的
                if j==0:
                    count*=1
                    index+=1
                else:
                    count*=Solution.counter(newls[index:j])
                    index=j+1
            j+=1
        if index<j+1:
            count*=Solution.counter(newls[index:j])
        return count

    def counter(ls:list)->int:
        if not ls:	#传入的列表为空
            return 0
        elif len(ls)==1 :
            return 1
        #判断并返回
        
        if len(ls)==3:
            v1=int("".join(map(str,ls[0:2])))
            v2=int("".join(map(str,ls[1:3])))    
            if v1>26 and v2>26:
                return 1
            elif v1<=26 and v2<=26:
                return 3
            else:
                return 2
        if len(ls)==2:
            v1=int("".join(map(str,ls[0:2])))
            if v1<=26:
                return 2
            else:
                return 1
        if len(ls)==4 :
            tab=0
            v1=int("".join(map(str,ls[0:2])))
            tab+=Solution.counter(ls[1:4])
            if v1<=26:
                tab+=(Solution.counter(ls[0:2])*Solution.counter(ls[2:4]))//2
            return tab
        #进行分组
        if len(ls)>4:
            v1=int("".join(map(str,ls[0:2])))
            fc=Solution.counter(ls[1:len(ls)])
            if v1<=26:
                fc+=Solution.counter(ls[2:len(ls)])   
            return fc
#转载自评论区,侵权请联系博主删除
#思路:新建cnt列表,然后遍历字符串的每一个字符,记下截止该字符能进行的解码方法数,最后返回末尾的操作数
def numDecodings(s:str) -> int:
    cnt = [1,1] + [0] * len(s)
    s = "99" + s #添加虚拟头部,以便不用对头部做特殊处理
    for i in range(2, len(s)):
        if( 10 <= int(s[i-1:i+1]) <= 26): #s[i]可与s[i-1]组合
            cnt[i] += cnt[i-2]
        if(s[i] != '0'): #s[i]可单独解码
            cnt[i] += cnt[i-1]
    return cnt[-1]

合并区间

1.题目描述:以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间

2.思路:递归(二路归并的思想)没解决,但是写着写着对题目的理解就搞混了,所以也并没有实现。
3.代码实现
#!!!!并没有解决题目
class Solution:
    def devide(intervals:list)->list:
        result=[]
        if len(intervals)==1:
            result.append(intervals[0])
            return result

        if len(intervals)==2:
            if intervals[0][1]>=intervals[1][0] and intervals[0][0]<=intervals[1][0]:
                if intervals[0][1]<=intervals[1][1]:
                    result.append([intervals[0][0],intervals[1][1]])
                    return result
                elif intervals[0][1]>intervals[1][1]:
                    result.append([intervals[0][0],intervals[0][1]])
                    return result
            elif intervals[0][1]>=intervals[1][0] and intervals[0][0]>intervals[1][0]:
                if intervals[1][0]==intervals[1][1]:
                    result.extend(intervals[1::-1]) #append intervals[1]-intervals[0]
                    return result
                if intervals[0][1]<=intervals[1][1]:
                    result.append([intervals[1][0],intervals[1][1]])
                    return result
                elif intervals[0][1]>intervals[1][1]:
                    result.append([intervals[1][0],intervals[0][1]])
                    return result             
                return result
            else:
                result.extend(intervals[0:2])
                return result

        elif len(intervals)==3:
            item3=[]
            item3=Solution.devide(intervals[0:2])
            #如果是两个列表传过去,只会返回两种情况:只剩下一个列表,或者因为其中一个列表的元素 而相同返回两个排好序列表
            if(len(item3)==1):
                item33=[item3[0],intervals[2]]
                item33r=[]
                item33r.extend(Solution.devide(item33))
                return item33r
            elif(len(item3)==2):
                item34=[item3[1],intervals[2]]
                item34r=[]
                item34r.append(item3[0])
                item34r.extend(Solution.devide(item34))
                return item34r
        elif len(intervals)>3:
            result.extend(Solution.devide(intervals[0:int(len(intervals)/2)]))
            result.extend(Solution.devide(intervals[int(len(intervals)/2):len(intervals)]))
            return result
    def merge(self, intervals: List[List[int]]) -> List[List[int]]:
        result=Solution.devide(intervals)
        return result

#来自评论区,侵权请联系博主删除
#思路:使用lambda函数先对intervals这个二维列表进行排序,排序的根据是子列表的第一个数;接着进行合并,合并规则是如果两个区间没有
#重合则在合并列表后append,重叠的话就进行合并
class Solution:
    def merge(self, intervals: List[List[int]]) -> List[List[int]]:
        intervals.sort(key=lambda x: x[0])
        merged = []
        for interval in intervals:
            # 如果列表为空,或者当前区间与上一区间不重合,直接添加
            if not merged or merged[-1][1] < interval[0]:
                merged.append(interval)
            else:
                # 否则的话,我们就可以与上一区间进行合并
                merged[-1][1] = max(merged[-1][1], interval[1])

        return merged
4.lambda函数的学习
#lambda函数的使用

#-1 一行函数
add=lambda x,y:x+y
result=add(2,3)
print(result)

#-2 作为参数传给高阶函数 
# map(function,iterable),map的返回值为iterator,如果需要打印需要转化为列表
nums=[1,2,3,4,5]
result2=[item for item in map(lambda x:x**2,nums)]
result22=map(lambda x:x**2,nums)
print(result2)
print(list(result22))

#-3 用于排序
nums3=[[9,8,7],[7,6,5],[5,4,3],[3,2,1]]
nums3.sort(key=lambda x:x[0])
#nums3.sort(key=lambda x:x) 
#第一种写法根据x[][0]进行排序,第二种写法根据x[]进行排序
print(nums3)
nums33=[[9,8,7],[7,6,5],[5,4,3],[3,2,1]]
nums33.sort(key=lambda x:(x.sort(),x[0]))  
print(nums33)

字符串转整数

1.题目描述:请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi 函数)

2.思路:感觉这题有点咬文嚼字=_=,除去所有不能转化为数字的字符串的情况就可以进行拼接了
3.代码实现
class Solution:
    def myAtoi(self, s: str) -> int:
        #空字符串,返回0
        if s=="":
           return 0
        #如果不以数字/空格/+/-开头,均返回0
        if s[0].isdigit()==False and s[0]!=' ' and s[0]!='+' and s[0]!='-':
            return 0
        ss = list(s)
        i = 0
        ii = 0
# 先遍历前面不为数字的字符
        while i < len(ss) and (ss[i] > '9' or ss[i] < '0'):
            #判断数字前的字符是否均为字母
            if s[i].isalpha()==True:
                return 0
            i += 1
        if i < len(ss):
            index=s.find('-',0,i)
            index1=s.find('+',0,i)
            #如果同时出现+/-,返回0
            if index!=-1 and index1!=-1:
                return 0
            #如果+/-后面不是数字,返回0
            if (index1>0 and s[index1+1].isdigit()==False) or (index>0 and s[index+1].isdigit()==False):
                return 0
            #如果存在 -
            if index>=0:
                while i < len(ss) and ss[i] <= '9' and ss[i] >= '0':
                    ii = ii * 10 + int(ss[i])
                    i += 1
                ii=0-ii
            elif index<0:
                while i < len(ss) and ss[i] <= '9' and ss[i] >= '0':
                    ii = ii * 10 + int(ss[i])
                    i += 1
        if ii>2**31-1:
            ii=2**31-1
        elif ii<0-2**31:
            ii=0-2**31
        return ii

无重复字符的最长字串

1.题目描述:给定一个字符串 s ,请你找出其中不含有重复字符的最长子串的长度。

2.代码实现
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        ss=""
        max=0
        for i in range(len(s)):
            if s[i] not in ss:
                ss+=s[i]
            elif s[i] in ss:
                if max<len(ss):
                    max=len(ss)
                
                #应该向前遍历一遍,将重复字符后的不重复字符加入
                ss=""
                tmp=i
                while i-1>=0 and s[tmp-1]!=s[i]:
                    ss+=s[tmp-1]
                    tmp-=1
                ss=ss[::-1]
                ss+=s[i]
        if max<len(ss):
            max=len(ss)
        return max

final

总结:学会了列表/元组这类迭代器的一些基本操作,以及lambda函数/map(func,iterable)/append/extend等函数的使用,有时候新建一些数组来存放新内容要比递归高效率。在使用python时多思考方法,因为python有很多意想不到的库函数可以解决复杂问题
posted @ 2024-05-10 22:04  天街如水  阅读(52)  评论(0)    收藏  举报