记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步
目录
-
-
- [4/20 2078. 两栋颜色不同且距离最远的房子](#4/20 2078. 两栋颜色不同且距离最远的房子)
- [4/21 1722. 执行交换操作后的最小汉明距离](#4/21 1722. 执行交换操作后的最小汉明距离)
- [4/22 2452. 距离字典两次编辑以内的单词](#4/22 2452. 距离字典两次编辑以内的单词)
- [4/23 2615. 等值距离和](#4/23 2615. 等值距离和)
- [4/24 2833. 距离原点最远的点](#4/24 2833. 距离原点最远的点)
- [4/25 3464. 正方形上的点之间的最大距离](#4/25 3464. 正方形上的点之间的最大距离)
- 4/26
-
4/20 2078. 两栋颜色不同且距离最远的房子
假设有n个房子 如果首尾颜色不同 那么最远距离为n-1
如果首尾颜色相同 那么找和首或尾颜色不同的最远房子
python
def maxDistance(colors):
"""
:type colors: List[int]
:rtype: int
"""
n = len(colors)
if colors[0]!=colors[-1]:
return n-1
l,r=n-1,0
for i in range(n):
if colors[i]!=colors[-1]:
l = i
break
for i in range(n-1,-1,-1):
if colors[i]!=colors[0]:
r=i
break
return max(r,n-1-l)
4/21 1722. 执行交换操作后的最小汉明距离
并查集 将可以互换的位置连成并查集分量
每个分量分别统计 source 与 target 的值频次
分量内可任意重排,无法匹配的剩余数量即贡献到汉明距离
python
def minimumHammingDistance(source, target, allowedSwaps):
"""
:type source: List[int]
:type target: List[int]
:type allowedSwaps: List[List[int]]
:rtype: int
"""
from collections import defaultdict, Counter
n = len(source)
parent = list(range(n))
size = [1] * n
def find(x):
while parent[x] != x:
parent[x] = parent[parent[x]]
x = parent[x]
return x
def union(a, b):
ra, rb = find(a), find(b)
if ra == rb:
return
if size[ra] < size[rb]:
ra, rb = rb, ra
parent[rb] = ra
size[ra] += size[rb]
for a, b in allowedSwaps:
union(a, b)
groups_source = defaultdict(list)
groups_target = defaultdict(list)
for i in range(n):
root = find(i)
groups_source[root].append(source[i])
groups_target[root].append(target[i])
ans = 0
for root in groups_source:
cs = Counter(groups_source[root])
ct = Counter(groups_target[root])
for v, cnt in cs.items():
if cnt > ct[v]:
ans += cnt - ct[v]
return ans
4/22 2452. 距离字典两次编辑以内的单词
编辑两次相同 意味着只有两个位置的字符不同
依次判断每个query是否编辑两次后在dictionary中
python
def twoEditWords(queries, dictionary):
"""
:type queries: List[str]
:type dictionary: List[str]
:rtype: List[str]
"""
ans = []
def isTwoEdit(query, word):
diff = 0
for i in range(len(query)):
if query[i]!=word[i]:
diff+=1
if diff>2:
return False
return True
for query in queries:
for word in dictionary:
if isTwoEdit(query, word):
ans.append(query)
break
return ans
4/23 2615. 等值距离和
即arr[i]等于所有 nums[i]==nums[j] 的 j 与 i 的距离之和
1 按值分组,记录每个值出现的所有下标,递增。
2 在每个分组内,用前缀和prefix[i] = prefix[i-1] + p[i] 计算每个位置的距离和。
对分组有下标 p[0...k-1],当前位置 t 的答案为:
左侧贡献 = (p[t]-p[0])+(p[t]-p[1])+...+(p[t]-p[t-1])
= p[t] * t - (p[0] + ... + p[t-1])
同理
右侧贡献 = (p[t+1] + ... + p[k-1]) - p[t] * (k - 1 - t)
两者相加即该位置结果。
python
def distance(nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
from collections import defaultdict
n = len(nums)
ans = [0] * n
pos = defaultdict(list)
for i, v in enumerate(nums):
pos[v].append(i)
for p in pos.values():
k = len(p)
prefix = [0] * (k + 1)
for i in range(k):
prefix[i + 1] = prefix[i] + p[i]
total = prefix[k]
for t in range(k):
left = p[t] * t - prefix[t]
right = (total - prefix[t + 1]) - p[t] * (k - 1 - t)
ans[p[t]] = left + right
return ans
4/24 2833. 距离原点最远的点
记录R,L,_的个数
为了让距离更远 向个数更多的方向移动
返回max(R,L)+-min(R,L)
python
def furthestDistanceFromOrigin(moves):
"""
:type moves: str
:rtype: int
"""
r,l,u=0,0,0
for c in moves:
if c=='R':
r+=1
elif c=='L':
l+=1
else:
u+=1
return max(r,l)+u-min(r,l)
4/25 3464. 正方形上的点之间的最大距离
1 二分答案 d(最小曼哈顿距离),判断是否存在可行的 k 个点。
2 先把边界点按环顺序展开成线性序列:
左边(上行) -> 上边(右行) -> 右边(下行) -> 下边(左行)。
3 对固定 d 做线性 DP + 单调队列:
-状态记录一个可行序列的起点、终点和长度。
-扫描当前点 (x, y) 时,弹出所有与当前点终点距离 >= d 的队首状态,
尝试把其长度 +1 转移到当前点。
-同时要求当前点与该状态起点距离也 >= d,保证环上闭合后仍满足最小距离约束。
4 若某次检查可得到长度 >= k,则 d 可行;据此做二分。
python
def maxDistance(side, points, k):
"""
:type side: int
:type points: List[List[int]]
:type k: int
:rtype: int
"""
from collections import deque
from dataclasses import dataclass
@dataclass
class Sequence:
start_x: int
start_y: int
end_x: int
end_y: int
length: int
left = sorted((x, y) for x, y in points if x == 0 and y > 0)
top = sorted((x, y) for x, y in points if x > 0 and y == side)
right = sorted(
((x, y) for x, y in points if x == side and y < side),
reverse=True,
)
bottom = sorted(((x, y) for x, y in points if y == 0), reverse=True)
ordered = left + top + right + bottom
def ok(d):
"""
判断是否可以选出 k 个点,使得最小曼哈顿距离 >= d。
"""
dq = deque([Sequence(*ordered[0], *ordered[0], 1)])
best = 1
for x, y in ordered[1:]:
start_x, start_y = x, y
length = 1
while dq and abs(x - dq[0].end_x) + abs(y - dq[0].end_y) >= d:
# 既要和当前序列末尾满足距离,也要和序列开头满足距离,
# 这样维护出的链在环上闭合时依然合法。
if (
abs(x - dq[0].start_x) + abs(y - dq[0].start_y) >= d
and dq[0].length + 1 >= length
):
start_x = dq[0].start_x
start_y = dq[0].start_y
length = dq[0].length + 1
if length > best:
best = length
dq.popleft()
dq.append(Sequence(start_x, start_y, x, y, length))
return best >= k
lo, hi = 0, side
while lo < hi:
mid = (lo + hi + 1) // 2
if ok(mid):
lo = mid
else:
hi = mid - 1
return lo
4/26
python