LeetCode第 118 场双周赛
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(n∗Li) , L i L_i Li代表 w o r d s [ i ] words[i] words[i]的字符串的长度
空间复杂度: O ( 1 ) O(1) O(1)
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 2∗1,但需要找到最大正方形空洞,因此如果对应横向的长度为1,最大正方形面积仍然为 1 ∗ 1 1 * 1 1∗1,即 m i n ( x , y ) 2 min(x, y) ^ 2 min(x,y)2 。
如果抽走若干条横线段,为使纵向的长度不断增大,则这若干条横线段的编号应该连续,此时纵向的最大长度为 抽走横线段数量 + 1 抽走横线段数量 + 1 抽走横线段数量+1。对于纵线段也是如此。
为便于计算编号连续的线段的数量,需要将hBars
和 vBars
进行升序排序。
代码:
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. 购买水果需要的最少金币数 中等
分析:
题意理解:
- 第一个水果肯定是要花钱买的。
- 如果买了第
j
个水果,那么j
后面的j
个水果可以免费(即 [ j + 1 , 2 ∗ j + 1 ] [j+1, 2*j+1] [j+1,2∗j+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])+∑n−402∗dp[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[i−1][1],dp[i−1][0])
最后在 d p [ n − 1 ] [ 0 ] dp[n-1][0] dp[n−1][0]与 d p [ n − 1 ] [ 1 ] dp[n-1][1] dp[n−1][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 2∗n的数组,因此总的空间复杂度: S ( n ) = O ( n ) S(n) = O(n) S(n)=O(n)