"""
20道单选+3算法
1.找到n的一个因子p,使得其满足p*p >n, 要求p尽可能小
"""
def func1(n):
q = int(math.sqrt(n))
#q逐渐递减至1 直到 q**2 < n即可
while q >= 1:
if n%q == 0:
if q*q < n:
return n//q
q -= 1
import math
"""
一个数组,每次操作可以把数组中的一个数x进行下面两种变换之一
a. x拆成x-1与1
b. x拆成a与b 不过要满足a*b = x
问使得数组中全部元素为1需要的最少操作次数
"""
def func2(arr):
dp = [float('inf') for i in range(max(arr)+1)]
dp[1] = 0
for i in range(2,len(dp)):
dp[i] = min(dp[i], 1 + dp[i - 1])
left=2
right = int(math.sqrt(i))
for j in range(left, right+1):
if i%j == 0:
dp[i] = min(dp[i], 1+dp[j]+dp[i//j])
print(dp)
print(sum([dp[a] for a in arr]))
"""
一个由左右括号构成的子串的权值定义为:其有效子序列的最大长度
有效子序列指的是能满足括号匹配规则
求出字符串s的全部子串的权值和
例如())())的和为26
"""
def func3_old(s):
#oN2复杂度 超时,过了22%
#计算权值和 对子串i j如何计算其中最大的合法子序列长度呢? s的长度<2e5
#dp[i]代表s[0:i]的有效子序列长度
#怎么得到最长子序列? 取一个栈 如果当前是右括号 则判定栈是否非空
ans = 0
for i in range(len(s)):
stack = 0
count = 0
for j in range(i,len(s)):
if s[j] == '(':
stack+=1
else:
if stack > 0:
stack -= 1
count += 2
ans += count
print(ans)
def func3(s):
#优化版本,过了88.89%
dp = [0]#dp[i]记录了以s[i]为终点的子串的权值和, x则记录了s[0:i]中有多少个子串的left - right 是大于0的?
pre = [0] #pre记录了以s[i]为终点的子串中,有多少个是满足left > right的? pre[k]代表left-right=k的子串数目
for i in range(len(s)):
if s[i] == '(':
dp.append(dp[-1])
pre.append(0)
pre[1:] = pre[0:-1]
pre[1] += 1
pre[0] = i+1 - sum(pre[1:])
else:
dp.append(dp[-1]+2*sum(pre[1:]))
pre[0:-1] = pre[1:]
if len(pre) > 1:
pre.pop()
pre[0] = i+1 - sum(pre[1:])
#pre是一个列表pre[i]为left-right多i的数目
print(sum(dp))
def func3(s):
stack = []
ans = 0
i = 0
while i < len(s):
if s[i] == '(':
stack.append(i)
else:
if not stack:
i += 1
x1 = stack.pop()
# stack.pop()
ans += 2*(x1+1)*(len(s)-i)
i += 1
print(ans)
京东20220903笔试
于 2022-09-03 21:11:03 首次发布