基础知识要求:
Java:方法、集合、泛型、数组、for循环、switch case语句、逻辑运算符、if判断、权限修饰符、static关键字、Scanner类
Python: 方法、列表、for循环、逻辑运算符、if判断、input()
题目:
小蓝最近学习了一种神奇的队列:分布式队列。简单来说,分布式队列包含 N 个节点(编号为 0 至 N − 1,其中 0 号为主节点),其中只有一个主节点,其余为副节点。主/副节点中都各自维护着一个队列,当往分布式队列中添加元素时都是由主节点完成的(每次都会添加元素到队列尾部);副节点只负责同步主节点中的队列。可以认为主/副节点中的队列是一个长度无限的一维数组,下标为 0, 1, 2, 3 . . . ,同时副节点中的元素的同步顺序和主节点中的元素添加顺序保持一致。
由于副本的同步速度各异,因此为了保障数据的一致性,元素添加到主节点后,需要同步到所有的副节点后,才具有可见性。
给出一个分布式队列的运行状态,所有的操作都按输入顺序执行。你需要回答在某个时刻,队列中有多少个元素具有可见性。
输入格式
第一行包含一个整数 N,表示节点个数。接下来包含多行输入,每一行包含一个操作,操作类型共有以下三种:add、sync 和 query,各自的输入格式如下:
-
add element:表示这是一个添加操作,将元素 element 添加到队列中;
-
sync follower_id:表示这是一个同步操作,follower_id 号副节点会从主节点中同步下一个自己缺失的元素;
-
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)