分布式队列 - 蓝桥杯2024年第十五届省赛真题

基础知识要求:

Java:方法、集合、泛型、数组、for循环、switch case语句、逻辑运算符、if判断、权限修饰符、static关键字、Scanner类
Python: 方法、列表、for循环、逻辑运算符、if判断、input()

题目:

小蓝最近学习了一种神奇的队列:分布式队列。简单来说,分布式队列包含 N 个节点(编号为 0 至 N − 1,其中 0 号为主节点),其中只有一个主节点,其余为副节点。主/副节点中都各自维护着一个队列,当往分布式队列中添加元素时都是由主节点完成的(每次都会添加元素到队列尾部);副节点只负责同步主节点中的队列。可以认为主/副节点中的队列是一个长度无限的一维数组,下标为 0, 1, 2, 3 . . . ,同时副节点中的元素的同步顺序和主节点中的元素添加顺序保持一致。

由于副本的同步速度各异,因此为了保障数据的一致性,元素添加到主节点后,需要同步到所有的副节点后,才具有可见性。

给出一个分布式队列的运行状态,所有的操作都按输入顺序执行。你需要回答在某个时刻,队列中有多少个元素具有可见性。

输入格式

第一行包含一个整数 N,表示节点个数。接下来包含多行输入,每一行包含一个操作,操作类型共有以下三种:add、sync 和 query,各自的输入格式如下:

  1. add element:表示这是一个添加操作,将元素 element 添加到队列中;

  2. sync follower_id:表示这是一个同步操作,follower_id 号副节点会从主节点中同步下一个自己缺失的元素;

  3. query:查询操作,询问当前分布式队列中有多少个元素具有可见性。

输出格式

对于每一个 query 操作,输出一行,包含一个整数表示答案。

样例输入

复制代码
3
add 1
add 2
query
add 1
sync 1
sync 1
sync 2
query
sync 1
query
sync 2
sync 2
sync 1
query

样例输出

复制代码
0
1
1
3

【样例说明】

执行到第一个 query 时,队列内容如下:

0:[1,2]

1:[]

2:[]

两个副节点中都无元素,因此答案为 0。

执行到第二个 query 时,队列内容如下:

0:[1,2,1]

1:[1,2]

2:[1]

只有下标为 0 的元素被所有节点同步,因此答案为 1。执行到第三个 query 时,队列内容如下:0:[1,2,1]1:[1,2,1]2:[1]

只有下标为 0 的元素被所有节点同步,因此答案为 1。执行到第四个 query 时,队列内容如下:0:[1,2,1]1:[1,2,1]2:[1,2,1]

三个元素都被所有节点同步,因此答案为 3。

【评测用例规模与约定】

对于 30% 的评测用例:1 ≤ 输入的操作数 ≤ 100。

对于 100% 的评测用例:1 ≤ 输入的操作数 ≤ 2000,1 ≤ N ≤ 10,1 ≤f ollower_id < N,0 ≤ element ≤ 105。

思路解析:

为了解决这个问题,我们可以使用一个数组来跟踪每个副节点当前同步到的队列位置。同时,我们需要记录主节点队列的当前长度。对于每一个操作,我们可以根据操作类型来更新这些信息。

Java代码示例:

java 复制代码
import java.util.ArrayList;  
import java.util.List;  
import java.util.Scanner;  
  
public class NodeSync {  
  
    public static void main(String[] args) {  
        Scanner scanner = new Scanner(System.in);  
        System.out.print("请输入节点总数(包括主节点和副节点):");  
        int N = scanner.nextInt();  
  
        List<Integer> mainQueue = new ArrayList<>(); // 主节点队列  
        int[] followerSync = new int[N - 1]; // 跟踪每个副节点同步到的位置(不包括主节点)  
  
        List<String> operations = new ArrayList<>();  
        // 这里假设operations已经以某种方式填充了  
        // operations.add("add 1");  
        // operations.add("add 2");  
        // ...  
  
        // 示例操作,硬编码到程序中  
        operations.add("add 1");  
        operations.add("add 2");  
        operations.add("query");  
        operations.add("add 1");  
        operations.add("sync 1");  
        operations.add("sync 1");  
        operations.add("sync 2");  
        operations.add("query");  
        operations.add("sync 1");  
        operations.add("query");  
        operations.add("sync 2");  
        operations.add("sync 2");  
        operations.add("sync 1");  
        operations.add("query");  
  
        processOperations(operations, N, mainQueue, followerSync);  
  
        scanner.close();  
    }  
  
    private static void processOperations(List<String> operations, int N, List<Integer> mainQueue, int[] followerSync) {  
        for (String operation : operations) {  
            String[] parts = operation.split(" ");  
            String op = parts[0];  
  
            switch (op) {  
                case "add":  
                    int element = Integer.parseInt(parts[1]);  
                    addElement(mainQueue, element);  
                    break;  
                case "sync":  
                    int followerId = Integer.parseInt(parts[1]);  
                    syncFollower(followerId, N, mainQueue, followerSync);  
                    break;  
                case "query":  
                    System.out.println(queryVisibility(mainQueue, followerSync));  
                    break;  
                default:  
                    System.out.println("无效的操作:" + op);  
            }  
        }  
    }  
  
    private static void addElement(List<Integer> mainQueue, int element) {  
        mainQueue.add(element);  
    }  
  
    private static void syncFollower(int followerId, int N, List<Integer> mainQueue, int[] followerSync) {  
        if (followerId >= 0 && followerId < N - 1 && followerSync[followerId] < mainQueue.size()) {  
            followerSync[followerId]++;  
        }  
    }  
  
    private static int queryVisibility(List<Integer> mainQueue, int[] followerSync) {  
        int minSync = Integer.MAX_VALUE;  
        for (int sync : followerSync) {  
            minSync = Math.min(minSync, sync);  
        }  
        return Math.min(minSync, mainQueue.size());  
    }  
}

Python代码示例:

python 复制代码
def process_operations(operations, N):  
    main_queue = []  # 主节点队列  
    follower_sync = [0] * (N - 1)  # 跟踪每个副节点同步到的位置(不包括主节点)  
  
    def add_element(element):  
        main_queue.append(element)  
  
    def sync_follower(follower_id):  
        if 0 <= follower_id < N - 1 and follower_sync[follower_id] < len(main_queue):  
            follower_sync[follower_id] += 1  
  
    def query_visibility():  
        # 查找所有副节点中最小的同步位置  
        min_sync = min(follower_sync)  
        # 具有可见性的元素是主节点队列中从下标0到min_sync-1的元素  
        return min(min_sync, len(main_queue))  
  
    for operation in operations:  
        op, *args = operation.split()  
        if op == 'add':  
            element = int(args[0])  
            add_element(element)  
        elif op == 'sync':  
            follower_id = int(args[0])  
            sync_follower(follower_id)  
        elif op == 'query':  
            print(query_visibility())  
  
# 从用户输入中获取N的值  
N = int(input("请输入节点总数(包括主节点和副节点):"))  
  
# 假设operations是从某个输入源读取的,这里用字符串列表代替  
operations = [  
    "add 1",  
    "add 2",  
    "query",  
    "add 1",  
    "sync 1",  
    "sync 1",  
    "sync 2",  
    "query",  
    "sync 1",  
    "query",  
    "sync 2",  
    "sync 2",  
    "sync 1",  
    "query"  
]  
  
# 调用函数处理操作  
process_operations(operations, N)
相关推荐
IT毕设梦工厂1 小时前
计算机毕业设计选题推荐-在线拍卖系统-Java/Python项目实战
java·spring boot·python·django·毕业设计·源码·课程设计
luthane1 小时前
python 实现average mean平均数算法
开发语言·python·算法
静心问道2 小时前
WGAN算法
深度学习·算法·机器学习
码农研究僧2 小时前
Flask 实现用户登录功能的完整示例:前端与后端整合(附Demo)
python·flask·用户登录
Ylucius2 小时前
动态语言? 静态语言? ------区别何在?java,js,c,c++,python分给是静态or动态语言?
java·c语言·javascript·c++·python·学习
凡人的AI工具箱2 小时前
AI教你学Python 第11天 : 局部变量与全局变量
开发语言·人工智能·后端·python
sleP4o2 小时前
Python操作MySQL
开发语言·python·mysql
七夜zippoe2 小时前
分布式系统实战经验
java·分布式
杰九2 小时前
【算法题】46. 全排列-力扣(LeetCode)
算法·leetcode·深度优先·剪枝
manba_2 小时前
leetcode-560. 和为 K 的子数组
数据结构·算法·leetcode