热题系列10

18 篇文章 0 订阅
13 篇文章 0 订阅

97. 交错字符串

在这里插入图片描述
题解:动态规划

dp[i][j]表示s[0:i-1]与s[0:j-1]是否可以交错组成s3[0:i+j-1]

1.dp[0][0]=True

2.dp[i][0] = dp[i-1][0] && s1[i-1]==s3[i-1]

3.dp[0][j] = dp[0][j-1] && s2[j-1]==s3[j-1]

4.dp[i][j] = (dp[i-1][j] and s1[i-1]==s3[i+j-1]) or (dp[i][j-1] and s2[j-1]==s3[i+j-1])

在这里插入图片描述

class Solution(object):
    def isInterleave(self, s1, s2, s3):
        lens1 = len(s1)
        lens2 = len(s2)
        lens3 = len(s3)
        if lens1+lens2!=lens3:
            return False
        dp = [[False for i in range(lens2+1)]for j in range(lens1+1)]
        dp[0][0]=True
        for i in range(1,lens1+1):
            dp[i][0] = dp[i-1][0]==True and s1[i-1]==s3[i-1]
        for j in range(1,lens2+1):
            dp[0][j] = dp[0][j-1]==True and s2[j-1]==s3[j-1]
        for i in range(1,lens1+1):
            for j in range(1,lens2+1):
                dp[i][j]=(dp[i-1][j]==True and s1[i-1]==s3[i+j-1])or (dp[i][j-1]==True and s2[j-1]==s3[i+j-1])
        print(dp)
        return dp[lens1][lens2]

264. 丑数 II

在这里插入图片描述
丑数中每个数字都可以由丑数序列u_numbers中之前的数字乘以2 3 5得到
1.用三个idx2 idx3 idx5记录分别用u_numbers中哪个数字乘以2 3 5,idx初始化为0,u_numbers初始化为[1]。
2.分别计算u_numbers[idx2]*2 u_numbers[idx3]*3 u_numbers[idx5]*5,求出三个结果中的最小值next_num,加入u_numbers中,并将对应的idx+1。

class Solution:
    def nthUglyNumber(self, n: int) -> int:
        idx2 = 0
        idx3 = 0
        idx5 = 0
        u_numbers = [1]
        for i in range(n-1):
            number_2 = u_numbers[idx2]*2
            number_3 = u_numbers[idx3]*3
            number_5 = u_numbers[idx5]*5
            next_num = min(number_2,number_3,number_5)
            if next_num==number_2:
                idx2 = idx2+1
            if next_num==number_3:
                idx3 = idx3+1
            if next_num==number_5:
                idx5 = idx5+1
            u_numbers.append(next_num)
        return u_numbers[-1]

剑指 Offer 34. 二叉树中和为某一值的路径

输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。

路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)

# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回二维列表,内部每个列表表示找到的路径
    def FindPath(self, root, expectNumber):
        # write code here
        res = []
        if not root: 
            return res
        self.target = expectNumber
        self.dfs(root, res, [root.val])
        return res

    def dfs(self, root, res, path):
        # 和大于要求的整数,则直接换路搜索
        if sum(path)>self.target:
            return
        if not root.left and not root.right and sum(path) == self.target:
            res.append(path)
        if root.left:
            self.dfs(root.left, res, path + [root.left.val])
        if root.right:
            self.dfs(root.right, res, path + [root.right.val])

86. 分隔链表

在这里插入图片描述
题解:

创建两个链表,一个保存原始链表中值小于x的节点,一个保存原始链表中值大于等于x的节点,然后把后一个链表接在前一个链表之后。

1.创建两个链表smallerhead,greaterhead,一个保存原始链表中值比x小的节点,一个保存原始链表中值大于或等于x 的节点。
2.smaller=smallerhead greater=greaterhead。
3.对原始链表中每个节点进行判断,如果当前head.val<x,则smaller.next=head,同时smaller后移,否则greater.next=head,greater后移一个节点。
4.对原始链表每个节点判断完成后,将greater.next设为None,把greaterhead链表接在samller之后。
5.返回smallerhead.next。

class Solution(object):
    def partition(self, head, x):
        smallerhead = smaller = ListNode()
        greaterhead = greater = ListNode()
        while head:
            if head.val<x:
                smaller.next = head
                smaller = smaller.next
            else:
                greater.next = head
                greater = greater.next
            head = head.next
        greater.next = None
        smaller.next = greaterhead.next

        return smallerhead.next 

395. 至少有K个重复字符的最长子串

给你一个字符串 s 和一个整数 k ,请你找出 s 中的最长子串, 要求该子串中的每一字符出现次数都不少于 k 。返回这一子串的长度。

示例 1:
输入:s = “aaabb”, k = 3
输出:3
解释:最长子串为 “aaa” ,其中 ‘a’ 重复了 3 次。

示例 2:
输入:s = “ababbc”, k = 2
输出:5
解释:最长子串为 “ababb” ,其中 ‘a’ 重复了 2 次, ‘b’ 重复了 3 次。

提示:
1 <= s.length <= 104
s 仅由小写英文字母组成
1 <= k <= 105

方法一:递归
我们来看要实现的longestSubstring函数。
它接受参数“字符串s”和“出现次数k”,返回串中字母每个都在串中出现至少k kk次的最长子串长度
首先,我们遍历字符串中出现的每一种字母。对于某种字母,如果这种字母出现次数本来就不足k kk次,那么只要是包含这种字母的子串,必定不满足题目要求。
因此,我们就可以以这种字母为分界,研究不包含这种字母的部分是否是满足题意的子串(递归)

例如aaabcccc, k = 3,我们遍历字符串aaabcccc中出现过的每一种字母a、b、c
对于字母a,其出现次数满足“最少出现3次”
对于字母b,其出现次数不满足“最少出现3次”,因此以b为分隔,递归判断各个子串是否符合要求
以b为分隔,可以将原始字符串分割成两个子串,分别是aaa和cccc,我们对这两个子串分别计算longestSubstring,最优结果即为答案
对于字符串aaa:其中只包含字母a,且a出现的次数满足“最少出现3次”。也就是说这是一个满足题意的字符串,返回答案“3”
对于字符串cccc:其中只包含字母c,且c出现的次数满足“最少出现3次”。也就是说这是一个满足题意的字符串,返回答案“4”
因此递归结束后,最佳答案是4
对于字母c,其出现次数满足“最少出现3次”

class Solution:
    def longestSubstring(self, s: str, k: int) -> int:
        for c in set(s):
            if s.count(c) < k:
                return max(self.longestSubstring(substr, k) for substr in s.split(c))
        return len(s)

12. 整数转罗马数字

罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

字符          数值
I             1
V             5
X             10
L             50
C             100
D             500
M             1000

例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给定一个整数,将其转为罗马数字。输入确保在 1 到 3999 的范围内。

示例 1:
输入: 3
输出: “III”

示例 2:
输入: 4
输出: “IV”

示例 3:
输入: 9
输出: “IX”

示例 4:
输入: 58
输出: “LVIII”
解释: L = 50, V = 5, III = 3.

示例 5:
输入: 1994
输出: “MCMXCIV”
解释: M = 1000, CM = 900, XC = 90, IV = 4.

思路:
这道题和上次的罗马数字转整数刚好是相反的,但是都用到了同一个知识点,也就是Python中的字典,这里我将IV、IX等6种情况都直接在字典中写出来了,只需要通过for循环遍历字典中的每一个数,然后看哪些罗马字符能够组成给出的数。根据题目给的提示,比如num=1994,那么肯定需要一个1000,也就是M,然后剩下的字符肯定不包含M了,我们将num-1000,再看剩下的这些数由哪些字符组成,以此找到所有的字符,形成一个字符串。

class Solution:
    def intToRoman(self, num: int):
        dict = {'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}
        s = ''
        for i in dict:
            while dict[i] <= num:  # 判断当前字符需要几个
                s += i
                num-=dict[i]
        return s

316. 去除重复字母

给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小(要求不能打乱其他字符的相对位置)。

注意:该题与 1081 https://leetcode-cn.com/problems/smallest-subsequence-of-distinct-characters 相同

示例 1:
输入:s = “bcabc”
输出:“abc”

示例 2:
输入:s = “cbacdcbc”
输出:“acdb”
提示:
1 <= s.length <= 104
s 由小写英文字母组成

思路:
1.栈
2.比前一个字母的字母序小且后面还有重复的就弹出

class Solution:
    def removeDuplicateLetters(self, s: str) -> str:
        stack = []  
        for i, c in enumerate(s):          
            if c not in stack:
                while c < stack[-1] and stack[-1] in s[i + 1:]:
                    stack.pop()
                stack.append(c)
        return ''.join(stack[1:])

剑指 Offer 45. 把数组排成最小的数

题解一:
思路:将nums中数字重复,取前面几位有效位进行比较。比如3和32,都重复5次33333 3232323232,32323比33333小,因此32应该放在3之前。

1.定义一个dict strnums,对nums中每个数字转为str,重复5次取前10位,按照 在原nums中的序号:前10位格式加入strnums。
2.对strnums按照key从小到大排序。
3.创建新list newnums,按照排序后的strnums中在nums的序号依次将对应数字加入newnums。
4.将newnums中数字拼接为str。

class Solution:
    def minNumber(self, nums: List[int]) -> str:
        strnums = {}
        for i in range(len(nums)):
            strnumi =str(nums[i])*5
            strnumi = strnumi[0:10]
            strnums[i] = strnumi
        strlist = sorted(strnums.items(),key=lambda item:item[1])
        newnums = []
        for t in strlist:
            newnums.append(str(nums[t[0]]))
        result = "".join(newnums)
        return result
题解二:比较a+b与b+a,从而判断a与b顺序。

class Solution:
    def minNumber(self, nums: List[int]) -> str:
        def sort_rule(x, y):
            a, b = x + y, y + x
            if a > b:
                # 结果为大,返回一个正数
                return 1
            elif a < b:
                # 结果为小,返回一个负数
                return -1
            else:
                return 0

        strs = [str(num) for num in nums]
        strs.sort(key=functools.cmp_to_key(sort_rule))
        return ''.join(strs)

剑指 Offer 53 - I. 在排序数组中查找数字 I

统计一个数字在排序数组中出现的次数。
示例 1:
输入: nums = [5,7,7,8,8,10], target = 8
输出: 2

示例 2:
输入: nums = [5,7,7,8,8,10], target = 6
输出: 0

限制:
0 <= 数组长度 <= 50000

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        return nums.count(target)

  • 19
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值