【LeetCode双周赛】第 118 场双周赛

LeetCode第 118 场双周赛

  • 2942. 查找包含给定字符的单词 简单
  • 2943. 最大化网格图中正方形空洞的面积 中等
  • 2944. 购买水果需要的最少金币数 中等

2942. 查找包含给定字符的单词 简单

2942. 查找包含给定字符的单词

分析:
按照题意模拟即可,只需要遍历words,判断 x 是否在对应下标的字符串中。

代码:

python代码

class Solution:
    def findWordsContaining(self, words: List[str], x: str) -> List[int]:
        return [i for i, s in enumerate(words) if x in s]

时间复杂度: O ( n ∗ L i ) O(n*L_i) O(nLi) L i L_i Li代表 w o r d s [ i ] words[i] words[i]的字符串的长度

空间复杂度: O ( 1 ) O(1) O(1)


2943. 最大化网格图中正方形空洞的面积 中等

2943. 最大化网格图中正方形空洞的面积

分析:
网格中,有横线段 n+2 条、竖线段m+2条,编号从 1 开始。
除去横竖边缘的两条,hBars 包含 [ 2 , n + 1 ] [2, n+1] [2,n+1] 中若干条横线段、vBars 包含 [ 2 , m + 1 ] [2, m+1] [2,m+1] 中若干条竖线段。

如果抽走一条横线段,那么纵向的长度最大变成了2,此时最大的 矩形 面积为 2 ∗ 1 2 * 1 21,但需要找到最大正方形空洞,因此如果对应横向的长度为1,最大正方形面积仍然为 1 ∗ 1 1 * 1 11,即 m i n ( x , y ) 2 min(x, y) ^ 2 min(x,y)2

如果抽走若干条横线段,为使纵向的长度不断增大,则这若干条横线段的编号应该连续,此时纵向的最大长度为 抽走横线段数量 + 1 抽走横线段数量 + 1 抽走横线段数量+1。对于纵线段也是如此。

为便于计算编号连续的线段的数量,需要将hBarsvBars 进行升序排序。

代码:

class Solution:
    def maximizeSquareHoleArea(self, n: int, m: int, hBars: List[int], vBars: List[int]) -> int:
        ln = len(hBars)
        lm = len(vBars)
        hBars=sorted(hBars)
        vBars=sorted(vBars)
        i=0
        lh=0
        while i<ln:
            j=i
            i+=1
            while i<ln and hBars[i]-hBars[i-1]==1:
                i+=1
            lh=max(lh,i-j)
        i=0
        lv=0
        while i<lm:
            j=i
            i+=1
            while i<lm and vBars[i]-vBars[i-1]==1:
                i+=1
            lv=max(lv,i-j)
        return min(lh+1, lv+1)*min(lh+1, lv+1)

时间复杂度: 排序时间复杂度 O ( n l o g n ) + O ( m l o g m ) O(nlogn) + O(mlogm) O(nlogn)+O(mlogm),遍历时间复杂度 O ( n ) + O ( m ) O(n) + O(m) O(n)+O(m),因此总的时间复杂度: T ( n , m ) = O ( n l o g n ) + O ( m l o g m ) T(n,m) = O(nlogn) + O(mlogm) T(n,m)=O(nlogn)+O(mlogm)

空间复杂度: 只创建了常数个变量,总的空间复杂度: S ( n ) = O ( 1 ) S(n) = O(1) S(n)=O(1)


2944. 购买水果需要的最少金币数 中等

2944. 购买水果需要的最少金币数

分析:
题意理解:

  • 第一个水果肯定是要花钱买的。
  • 如果买了第 j 个水果,那么 j 后面的 j 个水果可以免费(即 [ j + 1 , 2 ∗ j + 1 ] [j+1, 2*j+1] [j+1,2j+1]),也可以花钱买。

定义 i 为水果的下标,dp[i] 代表着选择第 i 个水果的花费,有两种选择:dp[i][0] :第 i 个水果免费取得的最小花费、dp[i][1]: 第 i 个水果花钱购买的最小花费。
转移方程:
d p [ i ] [ 0 ] = { p r i c e s [ 0 ] i = = 0 m i n ( d p [ j ] [ 1 ] ) + ∑ n − 4 0 2 ∗ d p [ i ] i > 0 \begin{equation} dp[i][0]=\begin{cases} prices[0] &i==0 \\ min_{}(dp[j][1]) + \sum_{n-4}^{0} 2*dp[i]&i>0 \end{cases} \end{equation} dp[i][0]={prices[0]min(dp[j][1])+n402dp[i]i==0i>0

d p [ i ] [ 1 ] = m i n ( d p [ i − 1 ] [ 1 ] , d p [ i − 1 ] [ 0 ] ) \begin{equation} dp[i][1]=min_{}(dp[i-1][1], dp[i-1][0]) \end{equation} dp[i][1]=min(dp[i1][1],dp[i1][0])

最后在 d p [ n − 1 ] [ 0 ] dp[n-1][0] dp[n1][0] d p [ n − 1 ] [ 1 ] dp[n-1][1] dp[n1][1]中选择更小的花销

代码:
python代码:

class Solution:
    def minimumCoins(self, prices: List[int]) -> int:
        n=len(prices)
        p  = [[0 for j in range(2)] for i in range(n)]
        p[0][1]=p[0][0]= prices[0]
        print(p)
        for i in range(1,n):
            j=i-1
            t = 10 ** 8
            while j>=0 and 2*j + 1 >=i:
                t=min(t,p[j][1])
                j-=1
            p[i][0]=t
            p[i][1]=min(p[i-1][0], p[i-1][1])+prices[i]
        print(p)
        return min(p[n-1][0], p[n-1][1])

时间复杂度: 有两层循环,内层循环也趋于 O ( n ) O(n) O(n)。因此总的时间复杂度: T ( n ) = O ( n 2 ) T(n) = O(n^2) T(n)=O(n2)

空间复杂度: 创建了一个 2 ∗ n 2 * n 2n的数组,因此总的空间复杂度: S ( n ) = O ( n ) S(n) = O(n) S(n)=O(n)

你可能感兴趣的:(LeetCode,leetcode,算法)