Leetcode:字符串问题ii

本博客详细解析LeetCode中的字符串相关问题,包括第一个唯一字符、字符串转换整数、翻转字符串、字母异位词等,并进行重写优化。同时涵盖高级动态规划、布隆过滤器、LRU缓存机制和位运算解题策略。

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

第一章 字符串相关问题II

1、Leetcode 387:字符串中的第一个唯一字符

题目描述

在这里插入图片描述

解题思路
使用哈希表,key存储字符,value存储对应下标。

代码实现

class Solution:
    def firstUniqChar(self, s: str) -> int:
        #建立哈希表
        dic=collections.defaultdict(list)
        for i in range(len(s)):
            dic[s[i]].append(i)
        #遍历哈希表找到第一个次数为1的
        for k,v in dic.items():
            if len(v)==1:
                return int(v[-1])
        return -1

2、Leetcode 8:字符串转换整数重写

class Solution:
    def myAtoi(self, s: str) -> int:
        #对字符串左边的空格进行处理
        slices=list(s.strip())
        #如果为空,返回0
        if len(slices)==0:
            return 0
        #先判断正负号
        signal = -1 if slices[0]=="-" else 1
        #将正负号删除
        if slices[0] in ["-","+"]: del slices[0]
        res,i=0,0
        #开始循环
        while i < len(slices) and slices[i].isdigit():
            res=res*10+ord(slices[i])-ord("0")
            i+=1
        return max(min(2**31-1,res*signal),-2**31)

3、Leetcode 541:反转字符串II重写

class Solution:
    def reverseStr(self, s: str, k: int) -> str:
        n=len(s)
        li=list(s)
        for i in range(0,n,k*2):
            li[i:i+k]=li[i:i+k][::-1]
        return "".join(li)

4、Leetcode 151:翻转字符串里的单词重写

class Solution:
    def reverseWords(self, s: str) -> str:
        #切片
        word_list=s.split()
        word_list.reverse()
        return " ".join(word_list)

5、Leetcode 537:反转字符串中的单词iii重写

class Solution:
    def reverseWords(self, s: str) -> str:
        n=len(s)
        #切片
        word_list=[list(word) for word in s.split()]
        #遍历
        res=[]
        for word in word_list:
            word.reverse()
            res.append("".join(word))
        return " ".join(res)

6、Leetcode 917:仅反转字母重写

class Solution:
    def reverseOnlyLetters(self, S: str) -> str:
        #将输入中纯字母的压栈
        stack=[char for char in S if char.isalpha()]
        #开始修改原始字符串
        li=list(S)
        for i in range(len(li)):
            if S[i].isalpha():
                new_char=stack.pop()
                li[i]=new_char
            else:
                continue
        return "".join(li)

7、Leetcode 438:找到字符串中所有字母异位词重写

class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        #长度
        m,n=len(s),len(p)
        res=[]
        #特殊条件
        if m<n:
            return []
        #建立一个26位列表的映射
        p_save=[0]*26
        s_save=[0]*26
        #对于s中的前n个数字进行添加
        for i in range(n):
            p_save[ord(p[i])-ord("a")]+=1
            s_save[ord(s[i])-ord("a")]+=1
        #判断
        if p_save==s_save:
            res.append(0)
        #开始从下标为n开始遍历
        for j in range(n,m):
            #新添加的
            s_save[ord(s[j])-ord("a")]+=1
            #去除的
            s_save[ord(s[j-n])-ord("a")]-=1
            #判断
            if s_save==p_save:
                res.append(j-(n-1))
        return res

8、Leetcode 5:最长回文串重写

class Solution:
    def expand_valid(self,s,left,right):
        while left>=0 and right<len(s) and s[left]==s[right]:
            left-=1
            right+=1
        return left+1,right-1

    def longestPalindrome(self, s: str) -> str:
        start,end=0,0
        for i in range(len(s)):
            l1,r1=self.expand_valid(s,i,i)
            l2,r2=self.expand_valid(s,i,i+1)
            #判断
            if r1-l1>end-start:
                start,end=l1,r1
            if r2-l2>end-start:
                start,end=l2,r2
        return s[start:end+1]

9、Leetcode 205:同构字符串

题目描述
在这里插入图片描述

解题思路
两个字典存储s和t每个单词出现的对应得下标位置,如果同构,他们的字典中的下标位置的存储一定相同,很简单。

代码实现

class Solution:
    def isIsomorphic(self, s: str, t: str) -> bool:
        n=len(s)
        dic_s=collections.defaultdict(list)
        dic_t=collections.defaultdict(list)
        for i in range(n):
            dic_s[s[i]].append(i)
            dic_t[t[i]].append(i)
        li1=[v for k,v in dic_s.items()]
        li2=[v for k,v in dic_t.items()]
        return li1==li2

10、Leetcode 680:验证回文字符串II重写

class Solution:
    def valid_str(self,s,left,right):
        while left<right:
            if s[left]==s[right]:
                left+=1
                right-=1
            else:
                return False
        return True
    def validPalindrome(self, s: str) -> bool:
        low,high=0,len(s)-1
        while low<high:
            if s[low]==s[high]:
                low+=1
                high-=1
            else:
                return self.valid_str(s,low+1,high) or self.valid_str(s,low,high-1)
        return True

11、Leetcode 44:通配符匹配重写

class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        #长度
        m,n=len(s),len(p)
        #建立dp
        dp=[[False]*(n+1) for _ in range(m+1)]
        dp[0][0]=True
        #初始化
        for i in range(1,n+1):
            if p[i-1]=="*":
                dp[0][i]=True
            else:
                break
        #开始遍历
        for i in range(1,m+1):
            for j in range(1,n+1):
                if p[j-1]=="*":
                    dp[i][j]=dp[i][j-1]|dp[i-1][j]
                elif p[j-1]=="?" or s[i-1]==p[j-1]:
                    dp[i][j]=dp[i-1][j-1]
        return dp[-1][-1]

12、Leetcode 32:最长有效括号重写

class Solution:
    def longestValidParentheses(self, s: str) -> int:
        #长度
        n=len(s)
        #特殊条件
        if n==0:
            return 0
        #建立dp
        dp=[0]*n
        #无边际条件,0就是0
        #开始遍历
        for i in range(1,n):
            #当前位置是右括号时
            if s[i]==")":
                if s[i-1]=="(":
                    dp[i]=dp[i-2]+2
                elif s[i-1]==")" and i-dp[i-1]-1>=0 and s[i-dp[i-1]-1]=="(":
                    dp[i]=dp[i-1]+dp[i-dp[i-1]-2]+2
        return max(dp)

13、Leetcode 115:不同的子序列重写

class Solution:
    def numDistinct(self, s: str, t: str) -> int:
        #统计长度
        m,n=len(s),len(t)
        if m<n:
            return 0
        #建立dp
        dp=[[0]*(n+1) for _ in range(m+1)]
        #当t为空时可以匹配所有
        for i in range(m+1):
            dp[i][n]=1
        #开始遍历,反向
        for i in range(m-1,-1,-1):
            for j in range(n-1,-1,-1):
                #如果当前相等
                if s[i]==t[j]:
                    #可以选择匹配或者不匹配
                    dp[i][j]=dp[i+1][j]+dp[i+1][j+1]
                else:
                    #只能不匹配
                    dp[i][j]=dp[i+1][j]
        return dp[0][0]

第二章 高级动态规划

1、Leetcode 300:最长递增子序列重做

class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        #长队
        n=len(nums)
        #定义dp
        dp=[1]*n
        #开始循环
        for i in range(n):
            for j in range(i):
                if nums[j]<nums[i]:
                    dp[i]=max(dp[i],dp[j]+1)
        return max(dp)

2、Leetcode 91:解码方法重做

class Solution:
    def numDecodings(self, s: str) -> int:
        #长度
        n=len(s)
        #建立dp
        dp=[0]*(n+1)
        #特殊条件
        if s[0]=="0":
            return 0
        #初始化
        dp[0],dp[1]=1,1
        #开始循环
        for i in range(1,n):
            #如果当前不为0
            if s[i]!="0":
                #它自己就可以被解码
                dp[i+1]=dp[i]
            #还要考虑两个相邻的
            nums=10*(ord(s[i-1])-ord("0"))+ord(s[i])-ord("0")
            if 10<=nums<=26:
                dp[i+1]+=dp[i-1]
        return dp[-1]

3、Leetcode 32:最长有效括号重写

class Solution:
    def longestValidParentheses(self, s: str) -> int:
        #长度
        n=len(s)
        dp=[0]*(n)
        #特殊条件
        if n==0:
            return 0
        #开始循环
        for i in range(1,n):
            if s[i]==")":
                if s[i-1]=="(":
                    dp[i]=dp[i-2]+2
                elif s[i-1]==")" and i-dp[i-1]-1>=0 and s[i-dp[i-1]-1]=="(":
                    dp[i]=dp[i-1]+2+dp[i-dp[i-1]-2]
        return max(dp)

4、Leetcode 85:最大矩形

题目描述
在这里插入图片描述

解题思路

  • 使用pre存储对于每一行来说,底为1的数量
  • 使用单调栈不断的把pre中的数量排序排号,当当前栈中最后一个位置索引对应的1的数量大于了当前循环位置的为1的数量P时,说明栈中以末尾索引O为基础,剩下的k-O-1个位置的储存1的数量都大于当前数量P,所以以k-O-1为长,P为高的矩形可找到,计算一次面积,不断更新最大的面积,最后返回。

代码实现

class Solution:
    def maximalRectangle(self, matrix: List[List[str]]) -> int:
        #特殊情况
        if not matrix: return 0
        #行列的长度
        m,n=len(matrix),len(matrix[0])
        #建立pre
        pre=[0]*(n+1)
        res=0
        #开始填充前缀和
        for i in range(m):
            for j in range(n):
                pre[j]=pre[j]+1 if matrix[i][j]=="1" else 0
            
            #每一层的单调栈
            stack=[-1]
            #遍历pre的索引和值
            for k,num in enumerate(pre):
                while stack and pre[stack[-1]]>num:
                    index=stack.pop()
                    res=max(res,pre[index]*(k-stack[-1]-1))
                stack.append(k)
        return res

5、Leetcode 115:不同的子序列重写

class Solution:
    def numDistinct(self, s: str, t: str) -> int:
        #长度
        m,n=len(s),len(t)
        #特殊条件,当s的长度小于t,不可能存在解
        if m<n:
            return 0
        #建立dp
        dp=[[0]*(n+1) for _ in range(m+1)]
        #特殊条件,当t为空时,它可以满足所有的s的长度
        for i in range(1,m+1):
            dp[i][n]=1
        #开始循环
        for i in range(m-1,-1,-1):
            for j in range(n-1,-1,-1):
                #如果当前i和j对应的相同
                if s[i]==t[j]:
                    #可以选择添加或者不添加
                    dp[i][j]=dp[i+1][j]+dp[i+1][j+1]
                else:
                    #只能不要j
                    dp[i][j]=dp[i+1][j]
        return dp[0][0]

6、Leetcode 818:赛车

题目描述
在这里插入图片描述

解题思路
这道题找到了一个解释的很清楚的题解
在这里插入图片描述
在这里插入图片描述

代码实现

class Solution:
    def racecar(self, target: int) -> int:
        #建立dp
        dp=[float("inf")]*(target+1)
        #开始循环
        for i in range(1,target+1):
            #A的次数
            k=1
            pos=1

            #当目前的pos小于i,且往回走
            while pos<i:
                #倒车转向后A的次数
                q=0
                while (1<<q)-1<pos:
                    dp[i]=min(dp[i],k+1+q+1+dp[i-(pos-((1<<q)-1))])
                    q+=1
                k+=1
                pos=(1<<k)-1
            #当i等于pos,那就是全为a
            if i==pos:
                dp[i]=k
            #如果超出了就往回走,+1是要代表R
            else:
                dp[i]=min(dp[i],k+1+dp[pos-i])
        return dp[target]

第三章 布隆过滤器&LRU cache

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

Leetcode 146:LRU缓存机制

题目描述
在这里插入图片描述

代码实现
orderdic实现哈希和双向链表

class LRUCache:

    def __init__(self, capacity: int):
        #建立一个orderdic
        self.dic=collections.OrderedDict()
        #定义容量
        self.remain=capacity


    def get(self, key: int) -> int:
        #如果不在dic中,直接返回-1
        if key not in self.dic:
            return -1
        #如果在的话,先把它pop出来
        v=self.dic.pop(key)
        #放到首端
        self.dic[key]=v
        return v


    def put(self, key: int, value: int) -> None:
        #如果当前key已经在lru中
        if key in self.dic:
            #拿出来
            self.dic.pop(key)
        else:
            #如果当前容量未满
            if self.remain>0:
                self.remain-=1
            #如果满了,就要把第一个pop出来
            else:
                self.dic.popitem(last=False)
        #添加元素
        self.dic[key]=value



# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)

第三章 位运算

在这里插入图片描述
在这里插入图片描述

1、Leetcode 191:位1的个数

题目描述
在这里插入图片描述

代码实现
方法一:不断清零最低位的1

class Solution:
    def hammingWeight(self, n: int) -> int:
        count=0
        while n>0:
            #清零最低位的1
            n=n&(n-1)
            count+=1
        return count

方法二:调用bin函数:将int转为二进制表示

class Solution:
    def hammingWeight(self, n: int) -> int:
        return bin(n).count("1")

方法三:循环检查

class Solution:
    def hammingWeight(self, n: int) -> int:
        count=0
        for num in bin(n):
            if num=="1":
                count+=1
        return count

方法四:位运算不断右移动

class Solution:
    def hammingWeight(self, n: int) -> int:
        count=0
        while n:
            #如果当前最后一位为1
            count+=n&1
            #x右移动一位
            n=n>>1
        return count

2、Leetcode 231:2的幂

题目描述
在这里插入图片描述

代码实现
方法一:循环统计

class Solution:
    def isPowerOfTwo(self, n: int) -> bool:
        if n<0:
            return False
        count=0
        for num in bin(n):
            if num=="1":
                count+=1
        return True if count==1 else False

方法2:不断除2看是否可以除进

class Solution:
    def isPowerOfTwo(self, n: int) -> bool:
        if n<=0:
            return False
        while n%2==0:
            n/=2
        return n==1

方法3:使用x&(-x)

class Solution:
    def isPowerOfTwo(self, n: int) -> bool:
        if n ==0:
            return False
        return n&(-n)==n#n&(-n):保留n中的最低位的1,其余归0

3、 Leetcode 190:颠倒二进制位

题目描述
在这里插入图片描述

解题思路
n&1可以返回当前最右边位置是1还是0,将这个位置左移动31位就是它该出现的颠倒后的位置,对于右边第二位,因为右边第一位已经处理好了,那么直接把n右移动一位,然后还是判断n&1的值,再左移动30位即可,如此循环,直到n为0

代码实现

class Solution:
    def reverseBits(self, n: int) -> int:
        res,idx=0,31
        while n:
            res+=(n&1)<<idx#看n最右边的是1还是0,左移动31-i位数
            n=n>>1#n向右移动一次
            idx-=1#更新idx
        return res

4、Leetcode 51:N皇后问题的位运算解法

代码实现
dfs方法

class Solution:
    def solveNQueens(self, n: int) -> List[List[str]]:
        #定义一个存储输出结果的列表
        res=[]
        #定义数组存储棋子的pie、na、col的信息
        col,pie,na=set(),set(),set()
        #建立递归函数
        def dfs(n,row,state):
            #终止条件
            if row==n:
                res.append(state)
            #当前层的处理
            for cols in range(n):#遍历当前层的每一个列
                #判断当前位置是否符合规定
                if cols in col or cols+row in pie or row-cols in na:
                    continue
                #将当前信息加入三个集合
                col.add(cols)
                pie.add(cols+row)
                na.add(row-cols)
                #进入下一层循环
                dfs(n,row+1,state+[cols])
                #出循环后remove掉
                col.remove(cols)
                pie.remove(cols+row)
                na.remove(row-cols)
        def generated_result(n):
            #建立一个空列表
            board=[]
            #拿出res的每一个state
            for state in res:
                #拿出state中每一行的信息
                for col_pos in state:
                    board.append("."*col_pos+"Q"+"."*(n-col_pos-1))
            #返回结果
            return [board[i:i+n] for i in range(0,len(board),n)]
        dfs(n,0,[])
        return generated_result(n)

位运算方法

class Solution:
    def solveNQueens(self, n: int) -> List[List[str]]:
        res=[]
        def generated_result():
            board=[]
            for i in range(n):
                row[queen[i]]="Q"
                board.append("".join(row))
                row[queen[i]]="."
            return board
        def dfs(row,columns,pie,na):
            #终止条件:
            if row==n:
                board=generated_result()
                res.append(board)
            else:
                #将所有可以放置的地方置为1
                possible=((1<<n)-1)&(~(columns|pie|na))
                #开始循环所有可能放置的位置
                while possible:
                    position=possible&(-possible)#拿到最右边可以放置的位置
                    #将该位置清零
                    possible=possible&(possible-1)
                    #找到为1的位置
                    column=bin(position-1).count("1")
                    queen[row]=column
                    #进入下一层
                    dfs(row+1,columns|position,(pie|position)<<1,(na|position)>>1)
        #存储每一行皇后的所在列位置
        queen=[-1]*n
        row=["."]*n
        dfs(0,0,0,0)
        return res

5、Leetcode 52:N皇后ii

返回的是一共有多少种可能
代码实现
方法一:dfs

class Solution:
    def totalNQueens(self, n: int) -> int:
        #定义三个集合
        column,pie,na=set(),set(),set()
        #递归
        def dfs(n,row):
            #终止条件:
            if row==n:
                return 1
            else:
                count=0
                for col in range(n):
                    if col in column or col+row in pie or row-col in na:
                        continue
                    #添加
                    column.add(col)
                    pie.add(col+row)
                    na.add(row-col)
                    count+=dfs(n,row+1)
                    column.remove(col)
                    pie.remove(col+row)
                    na.remove(row-col)
                return count
        return dfs(n,0)

方法二:位运算

class Solution:
    def totalNQueens(self, n: int) -> int:
        def dfs(row,column,pie,na):
            if row==n:
                return 1
            else:
                count=0
                #拿到当前层所有可能的位置
                possible=((1<<n)-1)&(~(column|pie|na))
                while possible:
                    #拿到最右边为1的值
                    postion=possible&(-possible)
                    #将该位置变为0
                    possible=possible&(possible-1)
                    #进入下一层
                    count+=dfs(row+1,column|postion,(pie|postion)<<1,(na|postion)>>1)
                return count

        return dfs(0,0,0,0)

6、Leetcode 338:比特位计数

题目描述
在这里插入图片描述

代码实现
循环的方法

class Solution:
    def countBits(self, num: int) -> List[int]:
        def solve(x):
            count=0
            while x>0:
                #将最低位的1变为0
                x=x&(x-1)
                count+=1
            return count
        return [solve(i) for i in range(num+1)]

位运算方法

class Solution:
    def countBits(self, num: int) -> List[int]:
        res=[0]*(num+1)
        res[0]=0
        high_bit=0
        for i in range(1,num+1):
            #如果当前i是2的某次幂
            if i&(i-1)==0:
                high_bit=i
            res[i]=res[i-high_bit]+1
        return res
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值