题目描述
幼儿园里有一个放倒的圆桶,它是一个线性结构 ( Q ),允许在桶的右边将篮球放入,可以在桶的左边和右边将篮球取出。每个篮球有单独的编号,老师可以连续放入一个或多个篮球,小朋友可以在桶左边或右边将篮球取出,当桶里只有一个篮球的情况下,必须从左边取出。
输入描述
- 第一行的数字作为老师依次放入的篮球编号;
- 第二行的数字作为要检查是否能够按照放入顺序取出的篮球编号;
其中篮球编号用逗号进行分隔。
输出描述
对于每个篮球的取出序列,如果确实可以获取,请打印出其按照左右方向的操作的取出顺序,如果无法获取则打印"NO"。
示例
输入:
4,5,6,7,0,1,2
6,4,0,1,2,5,7
输出:
RLRRRLL
说明:
篮球的取出顺序依次为“右,左,右,右,右,左,左”。
解题思路
这个问题可以通过模拟篮球的放入和取出过程来解决。我们可以使用一个双端队列(deque)来模拟圆桶的行为。具体步骤如下:
- 将老师放入的篮球编号依次加入队列的右边。
- 对于要检查的取出序列,依次尝试从队列的左边或右边取出篮球。
- 如果当前要取出的篮球编号与队列的左边或右边的篮球编号匹配,则记录取出方向,并将该篮球从队列中移除。
- 如果无法匹配,则输出"NO"。
- 如果所有篮球都能成功取出,则输出取出方向的序列。
代码实现
Java
import java.util.*;
public class Solution {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取输入的篮球编号
String[] input = scanner.nextLine().split(",");
// 读取要检查的取出序列
String[] output = scanner.nextLine().split(",");
// 使用双端队列模拟圆桶
Deque<String> deque = new ArrayDeque<>();
// 将输入的篮球编号依次加入队列的右边
for (String ball : input) {
deque.addLast(ball);
}
// 用于记录取出方向的序列
StringBuilder result = new StringBuilder();
// 遍历要检查的取出序列
for (String ball : output) {
// 如果队列不为空且队首的篮球编号匹配
if (!deque.isEmpty() && deque.peekFirst().equals(ball)) {
result.append("L"); // 记录从左取出
deque.removeFirst(); // 移除队首的篮球
}
// 如果队列不为空且队尾的篮球编号匹配
else if (!deque.isEmpty() && deque.peekLast().equals(ball)) {
result.append("R"); // 记录从右取出
deque.removeLast(); // 移除队尾的篮球
}
// 如果无法匹配,输出"NO"并结束程序
else {
System.out.println("NO");
return;
}
}
// 输出取出方向的序列
System.out.println(result.toString());
}
}
Python
from collections import deque
# 读取输入的篮球编号
input_balls = input().split(',')
# 读取要检查的取出序列
output_balls = input().split(',')
# 使用双端队列模拟圆桶
queue = deque(input_balls)
# 用于记录取出方向的序列
result = []
# 遍历要检查的取出序列
for ball in output_balls:
# 如果队列不为空且队首的篮球编号匹配
if queue and queue[0] == ball:
result.append('L') # 记录从左取出
queue.popleft() # 移除队首的篮球
# 如果队列不为空且队尾的篮球编号匹配
elif queue and queue[-1] == ball:
result.append('R') # 记录从右取出
queue.pop() # 移除队尾的篮球
# 如果无法匹配,输出"NO"并结束程序
else:
print("NO")
exit()
# 输出取出方向的序列
print(''.join(result))
C++
#include <iostream>
#include <deque>
#include <vector>
#include <sstream>
using namespace std;
int main() {
string input, output;
// 读取输入的篮球编号
getline(cin, input);
// 读取要检查的取出序列
getline(cin, output);
// 使用双端队列模拟圆桶
deque<string> queue;
stringstream ss(input);
string ball;
// 将输入的篮球编号依次加入队列的右边
while (getline(ss, ball, ',')) {
queue.push_back(ball);
}
stringstream ss2(output);
string result;
// 遍历要检查的取出序列
while (getline(ss2, ball, ',')) {
// 如果队列不为空且队首的篮球编号匹配
if (!queue.empty() && queue.front() == ball) {
result += 'L'; // 记录从左取出
queue.pop_front(); // 移除队首的篮球
}
// 如果队列不为空且队尾的篮球编号匹配
else if (!queue.empty() && queue.back() == ball) {
result += 'R'; // 记录从右取出
queue.pop_back(); // 移除队尾的篮球
}
// 如果无法匹配,输出"NO"并结束程序
else {
cout << "NO" << endl;
return 0;
}
}
// 输出取出方向的序列
cout << result << endl;
return 0;
}
JavaScript
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
let inputBalls, outputBalls;
// 读取输入的篮球编号和要检查的取出序列
rl.on('line', (line) => {
if (!inputBalls) {
inputBalls = line.split(',');
} else {
outputBalls = line.split(',');
rl.close();
}
}).on('close', () => {
// 使用双端队列模拟圆桶
const queue = [...inputBalls];
// 用于记录取出方向的序列
let result = '';
// 遍历要检查的取出序列
for (const ball of outputBalls) {
// 如果队列不为空且队首的篮球编号匹配
if (queue.length > 0 && queue[0] === ball) {
result += 'L'; // 记录从左取出
queue.shift(); // 移除队首的篮球
}
// 如果队列不为空且队尾的篮球编号匹配
else if (queue.length > 0 && queue[queue.length - 1] === ball) {
result += 'R'; // 记录从右取出
queue.pop(); // 移除队尾的篮球
}
// 如果无法匹配,输出"NO"并结束程序
else {
console.log("NO");
return;
}
}
// 输出取出方向的序列
console.log(result);
});
复杂度分析
- 时间复杂度: O(n),其中 n 是篮球的数量。每个篮球最多被放入和取出一次。
- 空间复杂度: O(n),用于存储篮球的队列。
总结
这个问题通过模拟篮球的放入和取出过程,使用双端队列来高效地解决问题。通过检查每个篮球的取出方向,可以确定是否能够按照给定的顺序取出篮球。