leetcode每日一题 + 巩固 + 微软题库

leetcode3086

3086. 拾起 K 个 1 需要的最少行动次数 - 力扣(LeetCode)

嘶,今天这道可不容易呀,看了两遍灵神题解+视频讲解,不过也收获满满

这道题要分情况讨论,因为max_c有可能很大,也有可能很小,因为如果是用两个位置互相转换的方法,肯定会需要操作次数更多,因为只有在当前位置次数才能是0,其他的就是这个位置周围距离为1的需要操作一次,而我们有max_c次机会来把周围的0变成1,这个需要操作两次,这个很显然比从远处把1拿过来更快,那么这种情况下经过计算,需要的答案就是max(c - 1,0) + (k - c) * 2这里面的c就是我们计算的连续的1的数量,这个c的取值只能是0,1,2,3。

然后就是max_c很小的时候了,这个时候灵神讲了一个货舱选址问题,这个刚好解决了最优位置的麻烦,然后再通过一次循环成功找到最小操作次数,这道题就的吃了。

这道题主要收获的就是中位数贪心来解决货舱选址,然后就是一个求数组前缀和的py函数accumlate这个函数你们可以去查一查,学习一下,还是很好用的。

货舱选址灵神讲解:中位数贪心 货仓选址【力扣周赛 389】_哔哩哔哩_bilibili

时间复杂度:O(n)

空间复杂度:O(n)

class Solution:
    def minimumMoves(self, nums: List[int], k: int, max_c: int) -> int:
        c = 0
        arr = []
        for i,j in enumerate(nums):
            if j == 1:
                arr.append(i)
                c = max(c,1)
                if i > 0 and nums[i - 1] == 1:
                    if i > 1 and nums[i - 2] == 1:
                        c = 3
                    else:
                        c = max(c,2)
        c = min(c,k)
        if max_c >= k - c:
            return max(c - 1,0) + (k - c) * 2
        n = len(arr)
        presum = list(accumulate(arr,initial = 0))
        ans = inf
        size = k - max_c
        for r in range(size,n + 1):
            l = r - size
            i = l + size // 2
            s1 = arr[i] * (i - l) - (presum[i] - presum[l])
            s2 = presum[r] - presum[i] - arr[i] * (r - i)
            ans = min(ans,s1 + s2)
        return ans + max_c * 2

leetcode2602

2602. 使数组元素全部相等的最少操作次数 - 力扣(LeetCode)

时间复杂度:O(nlogn+mlogn)

空间复杂度:O(n)

这道题很简单,先对数组进行排序,那么在q前面的就是减1,在q后面的就是加1,那么我们就需要用二分查找找到q的位置。

学到的函数:bisect_left(nums, q)找到数组nums中q的位置

class Solution:
    def minOperations(self, nums: List[int], queries: List[int]) -> List[int]:
        n = len(nums)
        nums.sort()
        s = list(accumulate(nums, initial=0))
        ans = []
        for q in queries:
            j = bisect_left(nums, q)
            left = q * j - s[j]
            right = s[n] - s[j] - q * (n - j) 
            ans.append(left + right)
        return ans

leetcode179

179. 最大数 - 力扣(LeetCode)

嘶,感觉今天做的三道题就没用一个省心的,不过好在能学到一些东西还是不错的,这道题的主要思想就是定义一个排序的规则,然后使用快排对这个进行排序。

学到了使用内置函数进行排序,也就是对内置函数的规则进行定义。

class Solution:
    def largestNumber(self, nums: List[int]) -> str:
        def quick_sort(l , r):
            if l >= r: 
                return
            i, j = l, r
            while i < j:
                while strs[j] + strs[l] >= strs[l] + strs[j] and i < j: 
                    j -= 1
                while strs[i] + strs[l] <= strs[l] + strs[i] and i < j: 
                    i += 1
                strs[i], strs[j] = strs[j], strs[i]
            strs[i], strs[l] = strs[l], strs[i]
            quick_sort(l, i - 1)
            quick_sort(i + 1, r)
        strs = [str(num) for num in nums]
        quick_sort(0, len(strs) - 1) 
        if strs[-1] == "0":
            return "0"
        return ''.join(strs[::-1])

使用内置函数(对内置函数的规则定义)

class Solution:
    def largestNumber(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 = cmp_to_key(sort_rule))
        if strs[0] == "0":
            return "0"
        return ''.join(strs)
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值