竞赛链接
新鲜出炉今天的周赛, 上周周末出去玩了所以没有更新, 这周重新恢复
这场周赛感觉难度适中, 我的发挥也不错, 最终排到了 23 名, 可能题目也是我比较熟悉的类型吧
题目难度: 简单
原题链接
给你一个数组 nums ,数组中有 2n 个元素,按 [x1,x2,…,xn,y1,y2,…,yn] 的格式排列。
请你将数组按 [x1,y1,x2,y2,…,xn,yn] 格式重新排列,返回重排后的数组。
nums = [2,5,1,3,4,7], n = 3
[2,3,5,4,1,7]
由于 x1=2, x2=5, x3=1, y1=3, y2=4, y3=7 ,所以答案为 [2,3,5,4,1,7]
nums = [1,2,3,4,4,3,2,1], n = 4
[1,4,2,3,3,2,4,1]
nums = [1,1,2,2], n = 2
[1,2,1,2]
class Solution:
def shuffle(self, nums: List[int], n: int) -> List[int]:
res = []
for i in range(n):
res.append(nums[i])
res.append(nums[i + n])
return res
class Solution
{
public:
vector<int> shuffle(vector<int> &nums, int n)
{
auto res = vector<int>();
for (int i = 0; i < n; ++i)
{
res.push_back(nums[i]);
res.push_back(nums[i + n]);
}
return res;
}
};
题目难度: 中等
原题链接
给你一个整数数组 arr 和一个整数 k 。
设 m 为数组的中位数,只要满足下述两个前提之一,就可以判定 arr[i] 的值比 arr[j] 的值更强:
请返回由数组中最强的 k 个值组成的列表。答案可以以 任意顺序 返回。
中位数 是一个有序整数列表中处于中间位置的值。形式上,如果列表的长度为 n ,那么中位数就是该有序列表(下标从 0 开始)中位于 ((n - 1) / 2) 的元素。
例如 arr = [6, -3, 7, 2, 11],n = 5:数组排序后得到 arr = [-3, 2, 6, 7, 11] ,数组的中间位置为 m = ((5 - 1) / 2) = 2 ,中位数 arr[m] 的值为 6 。
例如 arr = [-7, 22, 17, 3],n = 4:数组排序后得到 arr = [-7, 3, 17, 22] ,数组的中间位置为 m = ((4 - 1) / 2) = 1 ,中位数 arr[m] 的值为 3 。
1 <= arr.length <= 10^5
-10^5 <= arr[i] <= 10^5
1 <= k <= arr.length
arr = [1,2,3,4,5], k = 2
[5, 1]
arr = [1,1,3,5,5], k = 2
[5, 5]
中位数为 3, 按从强到弱顺序排序后,数组变为 [5,5,1,1,3]。最强的两个元素是 [5, 5]。
arr = [6,7,11,7,6,8], k = 5
[11,8,6,6,7]
((n - 1) / 2)
个元素, 降到 O(N))class Solution:
def getStrongest(self, arr: List[int], k: int) -> List[int]:
n = len(arr)
# 先排序求中位数
arr = sorted(arr)
mid = arr[(n - 1) // 2]
def mykey(x):
# 自定义最强排序的key函数
# 注意py 3不同于其他语言的传入两个参数的自定义比较函数
# 此处的意思代表先按照abs升序排列, 相等情况下再按照自身的值的升序排列
return (abs(x - mid), x)
# 按照最强排序后取最后的k个即为所求
arr = sorted(arr, key=mykey)
return arr[n - k:]
class Solution
{
public:
vector<int> getStrongest(vector<int> &arr, int k)
{
auto n = arr.size();
sort(arr.begin(), arr.end());
auto mid = arr[(n - 1) / 2];
sort(arr.begin(), arr.end(), [&](int x, int y) -> bool { return abs(x - mid) < abs(y - mid) || abs(x - mid) == abs(y - mid) && x < y; });
return vector<int>(arr.begin() + n - k, arr.end());
}
};
题目难度: 中等
原题链接
你有一个只支持单个标签页的 浏览器 ,最开始你浏览的网页是 homepage ,你可以访问其他的网站 url ,也可以在浏览历史中后退 steps 步或前进 steps 步。
请你实现 BrowserHistory 类:
BrowserHistory(string homepage) ,用 homepage 初始化浏览器类。
void visit(string url) 从当前页跳转访问 url 对应的页面 。执行此操作会把浏览历史前进的记录全部删除。
string back(int steps) 在浏览历史中后退 steps 步。如果你只能在浏览历史中后退至多 x 步且 steps > x ,那么你只后退 x 步。请返回后退 至多 steps 步以后的 url 。
string forward(int steps) 在浏览历史中前进 steps 步。如果你只能在浏览历史中前进至多 x 步且 steps > x ,那么你只前进 x 步。请返回前进 至多 steps 步以后的 url 。
1 <= homepage.length <= 20
1 <= url.length <= 20
1 <= steps <= 100
homepage 和 url 都只包含 ‘.’ 或者小写英文字母。
最多调用 5000 次 visit, back 和 forward 函数。
[null,null,null,null,“facebook.com”,“google.com”,“facebook.com”,null,“linkedin.com”,“google.com”,“leetcode.com”]
class BrowserHistory:
def __init__(self, homepage: str):
# 初始化访问主页, 下标为0
self.q = [homepage]
self.i = 0
def visit(self, url: str) -> None:
# 移除当前网页后面的所有网页
while self.i < len(self.q) - 1:
self.q.pop()
self.q.append(url)
self.i += 1
def back(self, steps: int) -> str:
# 新的下标要大于等于0
self.i = max(0, self.i - steps)
return self.q[self.i]
def forward(self, steps: int) -> str:
# 新的下标要小于列表长度
self.i = min(len(self.q) - 1, self.i + steps)
return self.q[self.i]
class BrowserHistory
{
public:
BrowserHistory(string homepage)
{
q.push_back(homepage);
i = 0;
}
void visit(string url)
{
while (i < q.size() - 1)
{
q.pop_back();
}
q.push_back(url);
++i;
}
string back(int steps)
{
i = max(0, i - steps);
return q[i];
}
string forward(int steps)
{
i = min(int(q.size()) - 1, i + steps);
return q[i];
}
private:
vector<string> q;
int i;
};
题目难度: 困难
原题链接
在一个小城市里,有 m 个房子排成一排,你需要给每个房子涂上 n 种颜色之一(颜色编号为 1 到 n )。有的房子去年夏天已经涂过颜色了,所以这些房子不需要被重新涂色。
我们将连续相同颜色尽可能多的房子称为一个街区。(比方说 houses = [1,2,2,3,3,2,1,1] ,它包含 5 个街区 [{1}, {2,2}, {3,3}, {2}, {1,1}] 。)
给你一个数组 houses ,一个 m * n 的矩阵 cost 和一个整数 target ,其中:
请你返回房子涂色方案的最小总花费,使得每个房子都被涂色后,恰好组成 target 个街区。如果没有可用的涂色方案,请返回 -1 。
houses = [0,0,0,0,0], cost = [[1,10],[10,1],[10,1],[1,10],[5,1]], m = 5, n = 2, target = 3
9
houses = [0,2,1,2,0], cost = [[1,10],[10,1],[10,1],[1,10],[5,1]], m = 5, n = 2, target = 3
11
houses = [3,1,2,3], cost = [[1,1,1],[1,1,1],[1,1,1],[1,1,1]], m = 4, n = 3, target = 3
-1
dp[i,j,b]
表示第 i 个房子, 涂成 j 颜色, 组成 b 个 block 的最小花费min(dp[m-1,x,target]) (1<=x<=n)
dp[i,j,b] = min(dp[i-1,jj,b-1]+cost[i][j], dp[i-1,j,b]+cost[i][j]) (1<=jj<=n 且 jj!=j)
dp[i,houses[i],b] = min(dp[i-1,jj,b-1], dp[i-1,houses[i],b]) (1<=jj<=n 且 jj!=houses[i])
class Solution:
def minCost(self, houses: List[int], cost: List[List[int]], m: int, n: int,
target: int) -> int:
dp = collections.defaultdict(int)
res = float('inf')
for i in range(m):
# paint表示是否需要涂色
paint = True
if houses[i] != 0:
# colors表示当前可选的颜色
colors = [houses[i]]
# 已有颜色, 不需要涂色
paint = False
else:
colors = range(1, n + 1)
for j in colors:
# 计算涂成当前颜色时的cost, 注意已有颜色的情况下cost就是0
curcost = (0 if not paint else cost[i][j - 1])
ii = i - 1
if i == 0:
# 第0号房子, 前面没有房子, 所以街区数一定为1, 花费也就是curcost
dp[i, j, 1] = curcost
continue
for jj in range(1, n + 1):
for b in range(i + 1):
# 街区数一定不会超过当前的房子数, 因为极限情况也是一个房子一个街区
if (ii, jj, b) in dp:
# 根据前一个房子的颜色计算当前的街区数
if j == jj:
newb = b
else:
newb = b + 1
# 更新当前dp值
if (i, j, newb) not in dp:
dp[i, j, newb] = dp[ii, jj, b] + curcost
else:
dp[i, j, newb] = min(
dp[i, j, newb],
dp[ii, jj, b] + curcost,
)
if i == m - 1 and target == newb:
# 更新最终结果值
res = min(res, dp[i, j, newb])
# 如果最终结果仍为inf的话则说明不存在这样的涂色方案, 返回-1
return res if res != float('inf') else -1
class Solution
{
public:
int minCost(vector<int> &houses, vector<vector<int>> &cost, int m, int n, int target)
{
// 三维dp数组, 初始化为最大int, 各个维度的长度略大于最大m或n即可
auto dp = vector<vector<vector<int>>>(102, vector<vector<int>>(22, vector<int>(102, INT_MAX)));
int res = INT_MAX;
vector<int> allcolors;
for (int i = 0; i < m; ++i)
{
bool paint = true;
// 这里改用存起点和终点
int startcolor = 1;
int endcolor = n;
if (houses[i] != 0)
{
startcolor = endcolor = houses[i];
paint = false;
}
for (int j = startcolor; j <= endcolor; ++j)
{
int curcost = paint ? cost[i][j - 1] : 0;
int ii = i - 1;
if (i == 0)
{
dp[i][j][1] = curcost;
}
else
{
for (int jj = 1; jj <= n; ++jj)
{
for (int b = 0; b <= i; ++b)
{
if (dp[ii][jj][b] != INT_MAX)
{
int newb = j == jj ? b : b + 1;
dp[i][j][newb] = min(dp[i][j][newb], dp[ii][jj][b] + curcost);
if (i == m - 1 && target == newb)
{
res = min(res, dp[i][j][newb]);
}
}
}
}
}
}
}
return res == INT_MAX ? -1 : res;
}
};
大家可以在下面这些地方找到我~
我的知乎专栏
我的 CSDN
我的 Leetcode
我的牛客网博客
我的公众号: 每日精选算法题, 欢迎大家扫码关注~