首页 > 编程语言 >juejin算法题_10月27

juejin算法题_10月27

时间:2024-10-27 19:21:17浏览次数:5  
标签:lf 10 27 str1 样例 len range juejin rt

https://juejin.cn/problemset

小R正在研究DNA序列,他需要一个函数来计算将一个受损DNA序列(dna1)转换成一个未受损序列(dna2)所需的最少编辑步骤。编辑步骤包括:增加一个碱基、删除一个碱基或替换一个碱基。

测试样例
样例1:

输入:dna1 = "AGT",dna2 = "AGCT"
输出:1

样例2:

输入:dna1 = "AACCGGTT",dna2 = "AACCTTGG"
输出:4


-------------------------------------------------
思路:动态规划,划分成子问题。
a[i][j]代表dna1前i个转化成dna2前j个序列所需要的编辑次数,有
	a[i][j]=a[i-1][j-1]    (dna1[i]==dna2[j]的情况下)
	a[i][j]=min(a[i-1][j],a[i][j-1],a[i-1][j-1])+1           (dna1[i]!=dna2[j]的情况下)
import sys
import re

    
def edit_distance(dna1, dna2):
    dp = [[0 for _ in range(len(dna2) + 1)] for _ in range(len(dna1) + 1)]
    
    for i in range(1, len(dp)):
        dp[i][0] = i
    for j in range(1, len(dp[0])):
        dp[0][j] = j
    
    for i in range(1, len(dp)):
        for j in range(1, len(dp[0])):
            if dna1[i-1] == dna2[j-1]:
                dp[i][j] = dp[i-1][j-1]
            else:
                dp[i][j] = min(dp[i-1][j] + 1, dp[i][j-1] + 1, dp[i-1][j-1] + 1)  
    
    return dp[-1][-1]

def parse_dna(input_str):
    matches = re.findall(r'(\w+)\s*=\s*"([^"]+)"', input_str)
    return matches[0][1],matches[1][1]

if __name__ == "__main__":
    for line in sys.stdin:
        dna1,dna2 = parse_dna(line)
        print(edit_distance(dna1,dna2))

小F正在进行一个 AB 实验,需要从整数位置 x 移动到整数位置 y。每一步可以将当前位置增加或减少,且每步的增加或减少的值必须是连续的整数(即每步的移动范围是上一步的 -1,+0 或 +1)。首末两步的步长必须是 1。求从 x 到 y 的最少步数。

输入描述
输入包含两个整数 x 和 y,表示起始位置和目标位置。

输出描述
输出从 x 到 y 所需的最小步数。

测试样例
样例1:

输入:x_position = 12, y_position = 6
输出:4

--------------------------------------
思路:数论。找规律
根据x和y的距离,可以得到1,2出现一次、再3,4出现两次、再5,6出现三次、再7,8出现四次...
距离1,2,3,4,5,6,7,8,9...
步数1,2,3,3,4,4,5,5,5,6,6,6...
import sys
import re

def solution(x1,x2):
    dis = abs(x1-x2)
    if dis==0:
        return 0
    k=1
    p=0
    num=0
    y=0
    while(y<dis):
        y+=k
        p+=1
        num+=1
        if(p==2):
            p=0
            k+=1
    return num
    
def parse_num(input_str):
    matches = re.findall(r'(\w+)\s*=\s*(-*[0-9]+)', input_str)
    return matches[0][1],matches[1][1]

if __name__ == "__main__":
    for line in sys.stdin:
        x1,x2 = parse_num(line)
        x1 = int(x1)
        x2 = int(x2)
        print(solution(x1,x2))

小F得到了一个特殊的字符串,这个字符串只包含字符A、S、D、F,其长度总是4的倍数。他的任务是通过尽可能少的替换,使得A、S、D、F这四个字符在字符串中出现的频次相等。求出实现这一条件的最小子串长度。

测试样例
样例1:

输入:input = "ADDF"
输出:1

样例2:

输入:input = "ASAFASAFADDD"
输出:3

样例3:

输入:input = "SSDDFFFFAAAS"
输出:1

--------------------------------------------------
思路:爆搜。暴力枚举每个区间,长度为n就枚举n*(n+1)/2次
统计这个区间左边和右边区间里,ASDF这四个字母分别出现的总次数,出现总次数都小于len(字符串长度)/4就是一个解。从所有可能的解中取最小值即可
import sys
import re

def solution(str1):
    lf = [[0 for _ in range(len(str1)+2)] for _ in range(4)]
    rt = [[0 for _ in range(len(str1)+2)] for _ in range(4)]
    for i in range(len(str1)):
        lf[0][i+1]=lf[0][i]
        lf[1][i+1]=lf[1][i]
        lf[2][i+1]=lf[2][i]
        lf[3][i+1]=lf[3][i]
        if(str1[i]=='A'):
            lf[0][i+1]+=1
        if(str1[i]=='S'):
            lf[1][i+1]+=1
        if(str1[i]=='D'):
            lf[2][i+1]+=1
        if(str1[i]=='F'):
            lf[3][i+1]+=1
    for i in range(len(str1)-1,-1,-1):
        rt[0][i+1]=rt[0][i+2]
        rt[1][i+1]=rt[1][i+2]
        rt[2][i+1]=rt[2][i+2]
        rt[3][i+1]=rt[3][i+2]
        if(str1[i]=='A'):
            rt[0][i+1]+=1
        if(str1[i]=='S'):
            rt[1][i+1]+=1
        if(str1[i]=='D'):
            rt[2][i+1]+=1
        if(str1[i]=='F'):
            rt[3][i+1]+=1
    
    
    
    res = len(str1)
    length = len(str1)/4
    for L in range(1,len(str1)+1):
        for R in range(L-1,len(str1)+1):
            x1 = lf[0][L-1]+rt[0][R+1]
            x2 = lf[1][L-1]+rt[1][R+1]
            x3 = lf[2][L-1]+rt[2][R+1]
            x4 = lf[3][L-1]+rt[3][R+1]
            if(x1<=length and x2<=length and x3<=length and x4<=length):
                res = min(res,R-L+1)
    return res

if __name__ == "__main__":
    str1 = "AAAADDDDAAAASSSS"
    print(solution(str1))

小R面对一个问题,她有两个由数字字符组成的超大字符串数,需要求出这两个数相加后得到的字符串数中的最大数和最小数之间的位数差距。如果结果中所有数字都相同,则差距为 0。如果存在多个符合最大或最小条件的数,应该选择最小的位置差。

例如,字符串数 "111" 和 "222" 相加得到 "333",所有数字相同,因此位数差为 0。另一例子,字符串数 "111" 和 "34" 相加得到 "145",其中最大数是 '5' 位于第 3 位,最小数是 '1' 位于第 1 位,他们之间的位差为 1。

测试样例
样例1:

输入:string1 = "111",string2 = "222"
输出:0

样例2:

输入:string1 = "111",string2 = "34"
输出:1

样例3:

输入:string1 = "999",string2 = "1"
输出:0
---------------------------------------------
思路:爆搜。
有最大值的索引和有最小值的索引各自用列表存放起来,用二重for循环枚举取最小值
import sys
import re

def solution(s1,s2):
    s1 = list(map(int,s1))
    s2 = list(map(int,s2))
    s3 = add(s1,s2)
    maxx=s3[0]
    idx_maxx=[0]
    minn=s3[0]
    idx_minn=[0]
    for idx,i in enumerate(s3):
        if(maxx<i):
            maxx = i
            idx_maxx = [idx]
        elif (maxx==i):
            idx_maxx.append(idx)
        
        if(minn>i):
            minn = i
            idx_minn = [idx]
        elif(minn==i):
            idx_minn.append(idx)
    
    x = len(s3)
    for i in idx_maxx:
        for j in idx_minn:
            x = min(x,abs(i-j))
    
    if(x==0):
        return 0
    return x-1
    
    
def add(s1, s2):

    length = max(len(s1), len(s2))
    s1.reverse()
    s2.reverse()
    while length - len(s1) > 0:
        s1.append(0)
    while length - len(s2) > 0:
        s2.append(0)
    s3 = []
    t = 0
    for i in range(length):
        if s1[i] + s2[i] + t < 10:
            s3.append(s1[i] + s2[i] + t)
            t = 0
        else:
            s3.append((s1[i] + s2[i] + t) % 10)
            t = 1
    if t == 1:
        s3.append(1)
    s3.reverse()

    return s3

if __name__ == "__main__":
    s1 = "1"
    s2 = "22222"
    print(solution(s1,s2))
n 个整数两两相加可以得到 n(n - 1) / 2 个和。我们的目标是:根据这些和找出原来的 n 个整数。

按非降序排序返回这 n 个数,如果无解,输出 "Impossible"。

测试样例
样例1:

输入:n = 3, sums = [1269, 1160, 1663]
输出:"383 777 886"

样例2:

输入:n = 3, sums = [1, 1, 1]
输出:"Impossible"

样例3:

输入:n = 5, sums = [226, 223, 225, 224, 227, 229, 228, 226, 225, 227]
输出:"111 112 113 114 115"
--------------------------------------------------
思路:数论。
首先, 这n(n - 1) / 2个数中可能有负数,那么就先把所有的数加上个偏置变成非负数,最后再把偏置减回去。
把这n(n - 1) / 2个数都变成非负数有个好处,就是可以确定加上偏置后的长度为n(n - 1) / 2序列,的长度为n的原序列中,所有的数都是非负数。(因为a0+a1>=0,且a0<a1,所以只有x0可能为负数,但是x0是负数的时候,比如[-1,2,3,4],和[0,1,2,5]是等价的,也就等价于x0是非负数)
现在问题就变成了给定n(n - 1) / 2个非负数,求原来的n个非负数。
从0到a0//2枚举x0,再判断x0确定的情况下,能不能从a0,a1,...中分出x1,x2,...。因为x0确定了,又知道a0,那就能算出x1。找到x1了,就能找到x1+x0并把这个数从数列中删除。接下来找到的最小的数一定是x2+x0,再把这个数减去x0后就确定了x2。找到x2了,就能找到x2+x0,x2+x1并把这两个数从数列中删除。以此类推找到所有的数。
import sys
import re

def f(u,n,sums):
    a=[]
    a.append(u)
    for i in range(1,n):
        xx = sums[0]-a[0]
        for x in a:
            if x+xx not in sums:
                return 0,[]
            sums.remove(x+xx)
        a.append(xx)
    return 1,a

def solution(n,sums):
    sums.sort()
    bias = 0
    if(sums[0]<0):
        bias = -sums[0]
        if(bias%2==1):
            bias+=1
        sums = [i+bias for i in sums]
    fl=0
    a=[]
    # print(sums)
    for i in range(0,sums[0]//2+1):
        P=list(sums)
        fl,a=f(i,n,P)
        if(fl==1):
            break
    
    if(fl==0):
        return "Impossible"
    else:
        a = [i-bias//2 for i in a]
        return ' '.join(map(str, a))
    


if __name__ == "__main__":#sb出题人,你管这叫中等?
    #  You can add more test cases here
    print(solution(5, [-1, 0, -1, -2, 1, 0, -1, 1, 0, -1]))
    # print(solution(3, [1, 1, 1]) == "Impossible")
    # print(solution(5, [226, 223, 225, 224, 227, 229, 228, 226, 225, 227]) == "111 112 113 114 115")
    # print(solution(5, [-1, 0, -1, -2, 1, 0, -1, 1, 0, -1]) == "-1 -1 0 0 1")
    # print(solution(5, [79950, 79936, 79942, 79962, 79954, 79972, 79960, 79968, 79924, 79932]) == "39953 39971 39979 39983 39989")

标签:lf,10,27,str1,样例,len,range,juejin,rt
From: https://www.cnblogs.com/zhuangzhongxu/p/18508799

相关文章

  • 如何解决VMware 安装Windows10系统出现Time out EFI Network
    一、问题描述使用VMware17安装windows10出现如下图所示TimeoutEFINetwork…Windows10镜像为微软官方下载的ISO格式镜像;二、问题分析VMware17默认的固件类型是UEFI(E),而微软官网下载的Windows10ISO格式镜像不支持UEFI(E),支持BIOS(B),将固件类型更改为BIOS(B)即可。三......
  • 备战蓝桥杯JAVA B组Day10
    备战蓝桥杯JAVAB组Day10目录备战蓝桥杯JAVAB组Day10前言P1428小鱼比可爱P1427小鱼的数字游戏P5727【深基5.例3】冰雹猜想P1047[NOIP2005普及组]校门外的树P5728【深基5.例5】旗鼓相当的对手前言零基础小白备战蓝桥杯第十天,刷题内容为:洛谷题单【入门3】循......
  • Nexpose 6.6.274 发布下载,新增功能概览
    Nexpose6.6.274发布下载,新增功能概览Nexpose6.6.274forLinux&Windows-漏洞扫描Rapid7VulnerabilityManagement,releasedOct16,2024请访问原文链接:https://sysin.org/blog/nexpose-6/查看最新版。原创作品,转载请保留出处。作者主页:sysin.org您的本地......
  • 【2024-10-27】连岳摘抄
    23:59生活就是这样变幻莫测:一会儿是满天云雾,转眼间又出现灿烂的太阳。                                                 ——奥斯特洛夫斯基你们两人都能干且负责,尤......
  • 20241027CF
    A.RectangleArrangement来晚了,没有说法B.StalinSort绷不住了,这个题在做的时候想了一个贪心结论,就是选择最后留下的上升序列中最多数留下来首先这个结论不对就不应该先去打补丁然后中间想了个选数留下的,居然没有深入想最后,不应该在这个题上用超过10分钟引以为戒C.A......
  • 10.24程序员节娱乐赛
    10.24程序员节娱乐赛前言10.24程序员节快乐,祝各位程序员新的一年里,代码如诗,bug无踪,算法神速,数据如龙,运维无忧,测试顺利,技术无界,创新不断!A题面不好写由于疫情原因,今年的天梯赛改在了11月28日进行。以下是今年天梯赛正式比赛的相关要求:竞赛时长为3小时。竞赛中3个不......
  • #【2024年10月26日更新】植物大战僵尸杂交本V2.6更新内容与下载
    更新内容新增植物:英雄植物:终极射手、向日葵公主、汉堡王(仅限英雄模式使用)。星卡植物:星星盒子、猫窝、迷幻投手、玉米旋转机(需要一定数量的星星解锁)。挑战植物:金卡黄金锤子、金卡联动贴吧版雷果子、钻卡车轮重塑者(通过特定挑战关卡解锁)。新增模式:梦幻联动:与up主轻柔......
  • 【2024年10月26日更新】植物大战僵尸杂交本V2.6更新内容与下载(包含历史版本)
    更新内容总结:新增植物:英雄植物:终极射手、向日葵公主、汉堡王(仅限英雄模式)。星卡植物:星星盒子、猫窝、迷幻投手、玉米旋转机(需星星解锁)。挑战植物:金卡黄金锤子、金卡雷果子、钻卡车轮重塑者(通过挑战解锁)。新增模式:梦幻联动:与up主轻柔北风合作的“植物大战僵尸贴吧版”。......
  • Java面试题及答案整理( 2024年 10 月最新版,持续更新)
    1.抽象类必须要有抽象方法吗?不需要,抽象类不一定非要有抽象方法。 普通类不能包含抽象方法,抽象类可以包含抽象方法。抽象类不能直接实例化,普通类可以直接实例化。2.抽象类能使用final修饰吗?不能,定义抽象类就是让其他类继承的,如果定义为final该类就不能被继承,这样彼......
  • 如果并发1000个请求url,通过虚拟线程应该怎么处理
    在Java中,如果要通过虚拟线程(VirtualThreads)处理1000个并发请求,能够有效提升吞吐量,同时避免传统线程池模型的线程资源开销。虚拟线程是JDK19引入的ProjectLoom的一部分,在JDK21中正式成为LTS版的稳定特性。下面是一个使用虚拟线程并发1000个请求的示例代码,并解释它的工作原理。......