一、问题描述
题目描述
疫情期间课堂的座位进行了特殊的调整,不能出现两个同学紧挨着,必须隔至少一个空位。
给你一个整数数组 desk
表示当前座位的占座情况,由若干 0 和 1 组成,其中 0 表示没有占位,1 表示占位。
在不改变原有座位秩序情况下,还能安排坐几个人?
输入描述
第一行是个子数组表示作为占座情况,由若干 0 和 1 组成,其中 0 表示没有占位,1 表示占位
输出描述
输出数值表示还能坐几个人
备注
1 ≤ desk.length ≤ 2 * 10^4
用例
输入
1,0,0,0,1
输出
1
说明
只有 desk[2]
的位置可以坐一个人
题目解析
我的解题思路如下:
-
解析输入:将输入解析为一个整型数组
desk
,然后遍历每一个元素desk[i]
。 -
检查空位:
- 如果
desk[i] == 0
,则说明desk[i]
是一个空位,此时只需要检查desk[i]
的左右两边也是空位,则说明desk[i]
可以坐人,此时将desk[i]
更新为 1,表示坐人了。 - 判断左右是否为空位的逻辑如下:
- 如果
i == 0 || desk[i-1] == 0
,则说明desk[i]
左边是空位,i == 0
说明其左边没有其他座位了,也相当于空位。 - 如果
i == desk.length - 1 || desk[i+1] == 0
,则说明desk[i]
右边也是空位,i == desk.length - 1
说明其右边没有其他座位了,也就相当于空位。
- 如果
- 如果
-
处理已占位:
- 如果
desk[i] != 0
,则说明desk[i]
不是一个空位,坐不了人,且说明了下一个i+1
座位也不能坐人。
- 如果
通过这种方法,我们可以有效地计算出在不改变原有座位秩序的情况下,还能安排坐几个人。时间复杂度为 O(n),其中 n 是 desk
的长度,因为我们只需要遍历数组一次。
二、JavaScript算法源码
以下是 JavaScript 代码的详细中文注释和讲解:
JavaScript 代码实现
/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline"); // 引入 readline 模块,用于读取控制台输入// 创建 readline.Interface 实例,用于处理输入和输出
const rl = readline.createInterface({input: process.stdin, // 输入流为标准输入output: process.stdout, // 输出流为标准输出
});// 监听 'line' 事件,当用户输入一行数据时触发
rl.on("line", (line) => {// 将输入的一行数据按逗号分隔为字符串数组,然后转换为数字数组 deskconst desk = line.split(",").map(Number);// 调用 getResult 函数,计算可以坐下的学生数量,并输出结果console.log(getResult(desk));
});/*** 计算可以坐下的学生数量** @param {number[]} desk - 表示座位状态的数组,0 表示空座位,1 表示已占用* @returns {number} - 可以坐下的学生数量*/
function getResult(desk) {let ans = 0; // 定义变量 ans,用于记录可以坐下的学生数量// 遍历座位数组 deskfor (let i = 0; i < desk.length; i++) {if (desk[i] == 0) { // 如果当前座位是空的// 检查当前座位的左侧是否为空const isLeftEmpty = i == 0 || desk[i - 1] == 0;// 检查当前座位的右侧是否为空const isRightEmpty = i == desk.length - 1 || desk[i + 1] == 0;// 如果左侧和右侧都为空,则可以坐下if (isLeftEmpty && isRightEmpty) {ans++; // 学生数量加 1desk[i] = 1; // 将当前座位标记为已占用i++; // 跳过下一个座位,因为下一个座位不能坐人}}}return ans; // 返回可以坐下的学生数量
}
代码讲解
1. 输入处理
- 使用
readline
模块读取控制台输入。 - 监听
line
事件,当用户输入一行数据时触发回调函数。 - 将输入的一行数据按逗号分隔为字符串数组,然后通过
map(Number)
转换为数字数组desk
。desk
数组表示座位的状态:0
表示空座位。1
表示已占用。
2. 主算法函数 getResult
- 功能:计算可以坐下的学生数量。
- 逻辑:
- 遍历
desk
数组,检查每个座位是否为空(值为0
)。 - 对于每个空座位,检查其左侧和右侧是否为空:
- 如果左侧和右侧都为空,则可以坐下。
- 如果可以坐下:
- 学生数量
ans
加 1。 - 将当前座位标记为已占用(值为
1
)。 - 跳过下一个座位(因为下一个座位不能坐人)。
- 学生数量
- 遍历
- 返回值:可以坐下的学生数量。
示例分析
示例 1
输入:
0,0,1,0,0
输出:
2
解释:
- 第一个空座位(索引 0)可以坐下,因为左侧和右侧都为空。
- 第二个空座位(索引 3)可以坐下,因为左侧和右侧都为空。
- 总共可以坐下 2 名学生。
示例 2
输入:
1,0,0,0,1
输出:
1
解释:
- 只有第二个空座位(索引 2)可以坐下,因为左侧和右侧都为空。
- 总共可以坐下 1 名学生。
复杂度分析
-
时间复杂度:
- 遍历
desk
数组一次,时间复杂度为O(n)
,其中n
是数组的长度。
- 遍历
-
空间复杂度:
- 除了输入数组
desk
外,只使用了常数级别的额外空间,空间复杂度为O(1)
。
- 除了输入数组
总结
- 该代码通过遍历座位数组,检查每个空座位的左右是否为空,来计算可以坐下的学生数量。
- 使用
readline
模块处理控制台输入,适合 Node.js 环境下的 ACM 模式。 - 如果有其他问题,欢迎继续提问!
三、Java算法源码
以下是 Java 代码的详细中文注释和讲解:
Java 代码实现
import java.util.Arrays;
import java.util.Scanner;public class Main {public static void main(String[] args) {// 创建 Scanner 对象,用于读取输入Scanner sc = new Scanner(System.in);// 读取输入的一行数据,并将其按逗号分隔为字符串数组// 然后将字符串数组转换为整数数组 deskint[] desk = Arrays.stream(sc.nextLine().split(",")).mapToInt(Integer::parseInt).toArray();// 调用 getResult 方法,计算可以坐下的学生数量,并输出结果System.out.println(getResult(desk));}/*** 计算可以坐下的学生数量** @param desk 表示座位状态的数组,0 表示空座位,1 表示已占用* @return 可以坐下的学生数量*/public static int getResult(int[] desk) {int ans = 0; // 定义变量 ans,用于记录可以坐下的学生数量// 遍历座位数组 deskfor (int i = 0; i < desk.length; i++) {if (desk[i] == 0) { // 如果当前座位是空的// 检查当前座位的左侧是否为空boolean isLeftEmpty = (i == 0) || (desk[i - 1] == 0);// 检查当前座位的右侧是否为空boolean isRightEmpty = (i == desk.length - 1) || (desk[i + 1] == 0);// 如果左侧和右侧都为空,则可以坐下if (isLeftEmpty && isRightEmpty) {ans++; // 学生数量加 1desk[i] = 1; // 将当前座位标记为已占用i++; // 跳过下一个座位,因为下一个座位不能坐人}}}return ans; // 返回可以坐下的学生数量}
}
代码讲解
1. 输入处理
- 使用
Scanner
读取输入的一行数据。 - 将输入按逗号分隔为字符串数组,然后转换为整数数组
desk
。desk
数组表示座位的状态:0
表示空座位。1
表示已占用。
2. 主算法函数 getResult
- 功能:计算可以坐下的学生数量。
- 逻辑:
- 遍历
desk
数组,检查每个座位是否为空(值为0
)。 - 对于每个空座位,检查其左侧和右侧是否为空:
- 如果左侧和右侧都为空,则可以坐下。
- 如果可以坐下:
- 学生数量
ans
加 1。 - 将当前座位标记为已占用(值为
1
)。 - 跳过下一个座位(因为下一个座位不能坐人)。
- 学生数量
- 遍历
- 返回值:可以坐下的学生数量。
示例分析
示例 1
输入:
0,0,1,0,0
输出:
2
解释:
- 第一个空座位(索引 0)可以坐下,因为左侧和右侧都为空。
- 第二个空座位(索引 3)可以坐下,因为左侧和右侧都为空。
- 总共可以坐下 2 名学生。
示例 2
输入:
1,0,0,0,1
输出:
1
解释:
- 只有第二个空座位(索引 2)可以坐下,因为左侧和右侧都为空。
- 总共可以坐下 1 名学生。
复杂度分析
-
时间复杂度:
- 遍历
desk
数组一次,时间复杂度为O(n)
,其中n
是数组的长度。
- 遍历
-
空间复杂度:
- 除了输入数组
desk
外,只使用了常数级别的额外空间,空间复杂度为O(1)
。
- 除了输入数组
总结
- 该代码通过遍历座位数组,检查每个空座位的左右是否为空,来计算可以坐下的学生数量。
- 使用
Scanner
和Arrays.stream
处理输入,适合 Java 的标准输入输出模式。 - 如果有其他问题,欢迎继续提问!
四、Python算法源码
以下是 Python 代码的详细中文注释和讲解:
Python 代码实现
# 输入获取
# 从标准输入读取一行数据,按逗号分隔并转换为整数列表 desk
desk = list(map(int, input().split(",")))# 算法入口
def getResult():ans = 0 # 定义变量 ans,用于记录可以坐下的学生数量i = 0 # 初始化索引 i,用于遍历座位数组 deskwhile i < len(desk): # 遍历座位数组if desk[i] == 0: # 如果当前座位是空的# 检查当前座位的左侧是否为空isLeftEmpty = i == 0 or desk[i - 1] == 0# 检查当前座位的右侧是否为空isRightEmpty = i == len(desk) - 1 or desk[i + 1] == 0# 如果左侧和右侧都为空,则可以坐下if isLeftEmpty and isRightEmpty:ans += 1 # 学生数量加 1desk[i] = 1 # 将当前座位标记为已占用i += 1 # 跳过下一个座位,因为下一个座位不能坐人i += 1 # 继续检查下一个座位return ans # 返回可以坐下的学生数量# 算法调用
print(getResult()) # 调用 getResult 函数并输出结果
代码讲解
1. 输入处理
- 使用
input()
函数从标准输入读取一行数据。 - 将输入按逗号分隔为字符串列表,然后通过
map(int, ...)
转换为整数列表desk
。desk
列表表示座位的状态:0
表示空座位。1
表示已占用。
2. 主算法函数 getResult
- 功能:计算可以坐下的学生数量。
- 逻辑:
- 使用
while
循环遍历desk
列表,检查每个座位是否为空(值为0
)。 - 对于每个空座位,检查其左侧和右侧是否为空:
- 如果左侧和右侧都为空,则可以坐下。
- 如果可以坐下:
- 学生数量
ans
加 1。 - 将当前座位标记为已占用(值为
1
)。 - 跳过下一个座位(因为下一个座位不能坐人)。
- 学生数量
- 继续检查下一个座位。
- 使用
- 返回值:可以坐下的学生数量。
示例分析
示例 1
输入:
0,0,1,0,0
输出:
2
解释:
- 第一个空座位(索引 0)可以坐下,因为左侧和右侧都为空。
- 第二个空座位(索引 3)可以坐下,因为左侧和右侧都为空。
- 总共可以坐下 2 名学生。
示例 2
输入:
1,0,0,0,1
输出:
1
解释:
- 只有第二个空座位(索引 2)可以坐下,因为左侧和右侧都为空。
- 总共可以坐下 1 名学生。
复杂度分析
-
时间复杂度:
- 遍历
desk
列表一次,时间复杂度为O(n)
,其中n
是列表的长度。
- 遍历
-
空间复杂度:
- 除了输入列表
desk
外,只使用了常数级别的额外空间,空间复杂度为O(1)
。
- 除了输入列表
总结
- 该代码通过遍历座位列表,检查每个空座位的左右是否为空,来计算可以坐下的学生数量。
- 使用
input()
和split()
处理输入,适合 Python 的标准输入输出模式。 - 如果有其他问题,欢迎继续提问!
五、C/C++算法源码:
以下是 C语言 和 C++ 代码的详细中文注释和讲解:
C语言代码实现
#include <stdio.h>#define MAX_SIZE 20000 // 定义最大数组长度// 函数声明
int getResult(int* desk, int desk_size);int main() {int desk[MAX_SIZE]; // 定义数组 desk,用于存储座位状态int desk_size = 0; // 定义变量 desk_size,用于记录数组长度// 从标准输入读取数据,以逗号分隔while (scanf("%d", &desk[desk_size++])) {if (getchar() != ',') break; // 如果下一个字符不是逗号,则结束输入}// 调用 getResult 函数,计算可以坐下的学生数量,并输出结果printf("%d\n", getResult(desk, desk_size));return 0;
}/*** 计算可以坐下的学生数量** @param desk - 表示座位状态的数组,0 表示空座位,1 表示已占用* @param desk_size - 数组的长度* @return 可以坐下的学生数量*/
int getResult(int* desk, int desk_size) {int ans = 0; // 定义变量 ans,用于记录可以坐下的学生数量// 遍历座位数组 deskfor (int i = 0; i < desk_size; i++) {if (desk[i] == 0) { // 如果当前座位是空的// 检查当前座位的左侧是否为空int isLeftEmpty = i == 0 || desk[i - 1] == 0;// 检查当前座位的右侧是否为空int isRightEmpty = i == desk_size - 1 || desk[i + 1] == 0;// 如果左侧和右侧都为空,则可以坐下if (isLeftEmpty && isRightEmpty) {ans++; // 学生数量加 1desk[i] = 1; // 将当前座位标记为已占用i++; // 跳过下一个座位,因为下一个座位不能坐人}}}return ans; // 返回可以坐下的学生数量
}
C++代码实现
#include <iostream>
#include <vector>using namespace std;/*** 计算可以坐下的学生数量** @param desk - 表示座位状态的数组,0 表示空座位,1 表示已占用* @return 可以坐下的学生数量*/
int getResult(vector<int>& desk) {int ans = 0; // 定义变量 ans,用于记录可以坐下的学生数量// 遍历座位数组 deskfor (int i = 0; i < desk.size(); i++) {if (desk[i] == 0) { // 如果当前座位是空的// 检查当前座位的左侧是否为空bool isLeftEmpty = i == 0 || desk[i - 1] == 0;// 检查当前座位的右侧是否为空bool isRightEmpty = i == desk.size() - 1 || desk[i + 1] == 0;// 如果左侧和右侧都为空,则可以坐下if (isLeftEmpty && isRightEmpty) {ans++; // 学生数量加 1desk[i] = 1; // 将当前座位标记为已占用i++; // 跳过下一个座位,因为下一个座位不能坐人}}}return ans; // 返回可以坐下的学生数量
}int main() {vector<int> desk; // 定义动态数组 desk,用于存储座位状态int num;char sep;// 从标准输入读取数据,以逗号分隔while (cin >> num) {desk.push_back(num); // 将数字添加到 desk 数组中if (cin.peek() != ',') break; // 如果下一个字符不是逗号,则结束输入cin >> sep; // 读取逗号}// 调用 getResult 函数,计算可以坐下的学生数量,并输出结果cout << getResult(desk) << endl;return 0;
}
代码讲解
1. 输入处理
- C语言:
- 使用
scanf
从标准输入读取整数,并通过getchar
检查下一个字符是否为逗号。 - 将读取的数据存储到数组
desk
中,并记录数组长度desk_size
。
- 使用
- C++:
- 使用
cin
从标准输入读取整数,并通过cin.peek
检查下一个字符是否为逗号。 - 将读取的数据存储到动态数组
desk
中。
- 使用
2. 主算法函数 getResult
- 功能:计算可以坐下的学生数量。
- 逻辑:
- 遍历座位数组
desk
,检查每个座位是否为空(值为0
)。 - 对于每个空座位,检查其左侧和右侧是否为空:
- 如果左侧和右侧都为空,则可以坐下。
- 如果可以坐下:
- 学生数量
ans
加 1。 - 将当前座位标记为已占用(值为
1
)。 - 跳过下一个座位(因为下一个座位不能坐人)。
- 学生数量
- 遍历座位数组
- 返回值:可以坐下的学生数量。
示例分析
示例 1
输入:
0,0,1,0,0
输出:
2
解释:
- 第一个空座位(索引 0)可以坐下,因为左侧和右侧都为空。
- 第二个空座位(索引 3)可以坐下,因为左侧和右侧都为空。
- 总共可以坐下 2 名学生。
示例 2
输入:
1,0,0,0,1
输出:
1
解释:
- 只有第二个空座位(索引 2)可以坐下,因为左侧和右侧都为空。
- 总共可以坐下 1 名学生。
复杂度分析
-
时间复杂度:
- 遍历数组一次,时间复杂度为
O(n)
,其中n
是数组的长度。
- 遍历数组一次,时间复杂度为
-
空间复杂度:
- 除了输入数组外,只使用了常数级别的额外空间,空间复杂度为
O(1)
。
- 除了输入数组外,只使用了常数级别的额外空间,空间复杂度为
总结
- C语言 和 C++ 代码的逻辑一致,主要通过遍历数组检查每个空座位的左右是否为空,来计算可以坐下的学生数量。
- C语言 使用静态数组和
scanf
处理输入,适合固定长度的场景。 - C++ 使用动态数组和
cin
处理输入,适合动态长度的场景。 - 如果有其他问题,欢迎继续提问!