[Leetcode Weekly Contest]196

链接: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

posted @ 2020-07-06 10:21  Jamest  阅读(226)  评论(0编辑  收藏  举报