华为OD刷题C卷 - 每日刷题 10(连续出牌数量,字符串筛选排序)

73 篇文章 0 订阅
37 篇文章 1 订阅

两段代码分别解决了两个不同的算法问题,下面是对它们的概述:

第一段代码(连续出牌数量):

这段代码是解决“连续出牌数量”的问题。它提供了一个Java类Main,其中包含main方法和getResult方法,以及一个内部Card类,用于定义卡牌的颜色和数字。

main方法首先读取手牌的数字和对应的颜色,然后调用getResult方法并打印能够打出的最大手牌数量。

getResult方法创建一个Card数组来存储每张卡牌的信息,然后使用一个布尔数组isUsed来跟踪已经打出的卡牌。该方法调用dfs方法来通过回溯算法寻找最优的出牌策略。

dfs方法是一个递归函数,用于尝试所有可能的出牌顺序。它遍历所有卡牌,如果一张卡牌可以跟随上一张卡牌(即颜色或数字相同),则将其标记为已使用,并递归地继续出牌。每次递归调用都会增加出牌数量,并在回溯时恢复卡牌状态(即将卡牌标记为未使用)。

最后,res变量存储了最大出牌数量,并作为结果返回。

2、(字符串筛选排序):

这段代码是解决“字符串筛选排序”的问题。它提供了一个Java类Main,其中包含main方法和getIndex方法。

main方法首先读取一个由大小写字母组成的字符串和整数k,然后调用getIndex方法并打印出第k个最小ASCII码值的字母在字符串中的位置索引。

getIndex方法将字符串转换为字符数组,然后对数组进行排序。如果k大于字符串的长度,则将k设置为字符串长度。接着,找到排序后数组中第k-1个位置的字符(即第k个最小ASCII码值的字符),并返回该字符在原始字符串中第一次出现的索引。

package OD216;

import java.util.Arrays;
import java.util.Scanner;

/**
 * @description 连续出牌数量
 * @level 7
 * @score 200
 */

/**
 * 题目描述
 * 有这么一款单人卡牌游戏,牌面由颜色和数字组成,颜色为红、黄、蓝、绿中的一种,数字为0-9中的一个。游戏开始时玩家从手牌中选取一张卡牌打出,接下来如果玩家手中有和他上一次打出的手牌颜色或者数字相同的手牌,他可以继续将该手牌打出,直至手牌打光或者没有符合条件可以继续打出的手牌。
 * <p>
 * 现给定一副手牌,请找到最优的出牌策略,使打出的手牌最多。
 * <p>
 * 输入描述
 * 输入为两行
 * <p>
 * 第一行是每张手牌的数字,数字由空格分隔,
 * 第二行为对应的每张手牌的颜色,用r y b g这4个字母分别代表4种颜色,字母也由空格分隔。
 * 手牌数量不超过10。
 * <p>
 * 输出描述
 * 输出一个数字,即最多能打出的手牌的数量。
 */
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    //新建一个牌类,记录颜色和牌面
    static class Card {
        int num;
        char color;

        public Card(int num, String color) {
            this.num = num;
            this.color = color.charAt(0);
        }

    }

    //最大出牌数
    static int res = 0;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        //牌的数字
        int[] nums = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
        //牌的颜色 r y b g
        String[] colors = sc.nextLine().split(" ");
        System.out.println(getResult(nums, colors));
    }

    public static int getResult(int[] nums, String[] colors) {
        int n = nums.length;
        //新建卡牌数组 把对应的牌面和颜色填进去
        Card[] cards = new Card[n];
        for (int i = 0; i < n; i++) {
            cards[i] = new Card(nums[i], colors[i]);
        }
        boolean[] isUsed = new boolean[n];
        dfs(cards, null, isUsed, 0);
        return res;
    }

    //回溯算法 求最大出牌数 数字相同或颜色相同都可以出
    public static void dfs(Card[] cards, Card lastCard, boolean[] isUsed, int count) {
        res = Math.max(count, res);
        for (int i = 0; i < cards.length; i++) {
            if (isUsed[i]) continue;
            //当前卡牌
            Card curCard = cards[i];
            //如果上一个不为空,且牌面和数字都不同,则跳过
            if (lastCard != null && lastCard.num != curCard.num && lastCard.color != curCard.color) continue;
            //否则,该牌可以打出
            isUsed[i] = true;
            //递归
            dfs(cards, curCard, isUsed, count + 1);
            //恢复状态
            isUsed[i] = false;
        }
    }


}
package OD218;

import java.util.*;

/**
 * @description 字符串筛选排序
 * @level 4
 */

/**
 * 题目描述
 * 输入一个由N个大小写字母组成的字符串
 * <p>
 * 按照ASCII码值从小到大进行排序
 * <p>
 * 查找字符串中第K个最小ASCII码值的字母(k>=1)
 * <p>
 * 输出该字母所在字符串中的位置索引(字符串的第一个位置索引为0)
 * <p>
 * k如果大于字符串长度则输出最大ASCII码值的字母所在字符串的位置索引
 * <p>
 * 如果有重复字母则输出字母的最小位置索引
 * <p>
 * 输入描述
 * 第一行输入一个由大小写字母组成的字符串
 * <p>
 * 第二行输入k ,k必须大于0 ,k可以大于输入字符串的长度
 * <p>
 * 输出描述
 * 输出字符串中第k个最小ASCII码值的字母所在字符串的位置索引
 * <p>
 * k如果大于字符串长度则输出最大ASCII码值的字母所在字符串的位置索引
 * <p>
 * 如果第k个最小ASCII码值的字母存在重复 则输出该字母的最小位置索引
 */
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        //读取字符串
        String str = sc.nextLine();
        //从小到大排序第k个ASCII码
        int k = Integer.parseInt(sc.nextLine());
        System.out.println(getIndex(str, k));

    }

    //输出字符串中第k个最小ASCII码值的字母所在字符串的位置索引
    public static int getIndex(String str, int k) {
        char[] chars = str.toCharArray();
        //按ASCII码排序
        Arrays.sort(chars);
        if (k > chars.length) {
            k = chars.length;
        }
        //第k个字符是
        char target = chars[k - 1];
        //返回该字符在str中第一次出现的索引
        return str.indexOf(target);
    }
}
  • 10
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值