5.26力扣 字符串处理 双指针

146. LRU缓存机制
在这里插入图片描述
我们用一个哈希表和一个双向链表维护所有在缓存中的键值对
我们首先使用哈希表进行定位,找出缓存项在双向链表中的位置,随后将其移动到双向链表的头部,即可在 O(1) 的时间内完成 get 或者 put 操作。
在这里插入图片描述
在这里插入图片描述
在双向链表的实现中,使用一个伪头部(dummy head)和伪尾部(dummy tail)标记界限,这样在添加节点和删除节点的时候就不需要检查相邻的节点是否存在。
每次添加新节点都将节点添加到头部,每次删除节点都删除尾部节点

#定义双向链表
class listnode:
    def __init__(self,key=0,value=0):
        self.key=key
        self.value=value
        self.prev=None
        self.next=None
class LRUCache:
    #移走该节点,将该节点前后节点的两个指针链接起来
    def removenode(self,node):
        node.prev.next=node.next
        node.next.prev=node.prev
    #将节点添加到头部
    def addtohead(self,node):
        node.prev=self.head
        node.next=self.head.next
        self.head.next.prev=node
        self.head.next=node
    #将节点移动到头部
    def removehead(self,node):
        self.removenode(node)
        self.addtohead(node)
       #移除尾部节点
    def removetail(self):
        node=self.tail.prev
        self.removenode(node)
        return node
    def __init__(self, capacity: int):
        self.stack=dict()
        self.size=0
        self.mac=capacity
        #伪 头尾节点
        self.head=listnode()
        self.tail=listnode
        self.head.next=self.tail
        self.tail.prev=self.head
    def get(self, key: int) -> int:
        if key not in self.stack:
            return -1
        # 如果 key 存在,先通过哈希表定位,再移到头部
        node=self.stack[key]
        self.removehead(node)
        return node.value

    def put(self, key: int, value: int) -> None:
        #如果节点不存在,则在头部添加节点
        if key not in self.stack:
            node=listnode(key,value)
            self.addtohead(node)
            self.stack[key]=node
            self.size+=1
            #容量超限,则删除尾部节点
            if self.size>self.mac:
                removed=self.removetail()
                self.stack.pop(removed.key)
                self.size-=1
        else:
            #如果节点存在,则更新节点值,并把该节点挪到头部
            node=self.stack[key]
            node.value=value
            self.removehead(node)

字符串处理

常用双指针
注意处理边界
6. Z 字形变换
在这里插入图片描述
在这里插入图片描述
按顺序遍历s时,每个字符的行索引先从s1增大到sn,在从sn递减到s1,遍历s,把每个字符填充到正确的行res[i]上,i从0-numrows-1
注意i=0和i=numrows-1是转折点,要将s反向
https://leetcode-cn.com/problems/zigzag-conversion/solution/zzi-xing-bian-huan-by-jyd/
在这里插入图片描述

class Solution:
    def convert(self, s: str, numRows: int) -> str:
        if numRows<2:
            return s
        #存储每一行字符串
        res=['' for _ in range(numRows)]
        i,flag=0,-1
        for c in s:
            res[i]+=c
            if i==0 or i==numRows-1:
                flag=-flag
            i+=flag
        return ''.join(res)

273. 整数转换英文表示
在这里插入图片描述
从低三位开始,每三个分成一组,接下来,我们可以继续将三位整数分解,例如数字 234 可以分别成百位 2 和十位个位 34,它的英文表示为 2 Hundred 34。这样我们继续将原问题分解成一位整数和两位整数的英文表示。其中一位整数的表示是很容易的,而两位整数中除了 10 到 19 以外,其余整数的的表示可以分解成两个一位整数的表示,这样问题就被圆满地解决了。

class Solution:
    def numberToWords(self, num):
        """
        :type num: int
        :rtype: str
        """
        def one(num):
            switcher = {
                1: 'One',
                2: 'Two',
                3: 'Three',
                4: 'Four',
                5: 'Five',
                6: 'Six',
                7: 'Seven',
                8: 'Eight',
                9: 'Nine'
            }
            return switcher.get(num)

        def two_less_20(num):
            switcher = {
                10: 'Ten',
                11: 'Eleven',
                12: 'Twelve',
                13: 'Thirteen',
                14: 'Fourteen',
                15: 'Fifteen',
                16: 'Sixteen',
                17: 'Seventeen',
                18: 'Eighteen',
                19: 'Nineteen'
            }
            return switcher.get(num)

        def ten(num):
            switcher = {
                2: 'Twenty',
                3: 'Thirty',
                4: 'Forty',
                5: 'Fifty',
                6: 'Sixty',
                7: 'Seventy',
                8: 'Eighty',
                9: 'Ninety'
            }
            return switcher.get(num)

        def two(num):
            if not num:
                return ''
            elif num < 10:
                return one(num)
            elif num < 20:
                return two_less_20(num)
            else:
                tenner = num // 10
                rest = num - tenner * 10
                return ten(tenner) + ' ' + one(rest) if rest else ten(tenner)

        def three(num):
            hundred = num // 100
            rest = num - hundred * 100
            if hundred and rest:
                return one(hundred) + ' Hundred ' + two(rest) 
            elif not hundred and rest: 
                return two(rest)
            elif hundred and not rest:
                return one(hundred) + ' Hundred'

        billion = num // 1000000000
        million = (num - billion * 1000000000) // 1000000
        thousand = (num - billion * 1000000000 - million * 1000000) // 1000
        rest = num - billion * 1000000000 - million * 1000000 - thousand * 1000

        if not num:
            return 'Zero'

        result = ''
        if billion:
            result = three(billion) + ' Billion'
        if million:
            result += ' ' if result else ''
            result += three(million) + ' Million'
        if thousand:
            result += ' ' if result else ''
            result += three(thousand) + ' Thousand'
        if rest:
            result += ' ' if result else ''
            result += three(rest)
        return result

12. 整数转罗马数字
在这里插入图片描述
在这里插入图片描述
python divmod() 函数把除数和余数运算结果结合起来,返回一个包含商和余数的元组(a // b, a % b)

class Solution:
    def intToRoman(self, num: int) -> str:
        roman_dict = {1:'I', 5:'V', 10:'X', 50:'L', 100:'C', 500:'D', 1000:'M'}
        roman_num=''
        a=1000
        #从大到小
        while num>0:
            s=num//a
            num=num%a
            if s in [4,9]:
                roman_num+=roman_dict[a]+roman_dict[(s+1)*a]
            elif s<4:
                roman_num+=s*roman_dict[a]
            elif s==5:
                roman_num+=roman_dict[s*a]
            else:
                roman_num+=roman_dict[5*a]+(s-5)*roman_dict[a]
            a=a//10
        return roman_num

13. 罗马数字转整数
在这里插入图片描述
在这里插入图片描述

class Solution:
    def romanToInt(self, s: str) -> int:
        dic={'I':1,'V': 5,'X':10,'L':50,'C':100,'D':500,'M':1000}
        res=0
        for i in range(len(s)-1):
            if dic[s[i]]<dic[s[i+1]]:
                res-=dic[s[i]]
            else:
                res+=dic[s[i]]
        return res+dic[s[-1]]

165. 比较版本号
在这里插入图片描述
在这里插入图片描述

class Solution:
    def compareVersion(self, version1: str, version2: str) -> int:
        v1=version1.split('.')
        v2=version2.split('.')
        n=max(len(v1),len(v2))
        for i in range(len(v1),n):
            v1.append('0')
        for i in range(len(v2),n):
            v2.append('0')
        for i in range(n):
            if int(v1[i])<int(v2[i]):
                return -1
            elif int(v1[i])>int(v2[i]):
                return 1
            else:
                continue
        return 0

929. 独特的电子邮件地址
在这里插入图片描述

class Solution:
    def numUniqueEmails(self, emails: List[str]) -> int:
        res=set()
        for email in emails:
            name,domain=email.split('@')
            name=name.replace('.','')
            name=name.split('+')[0]
            res.add(name+'@'+domain)
        return len(res)

双指针

使用两个相同方向(快慢指针)或者相反方向(对撞指针)的指针进行扫描,从而达到相应的目的
常见问题:
对于一个序列,用两个指针维护一段区间
对于两个序列,维护某种次序,比如归并排序中合并两个有序序列的操作

32. 最长有效括号
在这里插入图片描述
对于遇到的每个 ‘(’ ,我们将它的下标放入栈中。
对于遇到的每个 ‘)’ ,我们弹出栈顶的元素并将当前元素的下标与弹出元素下标作差,得出当前有效括号字符串的长度。通过这种方法,我们继续计算有效子字符串的长度,并最终返回最长有效子字符串的长度

class Solution:
    def longestValidParentheses(self, s: str) -> int:
        stack=[-1]
        maxl=0
        for i in range(len(s)):
            if s[i]=='(':
                stack.append(i)
            else:
                stack.pop()
                if stack:
                    maxl=max(maxl,i-stack[-1])
                else:
                    stack.append(i)
        return maxl

799. 香槟塔
在这里插入图片描述
在这里插入图片描述

class Solution:
    def champagneTower(self, poured: int, query_row: int, query_glass: int) -> float:
        dp = [[0 for _ in range(query_row + 2)] for _ in range(query_row + 2)]
        dp[0][0] = poured
        for i in range(query_row + 1):
            for j in range(i + 1):
                if dp[i][j] > 1:
                    dp[i + 1][j] += (dp[i][j] - 1) / 2
                    dp[i + 1][j + 1] += (dp[i][j] - 1) / 2
        return min(1, dp[query_row][query_glass])

287. 寻找重复数(快慢指针) (判断链表是否有环)
在这里插入图片描述
将数组看成链表,val是结点值也是下个节点的地址。因此这个问题就可以转换成判断链表有环
如果可以修改原数组,那么可以用遇到一个数变复数,或者哈希表
二分法太难想到了,不如判断有环

class Solution:
    def findDuplicate(self, nums: List[int]) -> int:
        slow,fast=0,0
        slow=nums[slow]
        fast=nums[nums[fast]]
        #说明入环了
        while slow !=fast:
            slow=nums[slow]
            fast=nums[nums[fast]]
        f1,f2=0,slow
        #为了找到环的入口
        while nums[f1]!=nums[f2]:
            f1=nums[f1]
            f2=nums[f2]
        return nums[f1]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值