【Py/Java/C++三种语言OD独家2024D卷真题】20天拿下华为OD笔试之【贪心】2024D-座位调整/2024D-找座位【欧弟算法】全网注释最详细分类最全的华为OD真题题解

有LeetCode算法/华为OD考试扣扣交流群可加 948025485
可上全网独家的 欧弟OJ系统 练习华子OD、大厂真题
绿色聊天软件戳 od1441了解算法冲刺训练(备注【CSDN】否则不通过)

从2024年4月15号开始,OD机考全部配置为2024D卷
注意两个关键点:

  1. 会遇到C卷复用题。虽然可能存在幸存者偏差,但肯定还会有一大部分的旧题。
  2. 现在又支持做完题目之后倒回去改了。就是可以先做200的再做100的,然后可以反复提交。
    在这里插入图片描述

题目描述与示例

题目描述

疫情期间课堂的座位进行了特殊的调整,不能出现两个同学紧挨着,必须隔至少一个空位。

给你一个整数数组 desk 表示当前座位的占座情况,由若干 01 组成,其中 0 表示没有占位,1 表示占位。在不改变原有座位秩序情况下,还能安排坐几个人?

输入

第一行是个子数组表示作为占座情况,由若干 01 组成,其中 0 表示没有占位,1 表示占位

输出

输出数值表示还能坐几个人

说明

1 <= desk.length <= 2 * 10^4

示例一

输入

1,0,0,0,1

输出

1

说明

只有 desk[2] 的位置可以坐一个人

示例二

输入

0,0,0,0,0

输出

3

解题思路

注意,本题和LC605. 种花问题几乎完全一致。

很多同学对这个经典的贪心问题感到混乱。

只知道应该在一个while循环下进行不定步长的索引前进,但是具体如何实现,仍然容易搞不清楚。

注意题目中有一个非常重要的隐藏条件:原数组中不会出现连续的两个紧挨着的1

在考虑位置i的近邻位置的时候,我们始终只考虑i后面的位置(比如i+1i+2i+3),而不会向前考虑i前面的位置(比如i-1)。

这是因为,i前面的位置是否为1,已经在考虑i前面位置时的向后考虑判断过了。

实际上,对于任意一个位置i,只可能出现以下3种情况。

注意,x表示既可能是0也可能是1,是后续要跳到的位置。

  • 情况1:第i个位置是1。那么第i+1个位置一定是0。下一步我们需要跳到第i+2的位置。在第i个位置和第i+1个位置我们都不能种花。种花数目不需要修改。
i   i+2
↓   ↓
1 0 x
  • 情况2:第i个位置是0,第i+1个位置也是0。下一步我们需要跳到第i+2的位置。我们贪心地选择在第i个位置种花。种花数目修改。
i   i+2
↓   ↓
0 0 x
  • 情况3:第i个位置是0,第i+1个位置是1,那么第i+2个位置一定是0,下一步我们需要跳到第i+3的位置。在第i个、第i+1个、第i+2个位置我们都不能种花。种花数目不修改。
i     i+3
↓     ↓
0 1 0 x

我们可以看到,每次进行索引更新之后,x(不管x1还是0),x的前一个位置,都一定是0

所以我们不需要去考虑i-1的情况,只需要考虑i后面位置的索引的情况。

另外,就是边界值的处理。对于情况2而言,如果lst[i]0,且已经到达了数组的最后一个位置lst[n-1],那么同样要进行答案更新。

代码

python

# 题目:2023B-座位调整
# 分值:100
# 作者:许老师-闭着眼睛学数理化
# 算法:贪心
# 代码看不懂的地方,请直接在群上提问


# 输入的座位数组
lst = input().split(",")
# 能坐下的总人数
ans = 0

# 遍历数组,在遍历过程中,采取贪心的思路,并不需要【每个位置】都去查看是否可以坐下
# 1、当前位置已经有人坐下,那么后一个位置明显不能坐下,可以跳过去
# 2、当前位置没有人坐下,需要考虑后面一个位置是否有人已经坐下

# 初始化座位索引为0
i = 0

while i < len(lst):
    # 对应情况1
    # 1、当前位置已经有人坐下,lst[i] == "1",那么后一个位置明显不能坐下,可以跳过去
    # 所以让 i 执行加 2 操作,跳过了加 1 后的那个位置
    if lst[i] == "1":
        # 让 i 执行加 2 操作
        i += 2
    # 2、否则说明当前位置没有人坐下 lst[i] == "0"
    else:
        # 对应情况2
        # 3、如果这个位置【是】数组的最后一个位置,说明后一个位置不存在,没有限制,说明 lst[i] 可以坐下
        # 4、如果这个位置【不是】数组的最后一个位置,那么只有当后一个位置【没人坐下】,才有资格在 lst[i] 位置坐下
        # 这两种条件都可以在 lst[i] 位置坐下
        if i == len(lst) - 1 or lst[i + 1] == "0":
            # 成功之后,坐下人数ans + 1
            ans += 1
            # 在 lst[i] 位置种花之后,i + 1 位置不需要去考虑了,因为它明显不能种花,可以跳过去
            # 让 i 执行加 2 操作
            i += 2

        # 对应情况3
        # 5、当前位置没有人坐下 lst[i] == "0"
        # 6、但是后一个位置已经有人坐下了,那么当前位置无法坐下
        # i + 1 位置已经坐下,不用再去访问一遍
        # i + 2 位置考虑到 i + 1 位置已经有人坐下,所以也无法坐下,不用再去访问
        # 让 i 执行加 3 操作
        else:
            i += 3

print(ans)

java

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String[] lst = scanner.nextLine().split(",");
        int ans = 0;
        int i = 0;

        while (i < lst.length) {
            if (lst[i].equals("1")) {
                i += 2;
            } else {
                if (i == lst.length - 1 || lst[i + 1].equals("0")) {
                    ans += 1;
                    i += 2;
                } else {
                    i += 3;
                }
            }
        }
        System.out.println(ans);
    }
}

cpp

#include <iostream>
#include <sstream>
#include <vector>

using namespace std;

int main() {
    string line;
    getline(cin, line);
    istringstream iss(line);
    vector<string> lst;
    string val;

    while (getline(iss, val, ',')) {
        lst.push_back(val);
    }

    int ans = 0;
    int i = 0;

    while (i < lst.size()) {
        if (lst[i] == "1") {
            i += 2;
        } else {
            if (i == lst.size() - 1 || lst[i + 1] == "0") {
                ans += 1;
                i += 2;
            } else {
                i += 3;
            }
        }
    }
    cout << ans << endl;
    return 0;
}

时空复杂度

时间复杂度:O(N)。仅需一次遍历数组

空间复杂度:O(1)。仅需要用到若干常数变量。

相同问题不同描述

2024D-找座位

题目描述

在一个大型体育场内举办了一场大型活动,由于疫情防控的需要,要求每位观众的必须间隔至少一个空位才允许落座。现在给出一排观众座位分布图,座位中存在已落座的观众,请计算出,在不移动现有观众座位的情况下,最多还能坐下多少名观众。

输入描述

一个数组,用来标识某一排座位中,每个座位是否已经坐人。0 表示该座位没有坐人,1 表示该座位已经坐人。 1 <= 数组长度 <= 10000

输出描述

整数,在不移动现有观众座位的情况下,最多还能坐下多少名观众。

示例一

输入
10001
输出
1

示例二

输入
0101
输出
0

华为OD算法/大厂面试高频题算法练习冲刺训练

  • 华为OD算法/大厂面试高频题算法冲刺训练目前开始常态化报名!目前已服务300+同学成功上岸!

  • 课程讲师为全网50w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化

  • 每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!

  • 60+天陪伴式学习,40+直播课时,300+动画图解视频,300+LeetCode经典题,200+华为OD真题/大厂真题,还有简历修改、模拟面试、专属HR对接将为你解锁

  • 可上全网独家的欧弟OJ系统练习华子OD、大厂真题

  • 可查看链接 大厂真题汇总 & OD真题汇总(持续更新)

  • 绿色聊天软件戳 od1336了解更多

  • 20
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值