力扣周赛333

38 阅读3分钟

力扣周赛333

2056. 二进制矩阵中的特殊位置

题目描述

给你一个 m x n 的二进制矩阵 mat。如果一个单元格中有且仅有一个 1,我们称它为 特殊位置

请你返回矩阵中 特殊位置 的数目。

题解思路

一种简单的方法是遍历矩阵中的每个元素,如果它是 1,就检查它所在的行和列是否都只有一个 1。如果是,就说明它是一个特殊位置,否则不是。这样做的时间复杂度是 O(mn * (m + n)),空间复杂度是 O(1)

另一种优化的方法是预处理矩阵,用两个数组分别记录每行和每列的 1 的个数。这样就可以在 O(1) 的时间内判断一个元素是否是特殊位置。这样做的时间复杂度是 O(mn),空间复杂度是 O(m + n)

代码实现

class Solution:
    def numSpecial(self, mat: List[List[int]]) -> int:
        # 预处理每行和每列的1的个数
        m, n = len(mat), len(mat[0])
        row = [0] * m # row[i]表示第i行的1的个数
        col = [0] * n # col[j]表示第j列的1的个数
        for i in range(m):
            for j in range(n):
                if mat[i][j] == 1:
                    row[i] += 1
                    col[j] += 1
        
        # 遍历矩阵,统计特殊位置的数目
        ans = 0
        for i in range(m):
            for j in range(n):
                if mat[i][j] == 1 and row[i] == 1 and col[j] == 1:
                    ans += 1
        
        return ans

2057. 最小化目标值与所选元素的差

题目描述

给你三个长度相同的整数数组 nums1nums2nums3,请你从每个数组中选出一个元素,组成一个大小为 3 的数组。

设选出的元素分别为 abc,请你返回一个 最小化 的结果:|a - b| + |b - c| + |c - a|

题解思路

一种直观的方法是枚举所有可能的组合,计算每个组合的结果,并取最小值。这样做的时间复杂度是 O(n^3),空间复杂度是 O(1)

另一种优化的方法是先对三个数组进行排序,然后使用三个指针分别指向三个数组的当前元素。每次计算当前指针所指元素的结果,并更新最小值。然后移动指向最小元素的指针,直到有一个数组遍历完毕。这样做的时间复杂度是 O(nlogn),空间复杂度是 O(1)

代码实现

class Solution:
    def minAbsDifference(self, nums1: List[int], nums2: List[int], nums3: List[int]) -> int:
        # 对三个数组进行排序
        nums1.sort()
        nums2.sort()
        nums3.sort()
        
        # 使用三个指针分别指向三个数组的当前元素
        i, j, k = 0, 0, 0
        n = len(nums1)
        
        # 初始化最小值为无穷大
        ans = float('inf')
        
        # 遍历三个数组,直到有一个数组遍历完毕
        while i < n and j < n and k < n:
            # 计算当前指针所指元素的结果
            a, b, c = nums1[i], nums2[j], nums3[k]
            res = abs(a - b) + abs(b - c) + abs(c - a)
            
            # 更新最小值
            ans = min(ans, res)
            
            # 移动指向最小元素的指针
            if a <= b and a <= c:
                i += 1
            elif b <= a and b <= c:
                j += 1
            else:
                k += 1
        
        return ans

2058. 找出最具竞争力的子序列

题目描述

给你一个整数数组 nums 和一个正整数 k,返回长度为 k 且最具 竞争力nums 子序列。

数组的子序列是从数组中删除一些元素(可能不删除元素)得到的序列。

在子序列 a 和子序列 b 第一个不相同的位置上,如果 a 中的数字小于 b 中对应的数字,那么我们称子序列 a 比子序列 b(相同长度下)更具 竞争力。例如,[1,3,4][1,3,5] 更具竞争力,在第一个不相同的位置,也就是最后一个位置上, 4 小于 5

题解思路

一种直观的方法是枚举所有长度为 k 的子序列,比较它们的竞争力,并取最小的一个。这样做的时间复杂度是 O(n^k),空间复杂度是 O(k)

另一种优化的方法是使用单调栈。单调栈是一种数据结构,它可以维护一个单调递增或递减的序列。我们可以从左到右遍历数组,每次遇到一个元素,就尝试将它加入单调栈中。如果加入后导致栈中元素个数超过 k,或者破坏了单调递减的性质,就弹出栈顶元素,直到满足条件为止。这样做可以保证栈中的元素是最具竞争力的子序列。这样做的时间复杂度是 O(n),空间复杂度是 O(k)

代码实现

class Solution:
    def mostCompetitive(self, nums: List[int], k: int) -> List[int]:
        # 使用单调栈
        stack = []
        n = len(nums)
        
        # 遍历数组
        for i in range(n):
            # 尝试将当前元素加入栈中
            num = nums[i]
            
            # 如果加入后导致栈中元素个数超过k,或者破坏了单调递减的性质,就弹出栈顶元素
            while stack and stack[-1] > num and len(stack) + n - i > k:
                stack.pop()
            
            # 如果栈中元素个数小于k,就加入当前元素
            if len(stack) < k:
                stack.append(num)
        
        # 返回栈中的元素作为结果
        return stack