1465. 切割后面积最大的蛋糕
Python3
直觉解法
class Solution:
def maxArea(self, h: int, w: int, horizontalCuts: List[int], verticalCuts: List[int]) -> int:
h_delta = []
v_delta = []
h1 = [0] + horizontalCuts + [h]
v1 = [0] + verticalCuts + [w]
h1.sort()
v1.sort()
for i in range(1, len(h1)):
h_delta.append(h1[i]-h1[i-1])
for i in range(1, len(v1)):
v_delta.append(v1[i]-v1[i-1])
return max(h_delta) * max(v_delta) % (10**9 + 7)
看官方题解后 改进
class Solution:
def maxArea(self, h: int, w: int, horizontalCuts: List[int], verticalCuts: List[int]) -> int:
h1 = [0] + horizontalCuts + [h]
v1 = [0] + verticalCuts + [w]
h1.sort()
v1.sort()
h_max = 0
for i in range(1, len(h1)):
h_max = max(h_max, h1[i]-h1[i-1])
v_max = 0
for i in range(1, len(v1)):
v_max = max(v_max, v1[i]-v1[i-1])
return h_max * v_max % (10**9 + 7)
官方解法: 由于只需要 最大的间隔,所以记录最大值即可
数组排序 花销 数组排序 花销
class Solution:
def maxArea(self, h: int, w: int, horizontalCuts: List[int], verticalCuts: List[int]) -> int:
horizontalCuts.sort()
verticalCuts.sort()
return (self.calMaxDelta(horizontalCuts, h) * self.calMaxDelta(verticalCuts, w)) % (10 ** 9 + 7)
# 子模块: 求最大间隔
def calMaxDelta(self, lis, boarder):
res = 0
pre = 0
for num in lis:
res = max(res, num - pre, res)
pre = num
return max(res, boarder - pre)
C++
class Solution {
public:
int maxArea(int h, int w, vector<int>& horizontalCuts, vector<int>& verticalCuts) {
int mod = 1e9 + 7;
sort(horizontalCuts.begin(), horizontalCuts.end());
sort(verticalCuts.begin(), verticalCuts.end());
return (long long)calMaxDelta(horizontalCuts, h) * calMaxDelta(verticalCuts, w) % mod;
}
// 子模块
long long calMaxDelta(vector<int> &arr, int boarder){
int res = 0, pre = 0;
for (int num : arr){
res = max(res, num - pre);
pre = num;
}
return max(res, boarder - pre);
}
};
2943. 最大化网格图中正方形空洞的面积
Python3
class Solution:
def maximizeSquareHoleArea(self, n: int, m: int, hBars: List[int], vBars: List[int]) -> int:
# 只有 Bars 里的 线段 可以 移除 整体是 1*1 网格,要形成更大的空洞,要求 可移除的Bar 应为 连续的。 转为 求解 hBars 和 vBars 里的 最大连续子序列 长度。 同时参考 1465. 切割后面积最大的蛋糕 的贪心思路
return min(self.calMaxDelta(hBars), self.calMaxDelta(vBars)) ** 2
# 子模块
def calMaxDelta(self, Bars):
mx = 2 # 至少可 移除 一根 , 长度 为 2
length = 2
for x, y in pairwise(sorted(Bars)):
if y - x == 1: ## 注意 可移除的连续子序列 前后 还有 两格 , 所以之前 置 2
length += 1
mx = max(mx, length) # 有可能会 一直等, 所以 不能放到 else 里
else: # 不等了, 重置 length
length = 2
return mx
class Solution:
def maximizeSquareHoleArea(self, n: int, m: int, hBars: List[int], vBars: List[int]) -> int:
# 只有 Bars 里的 线段 可以 移除 整体是 1*1 网格,要形成更大的空洞,要求 可移除的Bar 应为 连续的。 转为 求解 hBars 和 vBars 里的 最大连续子序列 长度。 同时参考 1465. 切割后面积最大的蛋糕 的贪心思路
return min(self.calMaxDelta(hBars), self.calMaxDelta(vBars)) ** 2
# 子模块
def calMaxDelta(self, Bars):
mx = 2 # 至少可 移除 一根 , 长度 为 2
length = 2
Bars.sort()
for i in range(1, len(Bars)):
if Bars[i] - Bars[i-1] == 1: ## 注意 可移除的连续子序列 前后 还有 两格 , 所以之前 置 2
length += 1
mx = max(mx, length) # 有可能会 一直等, 所以 不能放到 else 里
else: # 不等了, 重置 length
length = 2
return mx
class Solution:
def maximizeSquareHoleArea(self, n: int, m: int, hBars: List[int], vBars: List[int]) -> int:
# 只有 Bars 里的 线段 可以 移除 整体是 1*1 网格,要形成更大的空洞,要求 可移除的Bar 应为 连续的。 转为 求解 hBars 和 vBars 里的 最大连续子序列 长度。 同时参考 1465. 切割后面积最大的蛋糕 的贪心思路
return min(self.calMaxDelta(hBars), self.calMaxDelta(vBars)) ** 2
# 子模块
def calMaxDelta(self, Bars):
Bars.sort()
res = 0
i = 0
while i < len(Bars):
loc = i
i += 1 ##
while i < len(Bars) and Bars[i] - Bars[i-1] == 1:
i += 1 #
res = max(res, i - loc + 1) #
return res
不用排序的写法
class Solution:
def maximizeSquareHoleArea(self, n: int, m: int, hBars: List[int], vBars: List[int]) -> int:
# 只有 Bars 里的 线段 可以 移除 整体是 1*1 网格,要形成更大的空洞,要求 可移除的Bar 应为 连续的。 转为 求解 hBars 和 vBars 里的 最大连续子序列 长度。 同时参考 1465. 切割后面积最大的蛋糕 的贪心思路
return min(self.calMaxDelta(hBars), self.calMaxDelta(vBars)) ** 2
# 子模块
def calMaxDelta(self, Bars):
mx = 2 # 记录 最大长度 由于 至少 有一根 可移除的 Bar, 因此 长度至少 为2
for bar in Bars:
length = 0
if bar - 1 in Bars:
continue
while bar in Bars:
length += 1 # 包含了 起始的 一格
bar += 1
mx = max(mx, length + 1) # 要加上 后面 那一格
return mx
C++
排序后 比较
class Solution {
public:
int maximizeSquareHoleArea(int n, int m, vector<int>& hBars, vector<int>& vBars) {
int a = min(calMaxDelta(hBars), calMaxDelta(vBars));
return a * a;
}
// 子模块: 求解 最长间隔 最长可删除序列
int calMaxDelta(vector<int> & Bars){
int mx = 2;
int length = 2;
sort(Bars.begin(), Bars.end());
for (int i = 1; i < Bars.size(); ++i){
if (Bars[i] - Bars[i-1] == 1){
length += 1;
mx = max(mx, length);
}
else{
length = 2;
}
}
return mx;
}
};
不用排序 查找 有时 比排序慢
class Solution {
public:
int maximizeSquareHoleArea(int n, int m, vector<int>& hBars, vector<int>& vBars) {
int a = min(calMaxDelta(hBars), calMaxDelta(vBars));
return a * a;
}
// 子模块: 求解 最长间隔 最长可删除序列
int calMaxDelta(vector<int> & Bars){
int mx = 2;
for (int bar : Bars){
int length = 0;
if (find(Bars.begin(), Bars.end(),bar-1) == Bars.end())
continue;
while (find(Bars.begin(), Bars.end(),bar-1) != Bars.end()){
length += 1;
bar += 1;
}
mx = max(mx, length + 1);
}
return mx;
}
};
2975. 移除栅栏得到的正方形田地的最大面积
Python3
class Solution:
def maximizeSquareArea(self, m: int, n: int, hFences: List[int], vFences: List[int]) -> int:
hF = [1] + hFences + [m]
vF = [1] + vFences + [n]
hF.sort()
vF.sort()
sh, sv = set(), set() # 存储 任意两个 栅栏之间的 间隔
for i in range(len(hF)):
for j in range(i+1, len(hF)):
sh.add(hF[j] - hF[i])
for i in range(len(vF)):
for j in range(i+1, len(vF)):
sv.add(vF[j] - vF[i])
# s = sh.intersection(sv) ## 求 边长交集
# 另一写法
mx = 0 # 找 最长 边
for val in sh:
if val in sv:
mx = max(mx, val)
if mx == 0:
return -1 # 无法 形成 正方形
return mx ** 2 % (10 ** 9 + 7)
class Solution:
def maximizeSquareArea(self, m: int, n: int, hFences: List[int], vFences: List[int]) -> int:
hF = [1] + hFences + [m]
vF = [1] + vFences + [n]
hF.sort()
vF.sort()
sh, sv = set(), set() # 存储 任意两个 栅栏之间的 间隔
for i in range(len(hF)):
for j in range(i+1, len(hF)):
sh.add(hF[j] - hF[i])
for i in range(len(vF)):
for j in range(i+1, len(vF)):
sv.add(vF[j] - vF[i])
# s = sh.intersection(sv) ## 求 边长交集
s = sh & sv
if len(s) == 0:
return -1 # 无法 形成 正方形
return max(s) ** 2 % (10 ** 9 + 7)
C++
class Solution {
unordered_set<int> f(vector<int> &a, int mx) {
a.push_back(1);
a.push_back(mx);
sort(a.begin(), a.end());
unordered_set<int> set;
for (int i = 0; i < a.size(); i++) {
for (int j = i + 1; j < a.size(); j++) {
set.insert(a[j] - a[i]);
}
}
return set;
}
public:
int maximizeSquareArea(int m, int n, vector<int> &hFences, vector<int> &vFences) {
auto h = f(hFences, m);
auto v = f(vFences, n);
// if (h.size() > v.size()) {
// swap(h, v);
// }
int ans = 0;
for (int x: h) {
if (v.contains(x)) {
ans = max(ans, x);
}
}
return ans ? (long long)ans * ans % 1'000'000'007 : -1;
}
};