最长连续手牌 - 华为OD统一考试

OD统一考试(C卷)

分值: 200分

题解: Java / Python / C++

alt

题目描述

有这么一款单人卡牌游戏,牌面由颜色和数字组成,颜色为红、黄、蓝、绿中的一种,数字为 0−9 中的一个。游戏开始时玩家从手牌中选取一张卡牌打出,接下来如果玩家手中有和他上一次打出的手牌颜色或者数字相同的手牌,他可以继续将该手牌打出,直至手牌打光或者没有符合条件可以继续打出的手牌。

现给定一副手牌,请找到最优的出牌策略,使打出的手牌最多。

输入描述

第一行是每张手牌的数字,数字由空格分隔

第二行为对应的每张手牌的颜色,用 rybg 这 4 个字母分别代表 4 种颜色,字母也由空格分隔。

手牌数量不超过10。

输出描述

输出一个数字,即最多能打出的手牌的数量。

示例1

输入:
1 4 3 4 5
r y b b r输出:
3说明:
如果打(1,r)-> (5,r),那么能打两张。如果打(4,y) -> (4,b) -> (3,b),那么能打三张。

示例2

输入:
1 2 3 4
r y b l输出:
1说明:
没有能够连续出牌的组合,只能在开始时打出一张手牌,故输出 1 。

题解

题目类型: 深度优先搜索(DFS)

解题思路:

  1. 通过深度优先搜索遍历所有可能的出牌组合。
  2. 维护一个全局变量 maxCnt,记录最多能打出的手牌数。
  3. 递归函数 dfs 中,遍历未使用过的手牌,判断是否能打出。如果可以,标记为已使用,继续递归下一层。
  4. 在递归的过程中更新 maxCnt
  5. 最终返回 maxCnt

时间复杂度: 搜索的时间复杂度取决于搜索空间的大小,最坏情况下为 O(2^n),其中 n 为手牌数量。每张牌有两种状态:打出或不打出。

空间复杂度: 递归调用的深度为手牌数量,因此空间复杂度为 O(n)。

Java

import java.util.Arrays;
import java.util.Objects;
import java.util.Scanner;/*** @author code5bug*/
public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);// 读取卡牌数字列表int[] nums = Arrays.stream(in.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();// 读取卡牌颜色列表String[] colors = in.nextLine().split(" ");Solution solution = new Solution();// 调用 solve 方法求解并输出结果int result = solution.solve(nums, colors);System.out.println(result);}}class Solution {private int maxCnt;public int solve(int[] nums, String[] colors) {this.maxCnt = 0;dfs(-1, 0, nums, colors, new boolean[nums.length]);return this.maxCnt;}private void dfs(int prev, int cnt, int[] nums, String[] colors, boolean[] vis) {// 更新最多可以打出的手牌数this.maxCnt = Math.max(cnt, this.maxCnt);for (int cur = 0; cur < nums.length; cur++) {if (vis[cur]) continue;// 之前未打出牌 或 和前面牌数相同 或 和前面牌颜色相同if (prev == -1 || nums[prev] == nums[cur] || Objects.equals(colors[prev], colors[cur])) {vis[cur] = true;dfs(cur, cnt + 1, nums, colors, vis);  // 打出当前的牌vis[cur] = false;}}}
}

Python

from typing import Listdef solve(nums: List[int], colors: list[str]) -> int:# 卡牌数量, 最多可以打出的手牌数n, max_cnt = len(nums), 0vis = [False] * ndef dfs(prev, cnt):"""param: prev 前一张打出的牌param: cnt 已经打出的手牌数"""nonlocal max_cnt, n, vismax_cnt = max(cnt, max_cnt)  # 更新最多可以打出的手牌数for cur in range(n):if vis[cur]:continue# 之前未打出牌 或 和前面牌数相同 或 和前面牌颜色相同if prev == -1 or nums[prev] == nums[cur] or colors[prev] == colors[cur]:vis[cur] = Truedfs(cur, cnt + 1)  # 打出 cur 当前的牌vis[cur] = Falsedfs(-1, 0)return max_cntif __name__ == "__main__":nums = list(map(int, input().split()))colors = list(map(str, input().split()))print(solve(nums, colors))

C++

#include <iostream>
#include <sstream>
#include <vector>using namespace std;template <typename T>
vector<T> readList() {string input;getline(cin, input);stringstream stream(input);vector<T> result;T value;while (stream >> value) {result.push_back(value);}return result;
}int maxCnt;void dfs(int prev, int cnt, vector<int>& nums, vector<string>& colors, vector<bool>& vis) {// 更新最多可以打出的手牌数maxCnt = max(cnt, maxCnt);for (size_t cur = 0; cur < nums.size(); cur++) {if (vis[cur]) continue;// 之前未打出牌 或 和前面牌数相同 或 和前面牌颜色相同if (prev == -1 || nums[prev] == nums[cur] || colors[prev] == colors[cur]) {vis[cur] = true;dfs(cur, cnt + 1, nums, colors, vis);  // 打出当前的牌vis[cur] = false;}}
}int main() {// 读取卡牌数字列表vector<int> nums = readList<int>();// 读取卡牌颜色列表vector<string> colors = readList<string>();maxCnt = 0;// 调用 dfs 方法求解并输出结果vector<bool> vis(nums.size(), false);dfs(-1, 0, nums, colors, vis);cout << maxCnt << endl;return 0;
}

‍❤️‍华为OD机试面试交流群每日真题分享): 加V时备注“华为od加群”

🙏整理题解不易, 如果有帮助到您,请给点个赞 ‍❤️‍ 和收藏 ⭐,让更多的人看到。🙏🙏🙏

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/471890.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一篇文章彻底搞懂 TiDB 集群各种容量计算方式

作者丨hey-hoho 来自神州数码钛合金战队 神州数码钛合金战队是一支致力于为企业提供分布式数据库 TiDB 整体解决方案的专业技术团队。团队成员拥有丰富的数据库从业背景&#xff0c;全部拥有 TiDB 高级资格证书&#xff0c;并活跃于 TiDB 开源社区&#xff0c;是官方认证合作…

OpenCV Mat实例详解 四

OpenCV Mat实例详解三中详细介绍来了OpenCV Mat类的公有静态成员函数&#xff0c;下面介绍OpenCV Mat类的其他常用成员函数。 OpenCV Mat类常用成员函数 Mat & adjustROI (int dtop, int dbottom, int dleft, int dright)&#xff1b; dtop ROI 上边界移动值&#xff0c;如…

结构体对齐规则及为什么会有结构体对齐

前言&#xff1a; 大家在学习结构体中&#xff0c;在计算结构体大小时想必会很疑惑&#xff0c;为什么结构体的大小不是按照常理像数组一样一个字节一个字节的挨在一起放&#xff1f;今天带大家一起深入探讨一下背后的规则和原因。 结构体对齐规则&#xff1a; 结构体对齐其实…

【防网盘在线解压】Peazip 豌豆压缩 v9.7.0

软件介绍 Peazip 是一个免费的文件归档应用程序&#xff0c; 支持跨平台&#xff0c;是和WinRar、WinZip类似软件的开源免费替代品&#xff1b;支持压缩/ 存档到 7Z&#xff0c; ARC、Brotli BR、BZip2、GZip、 PAQ、PEA、RAR、自解压档案、TAR、WIM、XZ、Zstandard ZST、打开…

最短路径(dijstra算法,链式前向星,堆优化)

【模板】单源最短路径&#xff08;弱化版&#xff09; 对于这题我们使用邻接矩阵的话会导致弓箭复杂度会大大提升&#xff0c;所以我们就需要学习一种新的数据结构&#xff0c;名叫链式前向星&#xff0c;在链式前向星中&#xff0c;我们需要定义一个结构体数组&#xff0c;其中…

【实战】二、Jest难点进阶(一) —— 前端要学的测试课 从Jest入门到TDD BDD双实战(五)

文章目录 一、Jest 前端自动化测试框架基础入门二、Jest难点进阶1.snapshot 快照测试 学习内容来源&#xff1a;Jest入门到TDD/BDD双实战_前端要学的测试课 相对原教程&#xff0c;我在学习开始时&#xff08;2023.08&#xff09;采用的是当前最新版本&#xff1a; 项版本babe…

SVD奇异值分解

一、奇异值 奇异值&#xff08;Singular Values&#xff09;是线性代数中矩阵的重要性质之一&#xff0c;与奇异值分解&#xff08;SVD&#xff09;密切相关。让我们来更详细地了解一下奇异值的概念&#xff1a; 定义&#xff1a; 对于一个矩阵 ( A )&#xff0c;它的奇异值是…

C++ “雪花算法“原理

C雪花算法并不是传统的数据结构与算法而是一种崭新的分布式算法 属于深层次C 本篇文章就来描述一下雪花算法 什么是雪花算法: 雪花算法&#xff08;Snowflake&#xff09;是Twitter开源的一种分布式唯一ID生成算法。它可以在不依赖于数据库等其他存储设施的情况下&#xff0c…

算法刷题:有效三角形个数

有效三角形个数 .题目链接题目详情算法原理补充知识点双指针:对撞指针 我的答案 . 题目链接 有效三角形个数 题目详情 算法原理 补充知识点 有效三角形需要满足的条件: ab>cac>bbc>a 其实在满足1的时候,c是最大的,那么2和3是显然成立的,因此我们可以这样解题: 对…

platformio 提示 fatal error: TimeLib.h: No such file or directory 的解决方案

在platformio编译arduino项目的时候&#xff0c;如果提示fatal error: TimeLib.h: No such file or directory&#xff0c;解决方法有2&#xff1a; 方法1&#xff1a; 在项目的platformio.ini文件中&#xff0c;添加 lib_deps # Using library Id44方法2&#xff1a; 通过…

第三百四十九回

文章目录 1. 概念介绍2. 原理与方法2.1 知识对比2.2 使用方法 3. 示例代码4. 内容总结 我们在上一章回中介绍了"加密包crypto"相关的内容&#xff0c;本章回中将介绍characters包.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 在项目中会遇到获取字…