链接:LeetCode
[Leetcode]5452. 判断能否形成等差数列
给你一个数字数组 arr 。如果一个数列中,任意相邻两项的差总等于同一个常数,那么这个数列就称为 等差数列 。
如果可以重新排列数组形成等差数列,请返回 true ;否则,返回 false 。
排序后暴力即可。
class Solution:
def canMakeArithmeticProgression(self, arr: List[int]) -> bool:
arr.sort()
diff = arr[1]-arr[0]
for i in range(2,len(arr)):
if arr[i]-arr[i-1]!=diff:
return False
return True
[Leetcode]5453. 所有蚂蚁掉下来前的最后一刻
有一块木板,长度为 n 个 单位 。一些蚂蚁在木板上移动,每只蚂蚁都以 每秒一个单位 的速度移动。其中,一部分蚂蚁向 左 移动,其他蚂蚁向 右 移动。
当两只向 不同 方向移动的蚂蚁在某个点相遇时,它们会同时改变移动方向并继续移动。假设更改方向不会花费任何额外时间。
而当蚂蚁在某一时刻 t 到达木板的一端时,它立即从木板上掉下来。
给你一个整数 n 和两个整数数组 left 以及 right 。两个数组分别标识向左或者向右移动的蚂蚁在 t = 0 时的位置。请你返回最后一只蚂蚁从木板上掉下来的时刻。
两只蚂蚁碰面后不会改变任何数组,找最后到达的蚂蚁即可。
class Solution:
def getLastMoment(self, n: int, left: List[int], right: List[int]) -> int:
rightmin = min(right) if right else n
leftmax = max(left) if left else 0
return max(n-rightmin,leftmax)
[Leetcode]5454. 统计全 1 子矩形
给你一个只包含 0 和 1 的 rows * columns 矩阵 mat ,请你返回有多少个 子矩形 的元素全部都是 1 。
与统计正方形个数的题目类似,我们循环每一行,计算该行作为首行的前提下,有多少个子矩形。
class Solution:
def numSubmat(self, mat: List[List[int]]) -> int:
n,m = len(mat),len(mat[0])
res = 0
for i in range(n):
tmp = mat[i]
for j in range(i,n):
tmp = [x&y for x,y in zip(tmp,mat[j])]
res += self.get1(tmp)
return res
def get1(self,nums):
res = 0
result = 0
for i in range(len(nums)):
if nums[i] == 0:
result = 0
else:
result += 1
res += result
return res
[Leetcode]5455. 最多 K 次交换相邻数位后得到的最小整数
给你一个字符串 num 和一个整数 k 。其中,num 表示一个很大的整数,字符串中的每个字符依次对应整数上的各个 数位 。
你可以交换这个整数相邻数位的数字 最多 k 次。
请你返回你能得到的最小整数,并以字符串形式返回。
可以从最简单易行的暴力法开始优化。暴力法在每一次置换的时候查找满足条件间距小于k且比当前值小的最小值,时间复杂度(O(N^2))如下所示:
class Solution:
def minInteger(self, num: str, k: int) -> str:
num = list(num)
sorted_num = sorted(num)
if num == sorted_num or len(num) ** 2 < k:
return ''.join(sorted_num)
for i in range(len(num)):
if num[i]!=sorted_num[i] and k:
min_num = num[i]
min_ind = i
for j in range(i+1,min(len(num),i+k+1)):
if num[j] < min_num:
min_ind=j
min_num = num[j]
k -= (min_ind-i)
num = num[:i]+[num[min_ind]]+num[i:min_ind]+num[min_ind+1:]
return ''.join(num)
一种高效的代替方法是做预处理:记录下所有的0-9的位置然后用这些预处理的位置来进行查找,好处是每次查找时不需要重头开始遍历。
在每一次置换的过程中,需要将置换的数左侧ind+1,右侧保持不变, 由于需要对区间递增,可以采用线段树的方法简化复杂度(O(Nlog(N)))。
import collections
class Solution:
def minInteger(self, num: str, k: int) -> str:
numIndex = collections.defaultdict(list)
N = len(num)
for i in range(N):
numIndex[int(num[i])].append(i)
segemnt_nums = NumArray([0 for _ in range(N)])
res = ''
for i in range(N):
for n in range(10):
if not numIndex[n]:continue
min_ind = numIndex[n][0]
new_ind = segemnt_nums.sumRange(min_ind+1,N-1)+min_ind
if new_ind-i > k:
continue
k -= (new_ind-i)
numIndex[n].pop(0)
segemnt_nums.add(min_ind,1)
res += str(n)
break
return res
#Segment tree node
class Node(object):
def __init__(self, start, end):
self.start = start
self.end = end
self.total = 0
self.left = None
self.right = None
class NumArray(object):
def __init__(self, nums):
def createTree(nums, l, r):
if l > r:
return None
if l == r:
n = Node(l, r)
n.total = nums[l]
return n
mid = (l + r) // 2
root = Node(l, r)
root.left = createTree(nums, l, mid)
root.right = createTree(nums, mid+1, r)
root.total = root.left.total + root.right.total
return root
self.root = createTree(nums, 0, len(nums)-1)
def add(self, i, val):
def addVal(root, i, val):
if root.start == root.end:
root.total += val
return root.total
mid = (root.start + root.end) // 2
if i <= mid:
addVal(root.left, i, val)
else:
addVal(root.right, i, val)
root.total = root.left.total + root.right.total
return root.total
return addVal(self.root, i, val)
def sumRange(self, i, j):
if i>j:return 0
def rangeSum(root, i, j):
if root.start == i and root.end == j:
return root.total
mid = (root.start + root.end) // 2
if j <= mid:
return rangeSum(root.left, i, j)
elif i >= mid + 1:
return rangeSum(root.right, i, j)
else:
return rangeSum(root.left, i, mid) + rangeSum(root.right, mid+1, j)
return rangeSum(self.root, i, j)
参考:
Leetcode