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
嘶,感觉今天做的三道题就没用一个省心的,不过好在能学到一些东西还是不错的,这道题的主要思想就是定义一个排序的规则,然后使用快排对这个进行排序。
学到了使用内置函数进行排序,也就是对内置函数的规则进行定义。
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)