将数组升序排序,遍历数组,如果nums[n - i] >= i and nums[n - i -1] < i则i满足条件。注意边界情况。
class Solution:
def specialArray(self, nums: List[int]) -> int:
nums = sorted(nums)
n = len(nums)
ans = -1
for i in range(1, 1001):
if n - i < 0:
break
if nums[n - i] >= i and (n - i == 0 or nums[n - i - 1] < i):
ans = i
break
return ans
这里如果数据量大,也可用二分来找i。但是话说回来,sorted的复杂度已经nlogn了,二分优化不了最大的复杂度,即原来的复杂度是O(nlogn + n),而优化过的复杂度是O(nlogn + logn)。
先将数的每位分离出来,之后可用交换排序的思想,找数组里面的最大元素,与当前元素做交换。
class Solution:
def maximumSwap(self, num: int) -> int:
arr = []
while num > 0:
arr.append(num % 10)
num //= 10
arr = list(reversed(arr))
n = len(arr)
# 交换排序
for i in range(n):
tmp = arr[i]
pos = i
flag = False
for j in range(n - 1, i, -1):
if arr[j] > tmp:
tmp = arr[j]
pos = j
flag = True
arr[i], arr[pos] = arr[pos], arr[i]
if flag:
break
ans = 0
for val in arr:
ans = ans * 10 + val
return ans
最小5%和最大5%就是数组排序后前n/20, 和后n/20的数,将其过滤,算中间数的平均值即可。
class Solution:
def trimMean(self, arr: List[int]) -> float:
arr = sorted(arr)
ans, n = 0, len(arr)
k = n // 20
for i in range(k, n - k):
ans += arr[i]
return ans / (n - k * 2)
枚举n=1-5的情况,p枚举1-4的情况,会发现答案只有1, 2, 3, 4, 7, 8,这六种答案。
class Solution:
def flipLights(self, n: int, p: int) -> int:
if p == 0:
return 1
if n == 1:
return 2
if n == 2:
return 3 if p == 1 else 4
if n > 2:
if p == 1:
return 4
return 7 if p == 2 else 8
不会,这题用了好几种算法
换个题吧
class Solution:
def maxSumMinProduct(self, nums: List[int]) -> int:
nums = [0] + nums + [0] # 添加两个哨兵作为单调栈的两个边界
pre_sum = [0]
for num in nums:
pre_sum.append(pre_sum[-1] + num)
n = len(nums)
rfs = [None] * n # right_first_smaller 找右边第一个比i小的
stack = []
for i in range(n):
while stack and nums[i] < nums[stack[-1]]:
rfs[stack.pop()] = i
stack.append(i)
lfs = [None] * n # left_first_smaller 找左边第一个比i小的
stack = []
for i in range(n - 1, -1, -1):
while stack and nums[i] < nums[stack[-1]]:
lfs[stack.pop()] = i
stack.append(i)
mx = 0
for i in range(1, n - 1):
r = rfs[i]
l = lfs[i]
mx = max(mx, nums[i] * (pre_sum[r] - pre_sum[l + 1]))
return mx % (10**9 + 7)
用字符映射,只存不同字符出现的第一个字符,然后判断后面字符串有相同字符,将其下标作差-1即可。
class Solution:
def maxLengthBetweenEqualCharacters(self, s: str) -> int:
tmp = [None] * 26
ans = -1
for i, ch in enumerate(s):
if tmp[ord(ch) - 97] != None:
ans = max(ans, i - tmp[ord(ch) - 97] - 1)
else:
tmp[ord(ch) - 97] = i
return ans
第一遍并查集:将所有连通的1合并的一个集合
第二遍并查集:判断当前值为0的周边值,如果为1,则可将0变成1再来看连通分量的大小是多少。
class Solution:
# 方法1并查集
def largestIsland(self, grid: List[List[int]]) -> int:
def find(a):
if f[a] != a:
f[a] = find(f[a])
return f[a]
def union(a, b):
fa, fb = find(a), find(b)
if fa != fb:
f[fa] = fb # fb为父亲
size[fb] += size[fa]
n = len(grid)
f = list(range(n * n))
size = [1] * (n * n)
for i, row in enumerate(grid):
for j, v in enumerate(row):
if v == 1: # 将连通的1合并为一个集合
for a, b in [[0, -1], [-1, 0]]: # python强大之处,不用遍历四个方向,因为左边界走完就到了右边界,上边界走完到了下边界。
x, y = i + a, j + b
if 0 <= x < n and 0 <= y < n and grid[x][y] == 1:
union(x * n + y, i * n + j) # 将其转化为1维进行合并
ans = max(size)
for i, row in enumerate(grid):
for j, v in enumerate(row):
vis = set()
t = 1
if v == 0:
for a, b in [[0, -1], [-1, 0], [0, 1], [1, 0]]:
x, y = i + a, j + b
if 0 <= x < n and 0 <= y < n and grid[x][y] == 1:
root = find(x * n + y)
if root not in vis:
vis.add(root)
t += size[root] # 累加周围连通块为1的集合大小
ans = max(ans, t)
return ans