算法小试炼(差不多相当于重新过一遍ACWING,为了夏令营做点准备)

news2025/1/20 1:58:06

1.最长不重复子串

这个题目的具体意思就不用我说了,我这里给出两种算法

1)暴力搜索

只要机器够快,没有什么是暴搜解决不了的^ ^(开玩笑
很简单,我们只需要遍历长度,跟左边界就好了,这个应该没什么好说的

s = input()
n = len(s)
def solve(s):  # 判断字符串是否有重复,返回True 代表没重复
    charstr = set()
    for ch in s:
        if ch in charstr:
            return False
        charstr.add(ch)
    return True

res = 1
for maxl in range(2,n + 1):   # 字符串长度
    for i in range(n - maxl + 1):  # 左边界
        s2 = s[i : i + maxl]
        if solve(s2): res = maxl  # 我们的maxl是递增的,不用比较

2)滑动窗口

我们很明显的就能看出那个暴搜其实浪费了很多资源的,例如如果从1-5的子序列已经有重复的了,就不用再搜1-6的子序列了,于是,滑动窗口的思想应运而生
我们有两个指针,left 和 right,right先动,如果遍历到的元素不在set中,就把它加进去,并且lens + 1,反之,我们让left动,left去删除他遍历到的元素,直到right指针指到的元素不在set中

具体代码如下

s = input()
n = len(s)
left, right, lens, maxlen = 0, 0, 0, 0
strset = set()
while right < n:
    if s[right] not in strset:
        strset.add(s[right])
        right += 1
        lens += 1
        maxlen = max(lens,maxlen)
    else:
        while (s[right] in strset):
            strset.remove(s[left])
            left += 1
            lens -= 1
print(maxlen)

2.快排

快排的思想很简单,就是举一个数,然后找到这个数该在的位置,让这个数的左边都是小于他的,右边都是大于他的,分治做下去(这个数是否要变到他应该在的位置并不重要)

具体代码

n = int(input())
a = [int(x) for x in input().split()]
def quicksort(a,l,r):
    if l >= r : return
    x = a[l]
    i, j = l - 1, r + 1
    while (i < j):
        i += 1
        j -= 1
        while (a[i] < x):
            i += 1
        while (a[j] > x):
            j -= 1
        if (i < j): a[i], a[j] = a[j], a[i]
    quicksort(a,l,j)
    quicksort(a,j + 1,r)

quicksort(a,0,n - 1)
print(' '.join(map(str,a)))

3.归并排序

也是采取了分治思想,用一张图可以很好的展示分治排序
在这里插入图片描述
局部有序 --> 全局有序

具体代码如下

n = int(input())
a = [int(x) for x in input().split()]
def merge_sort(a,l,r):
    if l >= r : return
    mid = (l + r) // 2
    merge_sort(a, l, mid)
    merge_sort(a, mid + 1, r)

    temp = []
    i,j = l,mid + 1
    while (i <= mid and j <= r) :
        if a[i] < a[j]:
            temp.append(a[i])
            i += 1
        else:
            temp.append(a[j])
            j += 1
    
    if i <= mid:
        temp += a[i : mid + 1]
    else:
        temp += a[j : r + 1]
    a[l : r + 1] = temp[:]

merge_sort(a, 0, n - 1)
print(' '.join(map(str,a)))

4.整数二分

这个其实就两个模板,具体问题具体套一下
第一种就是 mid = (l + r) // 2,这时候要看a[mid] >=k r = mid
第二种就是 mid = (l + r + 1) // 2,这时候就看 a[mid] <=k l = mid
else的话只需要注意,r 永远是l - 1就好了

具体代码如下

## 整数二分,找到值在列表中的范围
# 第一行数n 和要查询的个数
# 第二行是单调递增的数组
# 其余后面几行是查询的数
# 浮点数二分没有那么复杂,没有+1 -1
n ,q = map(int, input().split())
a = [int(x) for x in input().split()]
for i in range(q):
    l ,r = 0, n - 1
    k = int(input())  # 要查询的数
    # 第一种模板
    while (l < r):          
        mid = (l + r) // 2
        if (a[mid] >= k):
            r = mid 
        else:
            l = mid + 1

    if a[l] != k : print('-1 1')
    else: 
        print(l, end = ' ')  # l相当于左边界
        print(r)
    # 第二种模板
    l ,r = 0, n - 1
    while (l < r):
        mid = (l + r + 1) // 2
        if (a[mid] <= k):
            l = mid
        else:
            r = mid - 1

    print(l)   # 这个l相当于右边界

5.一维前缀和

这个没啥好说的,就是为了能快速查到数组从 l 到 r的和
# 找a[l] +…+ a[r]很方便 , 下标从1开始
n ,m = map(int,input().split())
a = [0] + [int(x) for x in input().split()]
s = [0] * (n + 1)
for i in range(1,n + 1):
s[i] = s[i - 1] + a[i]

for i in range(m):  # m次查询
    l, r = map(int,input().split())
    print(s[r] - s[l - 1])

---------------现在反应过来不能一个个练了太慢了,我直接调到图论和DP,重点再过一下这两部分

先最短路部分
在这里插入图片描述

6.dijkstra

这个其实还是蛮简单的,就是要熟练,我回过头来写起来已经有点吃力了现在
dijkstra的原理很简单,就是每次重复n(点的个数)次,每次找到一个与原点距离最短的点,拿他去更新原点到其他点的距离,具体的证明我这里就不阐述了,时间复杂度是n^2,好像有一种堆优化的方法能做到复杂度为mlogn
在这里插入图片描述

具体代码如下

N,null = 510,0x3f3f3f3f


def dijkstra():
    dist[1] = 0
    
    for _ in range(n):  # 更新n次 因为有n个点,每次确定一个
        t = -1
        # 找出没有被确认的最短路径的点集合中离源点最近的点
        for j in range(1,n+1):
            if (not st[j] and (t == -1 or dist[t] > dist[j])):  # 他是第一个点 或者后面的点距离原点的距离比他小
                t = j
        st[t] = True
        for j in range(1,n+1):  # 用t去更新 其实只要更新不确定的,但为了代码方便就全部一起更新
            dist[j] = min(dist[j],dist[t] + g[t][j])
    
    if dist[n] == null : return -1
    else: return dist[n]


if __name__ == '__main__':
    g = [[null]*N for _ in range(N)]  # 稠密图用邻接矩阵
    dist,st = [null]*N,[False]*N      # dist用于存储每个点到起点的距离   st用于表示当前点已经确定最短了
    n,m = map(int,input().split())
    
    for _ in range(m):
        x,y,z = map(int,input().split())
        g[x][y] = min(g[x][y],z)  # 可能有重边 取最小的
    
    print(dijkstra())

7.bellman-ford

这个算法就是去根据边的信息去更新多次,最终要更新n(点的个数)次,就能求出来1到n的最短路
这个算法的好处是:1.允许有负边,2.他可以限制从1到n最多能经过几条边(等等看题)

在这里插入图片描述

具体代码如下

N, null = 100010, 0x3f3f3f3f
import copy
def bellman_ford():
    dist[1] = 0
    for _ in range(k):   # 遍历k次,因为有限制
        last = copy.deepcopy(dist) # 复制一下,只有限制边数才用到,怕会发生串联
        for j in range(m):  # 遍历遍历都更新所有的边
            a, b, c = edges[j]
            dist[b] = min(dist[b], last[a] + c)

    if dist[n] > null / 2: print('impossibile')
    else: print(dist[n])




if __name__ == '__main__':
    n, m, k = map(int,input().split())
    dist = [null] * N
    edges = []
    for _ in range(m):
        x, y, z = map(int,input().split())
        edges.append((x, y, z))
    bellman_ford()

8.spfa

这个算法其实就是对bellman-ford的改进,最坏情况下跟bellman-ford算法时间复杂度一样(好像一般比赛都会卡这个),他引入了一个思想就是,只有被更新的点才能去更新其他点,具体看代码把,我不是很喜欢用链表存储,点的个数太多的话邻接矩阵要开100000*100000,显然太大了,可以考虑使用两个列表分别存储点的连接和点的权重(如果不用链表的话),应该蛮好实现的,我这里就直接用邻接矩阵了哈

在这里插入图片描述

具体代码如下

##我还是不喜欢用链表存,我感觉有点麻烦
from collections import deque


def spfa():
    dist[1] = 0
    q = deque([1])
    while q:
        t = q.popleft()    # 弹出开头的元素
        st[t] = False      # 他就不在队列中了
        for i in range(1, n + 1):   # 这一步其实是要找到和t相连的结点,但是我没什么好的办法,只能遍历所有的
            if g[t][i] == null:continue
            if dist[i] > dist[t] + g[t][i]:
                dist[i] = min(dist[i], dist[t] + g[t][i])
                if not st[i]:  
                    q.append(i)
                    st[i] = True
    if dist[n] > null / 2: print('impossible')
    else: print(dist[n])




N = 510
null = 0x3f3f3f3f
dist, st = [null] * N, [False] * N
g = [[null] * N for _ in range(N)]
n, m = map(int,input().split())
for _ in range(m):
    x, y, z = map(int,input().split())
    g[x][y] = min(g[x][y], z)
spfa()

9.spfa判断负环

他判断负环的方式其实很简单,只要有一个边,被更新了n次以上,就代表有负环了,所以只需要在原来的代码下改一点就好了,要注意的是开头我们要把所有的点都加入到队列中,因为1号点可能走不到负环

具体代码如下

##我还是不喜欢用链表存,我感觉有点麻烦
from collections import deque


def spfa():
    dist[1] = 0
    q = deque([x for x in range(1,n+1)])  # 是因为可能从1号点走不到负环。所以需要以所有点都走一下试试
    while q:
        t = q.popleft()    # 弹出开头的元素
        st[t] = False      # 他就不在队列中了
        for i in range(1, n + 1):   # 这一步其实是要找到和t相连的结点,但是我没什么好的办法,只能遍历所有的
            if g[t][i] == null:continue
            if dist[i] > dist[t] + g[t][i]:
                dist[i] = min(dist[i], dist[t] + g[t][i])
                cnt[i] = cnt[t] + 1
                if cnt[i] >= n : return 'Yes'
                if not st[i]:  
                    q.append(i)
                    st[i] = True
    return 'No'



if __name__ == '__main__':
    N = 510
    null = 0x3f3f3f3f
    dist, st = [null] * N, [False] * N
    cnt = [0] * N
    g = [[null] * N for _ in range(N)]
    n, m = map(int,input().split())
    for _ in range(m):
        x, y, z = map(int,input().split())
        g[x][y] = min(g[x][y], z)
    spfa()

10.flord

这种n^3的做法就蛮暴力的感觉哈哈,这个没什么好说的,三个for就完事儿了
在这里插入图片描述

具体代码如下

N, null= 210, 0x3f3f3f3f

def flord():
    for k in range(n + 1):
        for i in range(n + 1):
            for j in range(n + 1):
                g[i][j] = min(g[i][j], g[i][k] + g[k][j])





if __name__ == '__main__':
    n, m, k = map(int,input().split())  # k次查询
    g = [[null] * N for _ in range(N)]
    for i in range(n + 1):      # flord是在g上更新,所以要做这一步
        g[i][i] = 0
    for _ in range(m):
        x, y, z = map(int,input().split())
        g[x][y] = min(g[x][y], z)
    flord()
    for _ in range(k):
        x, y = map(int, input().split())
        if g[x][y] > null / 2: print('impossible')
        else: print(g[x][y])

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/556172.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

测试必知必会的Mock数据方法

Mock数据的含义 那么Mock数据是什么意思呢 首先Mock这个英文单词有模拟的意思&#xff0c;模拟数据通俗的理解就是构造假数据&#xff0c;即Mock数据就是通过构造假数据来达到测试的目的&#xff0c;它广泛运用于功能测试、接口测试、单元测试 在功能测试中&#xff0c;可以…

离散数学 | 图论 | 欧拉图 | 哈密顿图 | 割点 | 桥(欧拉图和哈密顿图有没有割点和桥?)

本文主要解决以下几个问题&#xff1a; 1.欧拉图能不能有割点&#xff0c;能不能有桥&#xff1f; 2.哈密顿图能不能有割点&#xff0c;能不能有桥&#xff1f; 首先我们要明白几个定义 割点的定义就是在一个图G中&#xff0c;它本来是连通的&#xff0c;去掉一个点v以后这个…

【firewalld防火墙】

目录 一、firewalld概述二、firewalld 与 iptables 的区别1、firewalld 区域的概念 三、firewalld防火墙默认的9个区域四、Firewalld 网络区域1、区域介绍2、firewalld数据处理流程 五、firewalld防火墙的配置方法1、使用firewall-cmd 命令行工具。2、使用firewall-config 图形…

【计算机网络基础】章节测试4 网络层

R1与R2是一个自治系统中采用RIP路由协议的两个相邻路由器,R1的路由表如图(a)所示。如果R1收到R2发送的如图(b)所示的(V,D)报文,更新之后的R1的4个路由表项的距离从上到下依次为0、4、4、2,那么图 (b)中a、b、c、d 可能的数据一个是( C )。 A. 1、2、2、1 B. 2、2、3、1…

Java 核心技术 卷I 第2章 Java程序设计环境

第2章 Java程序设计环境 2.1 安装Java开发工具包 2.1.1 下载JDK www.oracle.com/technetwork/java/javase/downloads Java术语 2.1.2 设置JDK 下载JDK之后&#xff0c;需要安装这个开发包并明确要在哪里安装&#xff0c;后面还会需要这个信息. 指/opt/jdk1.8.0_31/bin或c…

从零开始Vue3+Element Plus后台管理系统(十四)——PDF预览和打印

其实我常常会纠结今天要写什么内容。 因为希望能够保持每日更新&#xff0c;所以要写的内容不能太难——最好是半天可以搞出demo并且输出文章&#xff0c;所以很多东西浅尝辄止&#xff0c;并没有深入研究&#xff0c;还写出了一些bug &#x1f41b; 今天又浅浅的研究了下在V…

这还只是阿里20K+测试岗面试题,看的我冷汗直流.....

朋友入职已经两周了&#xff0c;整体工作环境还是非常满意的&#xff01;所以这次特意抽空给我写出了这份面试题&#xff0c;而我把它分享给伙伴们&#xff0c;面试&入职的经验&#xff01; 大概是在3月中的时候他告诉我投递了阿里巴巴并且简历已通过&#xff0c;3月23经过…

python类型注释

目录 为什么需要类型注解 什么是类型注解 联合注解 使用注解时的注意点 为什么需要类型注解 看下图&#xff0c;很精炼&#xff1b; 什么是类型注解 Python类型注释是指在变量、函数参数、返回值等位置添加类型信息的一种语法&#xff0c;其目的是提高代码的可读性和可维护…

monkey测试方法及命令

1、查询测试包信息 # 查看已连接设备 adb devices # 带uuid查询包含test的第三方apk包 adb -s W21112003057 shell pm list package -3 | grep test # 清空logcat adb -s W21112003057 logcat -c # 启动app&#xff0c;通过日志查看安装包信息 adb -s W21112003057 logcat…

史上最全!全领域网络安全拓扑图(118页)

大家好&#xff0c;我是老杨。 前几天发了一篇OSPF的文章&#xff0c;助理发到群里和大家讨论。 好几个小友表示&#xff0c;绘制拓扑的才是最高境界&#xff0c;并且想看些拓扑图案例。 其实拓扑图案例老杨也分享过不少了。 可以看看这些往期文章&#xff0c;《超干货&…

【送书福利-第四期】从程序员到架构师:大数据量、缓存、高并发、微服务、多团队协同等核心场景实战书籍

大家好&#xff0c;我是洲洲&#xff0c;欢迎关注&#xff0c;一个爱听周杰伦的程序员。关注公众号【程序员洲洲】即可获得10G学习资料、面试笔记、大厂独家学习体系路线等…还可以加入技术交流群欢迎大家在CSDN后台私信我&#xff01; 送书福利-第四期 一、前言二、书籍介绍抽…

KY111 日期差值

1.题目&#xff1a; 2.分析&#xff1a; 1. 分别求出每一个日期与0000年0月1日距离的天数 2. 两个距离天数相减即可得到两个日期相差的天数 3.我的代码&#xff1a; #include <iostream> using namespace std;class Date { public:Date(int year 1, int month 1, …

java学习:字面量,基本语句

一、字面量 1.字面量的类型 Java字面量的类型其实跟 c 的有点相似&#xff0c;有一点不一样的就是&#xff0c;Java有个null类型&#xff0c;注意这个没有大写 2.特殊字面量 \t 是制表符&#xff0c;它的作用就是补齐一个字符串到8位&#xff0c;这样就会使输出结果变得美观…

【arxiv】关于 SAM 的论文扫读(一)

文章目录 一、阴影检测二、弱监督下的隐蔽物体分割&#xff1a;基于SAM的伪标签和多尺度特征分组三、Instruct2Act&#xff1a;利用大型语言模型将多模态指令映射到机器人动作四、OR-NeRF: Object Removing from 3D Scenes Guided by Multiview Segmentation with Neural Radia…

Lucene(5):索引维护

1 需求 管理人员通过电商系统更改图书信息&#xff0c;这时更新的是关系数据库&#xff0c;如果使用lucene搜索图书信息&#xff0c;需要在数据库表book信息变化时及时更新lucene索引库。 2 添加索引 调用 indexWriter.addDocument&#xff08;doc&#xff09;添加索引。 参…

[Data structure]环形链表

⭐作者介绍&#xff1a;大二本科网络工程专业在读&#xff0c;持续学习Java&#xff0c;努力输出优质文章 ⭐作者主页&#xff1a;逐梦苍穹 ⭐所属专栏&#xff1a;数据结构。数据结构专栏主要是在讲解原理的基础上拿Java实现 ⭐如果觉得文章写的不错&#xff0c;欢迎点个关注一…

文心一言 VS chatgpt (21)-- h264编码一帧数据的流程是怎样的?

h264编码一帧数据的流程是怎样的&#xff1f; 文心一言&#xff1a; H.264编码将一帧数据分成多个块&#xff0c;其中每个块可以单独进行编码。编码的过程包括预测、变换和量化等步骤。 具体流程如下&#xff1a; 1.帧内预测&#xff1a;对一帧视频进行编码&#xff0c;首先…

什么是网络编程

目录 一、什么是网络编程&#xff1f; 二、协议 1.用户数据报协议(User Datagram Protocol) 2.TCP协议 TCP三次握手过程 三、实例 1.UDP通信程序 实现步骤 TCP接收数据 四、TCP协议和UDP协议的区别和联系 一、什么是网络编程&#xff1f; 1.在网络通信协议下&#xf…

Qt编程基础 | 常用控件 | 组合框

一、组合框 1.1、定义 QComboBox提供了一种向用户呈现选项列表的方式&#xff0c;以占用最少的屏幕空间。 组合框是一个显示当前项目的选择小部件&#xff0c;可以弹出可选择项目的列表。 组合框可以是可编辑的&#xff0c;允许用户修改列表中的每个项目。 QComboBox 除了显示…

四、IOC容器(3)

一、IOC操作Bean管理&#xff08;外部属性文件&#xff09; 1.直接配置数据库信息 配置德鲁伊连接池引入德鲁伊连接池依赖jar包 <!--配置连接池--> <bean id"dataSource" class"com.alibaba.druid.pool.DruidDataSource"><property name&…