@@ -2167,4 +2167,190 @@ func findNumOfValidWords(words []string, puzzles []string) []int {
2167
2167
}
2168
2168
```
2169
2169
2170
- <!-- tabs:end -->
2170
+ <!-- tabs:end -->
2171
+
2172
+ ----
2173
+
2174
+ ## 第 157 场周赛
2175
+
2176
+ [ 点击前往第 157 场周赛] ( https://leetcode-cn.com/contest/weekly-contest-157 )
2177
+
2178
+ ### 5213. 玩筹码
2179
+
2180
+ [ 原题链接] ( https://leetcode-cn.com/contest/weekly-contest-157/problems/play-with-chips/ )
2181
+
2182
+ #### 暴力破解
2183
+
2184
+ ``` python
2185
+ class Solution :
2186
+ def minCostToMoveChips (self , chips : List[int ]) -> int :
2187
+ chip_set = set (chips)
2188
+ res = float (" inf" )
2189
+ for s in chip_set:
2190
+ tmp = 0
2191
+ for chip in chips:
2192
+ if chip > s:
2193
+ if (chip - s) % 2 == 1 :
2194
+ tmp += 1
2195
+ elif chip < s:
2196
+ if (s - chip) % 2 == 1 :
2197
+ tmp += 1
2198
+ else :
2199
+ pass
2200
+ if tmp <= res:
2201
+ res = tmp
2202
+ return res
2203
+ ```
2204
+
2205
+ #### 统计奇偶
2206
+
2207
+ 移动 2 位是无代价的,移动 1 位是有代价的,因此奇数位移动到奇数位或偶数位移动到偶数位是无代价移动,偶数位移动到奇数位或奇数位移动到偶数位需要花费代价 1。所以只要统计奇数位的筹码数和偶数位的筹码数,将少的一方移到多的一方即可。
2208
+
2209
+ ``` python
2210
+ class Solution :
2211
+ def minCostToMoveChips (self , chips : List[int ]) -> int :
2212
+ odd = 0
2213
+ even = 0
2214
+
2215
+ for chip in chips:
2216
+ if chip % 2 == 0 :
2217
+ even += 1
2218
+ else :
2219
+ odd += 1
2220
+
2221
+ return min (odd, even)
2222
+ ```
2223
+
2224
+ ### 5214. 最长定差子序列
2225
+
2226
+ [ 原题链接] ( https://leetcode-cn.com/contest/weekly-contest-157/problems/longest-arithmetic-subsequence-of-given-difference/ )
2227
+
2228
+ 把每一个数** 当前位置能构成的最长定差子序列长度** 用字典 ` dp ` 记录下来,遍历 ` arr ` 时,根据 ` difference ` 求出在定差子序列中该数的前一个数 ` pre = a - difference ` ,若 ` pre ` 存在 ` dp ` 中(已能构成定差子序列),则有 ` dp[a] = max(dp[a], dp[pre] + 1) ` ,否则令 ` dp[a] = 1 ` 。
2229
+
2230
+ ``` python
2231
+ class Solution :
2232
+ def longestSubsequence (self , arr : List[int ], difference : int ) -> int :
2233
+ dp = dict ()
2234
+ for a in arr:
2235
+ pre = a - difference
2236
+ if pre in dp:
2237
+ dp[a] = max (dp.get(a, 0 ), dp[pre] + 1 )
2238
+ else :
2239
+ dp[a] = 1
2240
+ return max ([x for _, x in dp.items()])
2241
+ ```
2242
+
2243
+ ### 5215. 黄金矿工
2244
+
2245
+ [ 原题链接] ( https://leetcode-cn.com/contest/weekly-contest-157/problems/path-with-maximum-gold/ )
2246
+
2247
+ DFS 暴力挖矿。对挖过的格子进行标记,走到一个格子后,判断该格子四个方向的格子是否满足要求:
2248
+
2249
+ 1 . 不超过 ` grid ` 边界
2250
+ 2 . 黄金数目不为 ` 0 `
2251
+ 3 . 没有被挖过
2252
+
2253
+ 如果满足上述条件就继续 DFS 挖下去。
2254
+
2255
+ 伪代码大概长这样:
2256
+
2257
+ ```
2258
+ dfs(v) // v 可以是 grid 的一个坑
2259
+ 在 v 上打访问标记
2260
+ for u in v 的四个相邻坑位
2261
+ if (u 没有越界) and (u 有黄金) and (u 没有被挖过) then
2262
+ dfs(i)
2263
+ ```
2264
+
2265
+ 具体实现:
2266
+
2267
+ ``` python
2268
+ class Solution :
2269
+
2270
+ ans = 0
2271
+
2272
+ def getMaximumGold (self , grid : List[List[int ]]) -> int :
2273
+
2274
+ n = len (grid)
2275
+ m = len (grid[0 ])
2276
+
2277
+ """
2278
+ 获取方向
2279
+ """
2280
+ def get_directions (i , j , mark ):
2281
+ directions = []
2282
+ if i - 1 >= 0 and grid[i - 1 ][j] != 0 and (not mark[i - 1 ][j]):
2283
+ directions.append([i - 1 , j])
2284
+ if i + 1 < n and grid[i + 1 ][j] != 0 and (not mark[i + 1 ][j]):
2285
+ directions.append([i + 1 , j])
2286
+ if j - 1 >= 0 and grid[i][j - 1 ] != 0 and (not mark[i][j - 1 ]):
2287
+ directions.append([i, j - 1 ])
2288
+ if j + 1 < m and grid[i][j + 1 ] != 0 and (not mark[i][j + 1 ]):
2289
+ directions.append([i, j + 1 ])
2290
+
2291
+ return directions
2292
+
2293
+ """
2294
+ DFS
2295
+ """
2296
+ def dfs (i , j , mark , count ):
2297
+ # 打上访问标记
2298
+ mark[i][j] = True
2299
+ # 获得可走方向
2300
+ directions = get_directions(i, j, mark)
2301
+ # 无路可走时返回
2302
+ if len (directions) == 0 :
2303
+ self .ans = max (self .ans, count)
2304
+ return
2305
+ # 遍历方向
2306
+ for direction in directions:
2307
+ dfs(direction[0 ], direction[1 ], [x[:] for x in mark], count + grid[direction[0 ]][direction[1 ]]) # dfs
2308
+
2309
+ for i in range (n):
2310
+ for j in range (m):
2311
+ # 任意一个有黄金的单元格出发
2312
+ if grid[i][j] != 0 :
2313
+ mark = [[False for _ in range (m)] for _ in range (n)]
2314
+ dfs(i, j, mark, grid[i][j])
2315
+
2316
+ return self .ans
2317
+ ```
2318
+
2319
+ ### 5216. 统计元音字母序列的数目
2320
+
2321
+ [ 原题链接] ( https://leetcode-cn.com/contest/weekly-contest-157/problems/count-vowels-permutation/ )
2322
+
2323
+ 长度为 ` x ` 的字符串是由** 长度为 ` x - 1 ` 的合法字符串** ,根据其最后一个字母,追加一个符合规则的字母构成的。
2324
+
2325
+ 因此,如果我们要求长度为 ` x ` 的字符串个数,只需要知道长度为 ` x - 1 ` 的字符串中所有字符串最后一个字母的情况,从 ` n = 1 ` 开始一直推算到 ` n = x ` 。
2326
+
2327
+ ``` python
2328
+ class Solution :
2329
+ def countVowelPermutation (self , n : int ) -> int :
2330
+
2331
+ if n == 1 :
2332
+ return 5
2333
+
2334
+ map_dict = {" a" : [" e" ], " e" : [" a" , " i" ], " i" : [" a" , " e" , " o" , " u" ], " o" : [" i" , " u" ], " u" : [" a" ]}
2335
+ index = {" a" : 0 , " e" : 1 , " i" : 2 , " o" : 3 , " u" : 4 }
2336
+ c = {0 : " a" , 1 : " e" , 2 : " i" , 3 : " o" , 4 : " u" }
2337
+
2338
+ # aeiou 对应的个数
2339
+ pre = [1 , 1 , 1 , 1 , 1 ]
2340
+
2341
+ res = 0
2342
+
2343
+ for i in range (2 , n + 1 ):
2344
+ cur = [0 for _ in range (5 )]
2345
+ for j in range (len (pre)):
2346
+ cur_c = c[j] # 当前字母
2347
+ cur_c_count = pre[j] # 当前字母数量
2348
+ for map_c in map_dict[cur_c]: # 遍历可以跟随的字母
2349
+ map_c_index = index[map_c]
2350
+ cur[map_c_index] += cur_c_count
2351
+ pre = cur
2352
+
2353
+ res = sum (cur)
2354
+
2355
+ return res % (10 ** 9 + 7 )
2356
+ ```
0 commit comments