leetcode刷题记录(Python)每日一题(2023):

1.1 简单 用时5min

2351. 第一个出现两次的字母

 注意!!!python创建空集合只能用set(),如果用{}创建的是字典。

class Solution:
    def repeatedCharacter(self, s: str) -> str:
        res = set()
        for x in s:
            if x not in res:
                res.add(x)
            else:
                return x
        return ""

1.2 中等 用时x 想了半小时没想出来

1801. 积压订单中的订单总数***

 想了很久没有想出合适复杂度的方法。看官解使用了优先队列。按照题意应该将sell由小到大排序,buy由大到小排序。

先复习一下优先队列的知识:(待填坑)

在python中可以使用堆来实现,操作有heappush和heappop,由于python的堆是小根堆,所以buy入队时将元素取负数,这也是常用的操作。

时间复杂度为O(nlogn),其中logn为每次处理优先队列的时间复杂度。空间复杂度为O(n)

class Solution:
    def getNumberOfBacklogOrders(self, orders: List[List[int]]) -> int:
        MOD = 10 ** 9 + 7
        buyOrders, sellOrders = [], []
        for price, amount, type in orders:
            if type == 0:
                while amount and sellOrders and sellOrders[0][0] <= price:
                    if sellOrders[0][1] > amount:
                        sellOrders[0][1] -= amount
                        amount = 0
                        break
                    amount -= heappop(sellOrders)[1]
                if amount:
                    heappush(buyOrders, [-price, amount])
            else:
                while amount and buyOrders and -buyOrders[0][0] >= price:
                    if buyOrders[0][1] > amount:
                        buyOrders[0][1] -= amount
                        amount = 0
                        break
                    amount -= heappop(buyOrders)[1]
                if amount:
                    heappush(sellOrders, [price, amount])
        return (sum(x for _, x in buyOrders) + sum(x for _, x in sellOrders)) % MOD

作者:力扣官方题解
链接:https://leetcode.cn/problems/number-of-orders-in-the-backlog/solutions/2039856/ji-ya-ding-dan-zhong-de-ding-dan-zong-sh-6g22/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

1.3 简单 用时 10min

2042. 检查句子中的数字是否递增

比较简单,但是时空复杂度都是O(n),按照官解那种一个一个字符遍历可以把空间复杂度压缩到O(1)。 

class Solution:
    def areNumbersAscending(self, s: str) -> bool:
        res = s.split(' ')
        num = 0
        for x in res:
            if x.isdigit():
                if int(x) <= num: return False
                else:num = int(x)
        return True 

1.4 中等 用时2h 

1802. 有界数组中指定下标处的最大值

通过将和划分成index的左边、index的右边、index,直接推出了和的表达式(由于我到处缺一少一错了四五次),于是就变成了解方程的查找问题,一开始用for循环超时了,想到用二分查找,第一反应是递归,然后递归层数太多过不了,改用while循环,通过。当然,这是个一元二次方程,也可以通过分情况去公式求解,即\frac{-b\pm \sqrt{b^{2}-4ac}}{2a}(没错我忘记了公式所以没用)。

反思:每次直接上手写,一瞬间想到更快的解法但是懒得想和写。

class Solution:
    def maxValue(self, n: int, index: int, maxSum: int) -> int:
        maxSum = maxSum - n
        left, right = 0, maxSum
        while left

看题解发现还可以用贪心算法加二分查找的方法。  下面贴上官方题解。

class Solution:
    def maxValue(self, n: int, index: int, maxSum: int) -> int: 
        left, right = 1, maxSum
        while left < right:
            mid = (left + right + 1) // 2
            if self.valid(mid, n, index, maxSum):
                left = mid
            else:
                right = mid - 1
        return left

    def valid(self, mid: int, n: int, index: int, maxSum: int) -> bool:
        left = index
        right = n - index - 1
        return mid + self.cal(mid, left) + self.cal(mid, right) <= maxSum

    def cal(self, big: int, length: int) -> int:
        if length + 1 < big:
            small = big - length
            return ((big - 1 + small) * length) // 2
        else:
            ones = length - (big - 1)
            return (big - 1 + 1) * (big - 1) // 2 + ones

作者:力扣官方题解
链接:https://leetcode.cn/problems/maximum-value-at-a-given-index-in-a-bounded-array/solutions/2042360/you-jie-shu-zu-zhong-zhi-ding-xia-biao-c-aav4/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

1.5 困难 不会

字典树 

1.6 简单 10min

2180. 统计各位数字之和为偶数的整数个数

class Solution:
    def countEven(self, num: int) -> int:
        s = 0
        n = num
        while n:
            s += n%10
            n = n//10
        if s % 2 == 0:
            return num//2
        else:
            return (num-1)//2

1.7 中等

1658. 将 x 减到 0 的最小操作数

滑动窗口! 竟然忘记了这个解法;注意外层的for循环,因为要最小的和为x的长度,所以如果少一层循环结果可能不是最小。

class Solution:
    def minOperations(self, nums: List[int], x: int) -> int:
        if len(nums)==1:
            return 1 if nums[0]==x else -1
        s = sum(nums)
        total = len(nums)+1
        right = 0
        for left in range(-1,len(nums)-1):
            if left!=-1: s+=nums[left]
            while rightx:
                    s-=nums[right]
                    right += 1
            if s==x:
                total = min(len(nums)-right+left+1, total)
                
        return total if total

1.8 简单 略

1.9 中等 30min

1806. 还原排列的最少操作步数

class Solution:
    def reinitializePermutation(self, n: int) -> int:
        perm = [i for i in range(n)]
        watch = [i for i in range(n)]
        arr = [0 for _ in range(n)]
        count = 0
        while arr!=watch:
            for i in range(n):
                if i%2 == 0:
                    arr[i] = perm[i//2]
                else:
                    arr[i] = perm[n//2 + (i-1)//2]
            perm = arr[:]
            count += 1

            if perm==watch:
                return count
        return -1
        

 1.10 困难 不会

753. 破解保险箱

 先取学习一下欧拉回路/通路

Hierholzer 算法如下:

我们从节点 uuu 开始,任意地经过还未经过的边,直到我们「无路可走」。此时我们一定回到了节点 uuu,这是因为所有节点的入度和出度都相等。

回到节点 uuu 之后,我们得到了一条从 uuu 开始到 uuu 结束的回路,这条回路上仍然有些节点有未经过的出边。我么从某个这样的节点 vvv 开始,继续得到一条从 vvv 开始到 vvv 结束的回路,再嵌入之前的回路中

下面这个图非常帮助理解,来自力扣 

leetcode刷题记录(Python)每日一题(2023):_第1张图片

 这个图让我想起来数字电路,知识真是相通的啊,太妙了。

class Solution:
    def crackSafe(self, n: int, k: int) -> str:
        seen = set()
        ans = list()
        highest = 10 ** (n - 1)

        def dfs(node: int):
            for x in range(k):
                nei = node * 10 + x
                if nei not in seen:
                    seen.add(nei)
                    dfs(nei % highest)
                    ans.append(str(x))

        dfs(0)
        return "".join(ans) + "0" * (n - 1)

作者:力扣官方题解
链接:https://leetcode.cn/problems/cracking-the-safe/solutions/393529/po-jie-bao-xian-xiang-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

1.11 简单

2283. 判断一个数的数字计数是否等于数位的值 

注意一下数据类型就行,还有如果没有用Counter,注意出现次数0在字典中没有的情况。 

class Solution:
    def digitCount(self, num: str) -> bool:
        h = Counter(num)
        for idx, v in enumerate(num):
            if h[str(idx)] != int(v):
                return False
        return True

1.12 中等

1807. 替换字符串中的括号内容

看着答案提醒才做出来,注意不在括号里的要怎么处理。我一开始是想直接替换,结果python字符串是不可变的,然后试着用切片的方法,但是忽略了修改字符串后原来记下的括号的索引也变了!!所以想着改字符串是行不通的,还是得数组。

class Solution:
    import re
    def evaluate(self, s: str, knowledge: List[List[str]]) -> str:
        d = dict(knowledge)
        
        n = len(s)
        i = 0
        res = []
        while i

1.13 简单

2287. 重排字符形成目标字符串

自己只对s做了哈希表,然后一遍遍遍历target,我真傻555。

# 我的
class Solution:
    def rearrangeCharacters(self, s: str, target: str) -> int:
        dic = Counter(s)
        res = 0
        flag = 1
        while flag:
            for i in target:
                if i in dic and dic[i]>0:
                    dic[i]-=1
                else:
                    flag = 0
                    break
            if flag: res+=1
        return res

# 官解下面一个人的一行代码
class Solution:
    def rearrangeCharacters(self, s: str, target: str) -> int:
        return min(Counter(s)[i] // v for i, v in Counter(target).items())

你可能感兴趣的:(leetcode,算法,职场和发展)