LeetCode:每日一题【第八周】

1636. 按照频率将数组升序排序 【自定义排序】

思路

先用Counter内置函数,统计每个数字出现的次数,再按照题目规则对其排序得到list,遍历即可

AC代码

class Solution:
    def frequencySort(self, nums: List[int]) -> List[int]:
        cnt = Counter(nums)
        cnt = sorted(cnt.items(), key=lambda x:(x[1], -x[0]))  # 变成list
        ans = []
        for v, num in cnt:
            while num > 0:
                num -= 1
                ans.append(v)
        return ans

优化

class Solution:
    def frequencySort(self, nums: List[int]) -> List[int]:
        cnt = Counter(nums)
        nums.sort(key=lambda x:(cnt[x], -x))
        return nums

698. 划分为k个相等的子集【DFS+剪枝】

思路

先判断是否是nums的和是否是num的倍数,如果是则有可能被划分成num个子集。然后记录s为每个子集的和。
通过dfs遍历将nums[i]尝试放到cur数组中。cur数组设定为num个子集,存放被划分的子集和。

AC代码

class Solution:
    def canPartitionKSubsets(self, nums: List[int], num: int) -> bool:
        def dfs(i):
            if i == len(nums):
               return True
            for j in range(num):
                if j and cur[j] == cur[j - 1]:
                    continue 
                cur[j] += nums[i]
                if cur[j] <= s and dfs(i + 1):
                    return True
                cur[j] -= nums[i] # 回溯
            return False
        s, mod = divmod(sum(nums), num)
        if mod:
            return False
        cur = [0] * num
        nums.sort(reverse=True)
        return dfs(0)

854. 相似度为 K 的字符串【DFS回溯】

思路

枚举两个字符串对应位置,如果不相同,则s2往后找,找到和s1位置相同的字符,且当前的s2位置的字符不能和当前的s1位置的字符相同,不然会做重复操作,这点就是剪枝。

AC代码

class Solution:
    def kSimilarity(self, st1: str, st2: str) -> int:
        def dfs(s1, s2, st, cur):
            nonlocal ans # 将ans设置为全局变量
            if cur >= ans: # 如果枚举到比最优解还长的解直接返回最优解的长度
                return ans
            if st == n1 - 1:
                ans = min(ans, cur) # 枚举到最后一个位置,更新ans的值
                return ans
            for i in range(st, n1):
                if s1[i] != s2[i] : # 如果两个字符不对应,就交换
                    for j in range(i + 1, n2):
                        if s2[j] == s1[i] and s2[j] != s1[j]: # 找到s2中与s1中当前位置对应的字符交换
                            s2[i], s2[j] = s2[j], s2[i] # 将两个位置进行交换
                            dfs(s1, s2, i + 1, cur + 1) # 递归判断下一个位置
                            s2[i], s2[j] = s2[j], s2[i] # 回溯,枚举下一种可能
                    return ans
            ans = min(ans, cur)
            return ans

        st1, st2 = list(st1), list(st2)
        n1, n2 = len(st1), len(st2)
        ans = 10**9 + 7
        return dfs(st1, st2, 0, 0)

1640. 能否连接形成数组【哈希表】

思路

将pieces数组的每个子数组的第一个元素,与他的下标作为一个哈希,然后判断arr[i]是否在这个哈希表中。

  • 如果不在,则说明通过对pieces进行子数组间的交换不能和arr一样。
  • 如果在,则在判断arr[i:i+len§]是否和p相同,p为子数组。

AC代码

class Solution:
    def canFormArray(self, arr: List[int], pieces: List[List[int]]) -> bool:
        index = {p[0] : i for i, p in enumerate(pieces)}

        i = 0
        while i < len(arr):
            if arr[i] not in index:
                return False
            p = pieces[index[arr[i]]]
            if arr[i : i+len(p)] != p:
                return False
            i = i + len(p)

        return True

707. 设计链表 【模拟】

思路

按照题目模拟链表

AC代码

class LinkNode:
    def __init__(self, val):
        self.val = val
        self.next = None

class MyLinkedList:

    def __init__(self):
        self.size = 0
        self.head = LinkNode(0) # 带头的单向链表

    def get(self, index: int) -> int:
        if index < 0 or index >= self.size:
            return -1
        t = self.head
        for _ in range(index + 1): # 第0个位置的元素是无效结点(只是头节点)
            t = t.next
        return t.val

    def addAtHead(self, val: int) -> None:
        self.addAtIndex(0, val)

    def addAtTail(self, val: int) -> None:
         self.addAtIndex(self.size, val)


    def addAtIndex(self, index: int, val: int) -> None:
        if index > self.size:
            return
        index = max(index, 0)
        self.size += 1
        pred = self.head
        for _ in range(index):
            pred = pred.next
        add_node = LinkNode(val)
        add_node.next = pred.next
        pred.next = add_node

    def deleteAtIndex(self, index: int) -> None:
        if index < 0 or index >= self.size:
            return
        self.size -= 1
        pred =self.head
        for _ in range(index):
            pred = pred.next
        pred.next = pred.next.next

1652. 拆炸弹【构造循环数组】

思路

将code数组多加一个code数组在后面,这样可计算每个元素的前(后)k个元素的和。

AC代码

class Solution:
    def decrypt(self, code: List[int], k: int) -> List[int]:
        n = len(code)
        ans = [0] * n
        if k == 0:
            return ans
        code += code
        if k > 0:
            for i in range(n):
                ans[i] = sum(code[i + 1: i + 1 + k])
        if k < 0:
            for i in range(n, 2 * n):
                ans[i - n] = sum(code[i + k: i])
        return ans

788. 旋转数字 【模拟】

思路

根据题意,判断每位数字是否满足题意即可。

AC代码

class Solution:
    def rotatedDigits(self, n: int) -> int:
        ans = 0
        for i in range(1, n + 1):
            j = i
            x, y = 0, 0
            l = 0
            while j > 0:
                l += 1
                t = j % 10
                if t == 2 or t == 5 or t == 6 or t == 9:
                    x += 1
                if t == 1 or t == 0 or t == 8:
                    y += 1
                j //= 10
            if x + y == l and x > 0:
                ans += 1
        return ans
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星空皓月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值