华为OD刷题C卷 - 每日刷题38(万能字符单词拼写,虚拟理财游戏)

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

1、(万能字符单词拼写):

这段代码是解决“万能字符单词拼写”的问题。它提供了一个Java类Main,其中包含main方法和getResult方法,以及一个辅助方法success,用于计算使用给定字符chars能拼写出的单词words中的单词个数。

main方法首先读取单词数组words的个数和每个单词,然后读取掌握的字符control。接着,调用getResult方法并打印能拼写出的单词个数。

getResult方法遍历所有单词,并使用success方法检查每个单词是否能使用control中的字符拼写。如果能,计数器加一。

success方法首先统计control中万能字符?的数量。然后,遍历单词中的每个字符,检查该字符是否在control中。如果不在,但还有万能字符,就减少万能字符的数量;如果不在,且没有万能字符,则返回false。如果所有字符都能匹配,则返回true。

2、(虚拟理财游戏):

这段代码是解决“虚拟理财游戏”的问题。它提供了一个Java类Main,其中包含main方法,用于在虚拟游戏中选择最优的投资方式以获得最大回报。

main方法首先读取产品数、总投资额和可接受的总风险值。然后,读取每个产品的投资回报率、风险值和最大投资额度。接着,使用嵌套循环遍历所有可能的投资组合,更新最大投资回报和最小风险值,并记录最优投资策略。

最后,使用StringJoiner构建每个产品的投资额序列,并打印结果。

package OD371;

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

/**
 * @description 万能字符单词拼写
 * @level 4
 * @score 100
 */

/**
 * 题目描述
 * 有一个字符串数组 words 和一个字符串 chars。
 * <p>
 * 假如可以用 chars 中的字母拼写出 words 中的某个“单词”(字符串),那么我们就认为你掌握了这个单词。
 * <p>
 * words 的字符仅由 a-z 英文小写字母组成,例如 "abc"
 * <p>
 * chars 由 a-z 英文小写字母和 "?" 组成。其中英文 "?" 表示万能字符,能够在拼写时当作任意一个英文字母。例如:"?" 可以当作 "a" 等字母。
 * <p>
 * 注意:每次拼写时,chars 中的每个字母和万能字符都只能使用一次。
 * <p>
 * 输出词汇表 words 中你掌握的所有单词的个数。没有掌握任何单词,则输出0。
 * <p>
 * 输入描述
 * 第一行:输入数组 words 的个数,记作N。
 * <p>
 * 第二行 ~ 第N+1行:依次输入数组words的每个字符串元素
 * <p>
 * 第N+2行:输入字符串chars
 * <p>
 * 输出描述
 * 输出一个整数,表示词汇表 words 中你掌握的单词个数
 * <p>
 * 备注
 * 1 ≤ words.length ≤ 100
 * 1 ≤ words[i].length, chars.length ≤ 100
 * 所有字符串中都仅包含小写英文字母、英文问号
 */
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        //单词数组个数
        int n = Integer.parseInt(sc.nextLine());
        //单词数组
        String[] words = new String[n];
        for (int i = 0; i < n; i++) {
            words[i] = sc.nextLine();
        }
        //掌握的字符
        String control = sc.nextLine();
        //输出能拼写出来的单词个数
        System.out.println(getResult(words, control));
    }

    //输出能用掌握的单词拼写出单词的个数
    public static int getResult(String[] words, String control) {
        int count = 0;
        for (int i = 0; i < words.length; i++) {
            if (success(words[i], control)) {
                count++;
            }
        }
        return count;
    }

    //判断word能否被已掌握的字符拼写出
    public static boolean success(String word, String control) {
        //统计control中?的个数
        char[] chars = control.toCharArray();
        int n = chars.length;
        int count = 0;
        for (int i = 0; i < n; i++) {
            if (chars[i] == '?') {
                count++;
            }
        }
        char[] words = word.toCharArray();
        int m = words.length;
        for (int i = 0; i < m; i++) {
            //如果字符不在已掌握的字符里或没有多余?号,则返回false
            if (!control.contains(words[i] + "")) {
                //判断是否还有?
                if (count > 0) {
                    count--;
                } else {
                    return false;
                }
            } else {
                //每个字符只能用一次,所以需要把匹配到的字符去掉
                control = control.replaceFirst(words[i] + "", "");
            }
        }
        return true;
    }

} 
package OD372;

import java.util.*;

/**
 * @description 虚拟理财游戏
 * @level 6
 * @score 100
 */

/**
 * 题目描述
 * 在一款虚拟游戏中生活,你必须进行投资以增强在虚拟游戏中的资产以免被淘汰出局。
 * <p>
 * 现有一家Bank,它提供有若干理财产品 m 个,风险及投资回报不同,你有 N(元)进行投资,能接收的总风险值为X。
 * <p>
 * 你要在可接受范围内选择最优的投资方式获得最大回报。
 * <p>
 * 备注:
 * <p>
 * 在虚拟游戏中,每项投资风险值相加为总风险值;
 * 在虚拟游戏中,最多只能投资2个理财产品;
 * 在虚拟游戏中,最小单位为整数,不能拆分为小数;
 * 投资额*回报率=投资回报
 * 输入描述
 * 第一行:
 * <p>
 * 产品数(取值范围[1,20])
 * 总投资额(整数,取值范围[1, 10000])
 * 可接受的总风险(整数,取值范围[1,200])
 * 第二行:产品投资回报率序列,输入为整数,取值范围[1,60]
 * <p>
 * 第三行:产品风险值序列,输入为整数,取值范围[1, 100]
 * <p>
 * 第四行:最大投资额度序列,输入为整数,取值范围[1, 10000]
 * <p>
 * 输出描述
 * 每个产品的投资额序列
 */
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        //产品数 总投资额 可接受的总风险
        int[] line1 = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
        int m = line1[0];//[1,20]
        int n = line1[1];//[1,10000]
        int x = line1[2];//[1,200]
        //投资回报率序列
        int[] backs = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
        //产品风险
        int[] risks = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
        //最大投资额度序列
        int[] invests = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
        //最大投资回报
        int max_invest_back = 0;
        //最小风险值
        int min_invest_risk = Integer.MAX_VALUE;
        //存放最后选择的iD和对应投资额
        Map<Integer, Integer> select = new HashMap<>();
        for (int i = 0; i < m; i++) {
            //如果当前产品风险大于最大风险,跳过
            if (risks[i] > x) {
                continue;
            }
            //如果投资单件产品最优
            if (risks[i] <= x) {
                //产品i的投资额
                int invest_i = Math.min(invests[i], n);
                //产品i的投资回报
                int back_i = invest_i * backs[i];
                //如果只投资i产品,投资回报高于当前的最优策略,或者等于最优但风险值更小
                if (back_i > max_invest_back || back_i == max_invest_back && risks[i] < min_invest_risk) {
                    //更新最大投资回报
                    max_invest_back = back_i;
                    //更新最小风险
                    min_invest_risk = risks[i];
                    //把之前选择清空,重新选择
                    select.clear();
                    select.put(i, invest_i);
                }
            }
            //购买两个产品
            for (int j = i + 1; j < m; j++) {
                //如果总风险不超过risk_all 则都投资
                if (risks[i] + risks[j] <= x) {
                    //产品i j分别的投资额
                    int invest_i;
                    int invest_j;
                    //如果投资回报率不相同,则谁回报率高,谁多投
                    if (backs[i] != backs[j]) {
                        if (backs[i] > backs[j]) {
                            //总和不能超过n
                            invest_i = Math.min(invests[i], n);
                            invest_j = Math.min(invests[j], n - invest_i);
                        } else {
                            invest_j = Math.min(invests[j], n);
                            invest_i = Math.min(invests[i], n - invest_j);
                        }
                    } else {
                        //产品回报率相同,谁风险小,谁多投
                        if (risks[i] < risks[j]) {
                            invest_i = Math.min(invests[i], n);
                            invest_j = Math.min(invests[j], n - invest_i);
                        } else {
                            invest_j = Math.min(invests[j], n);
                            invest_i = Math.min(invests[i], n - invest_j);
                        }
                    }
                    //投资两个产品的总投资回报
                    int invest_back = invest_i * backs[i] + invest_j * backs[j];
                    //总风险
                    int invest_risk = risks[i] + risks[j];
                    //如果大于当前最优投资回报 或等于但风险更小,则更新
                    if (invest_back > max_invest_back || invest_back == max_invest_back && invest_risk < min_invest_risk) {
                        max_invest_back = invest_back;
                        min_invest_risk = invest_risk;
                        //清空当前最优策略
                        select.clear();
                        //添加当前的最优策略 id 投资额
                        if (invest_i > 0) {
                            select.put(i, invest_i);
                        }
                        if (invest_j > 0) {
                            select.put(j, invest_j);
                        }
                    }
                }
            }
        }
        //存放结果
        StringJoiner sj = new StringJoiner(" ");
        for (int k = 0; k < m; k++) {
            //如果id在select中,则添加对应的投资额
            if (select.containsKey(k)) {
                sj.add(select.get(k) + "");
            } else {
                sj.add("0");
            }
        }
        System.out.println(sj);
    }
}
  • 13
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值