京东20220903笔试


"""
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)




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值