全网最全面的华为OD机试真题汇总,100%原题题库,不需要开会员即可查看全部内容,更多考题请查看真题库。
真题库:https://www.yuque.com/codernav.com/od
题目:对称字符串
时间限制:1s 空间限制:256MB 限定语言:不限
题目描述:
对称就是最大的美学,现有一道关于对称字符串的美学。已知:
第 1 个字符串:R
第 2 个字符串:BR
第 3 个字符串:RBBR
第 4 个字符串:BRRBRBBR
第 5 个字符串:RBBRBRRBBRRBRBBR
相信你已经发现规律了,没错!就是第 i 个字符串 = 第 i - 1 号字符串的取反 + 第 i - 1 号字符串;取反(R->B, B->R);
现在告诉你 n 和 k,让你求得第 n 个字符串的第 k 个字符是多少。(k的编号从 0 开始)
输入描述:
第一行输入一个T,表示有T组用例;
接下里输入T行,每行输入两个数字,表示n, k
1 <= T <= 100;
1 <= n <= 64;
0 <= k < 2^(n-1);
输出描述:
输出T行表示答案;
输出 "blue" 表示字符是B;
输出 "red" 表示字符是R;
补充说明:
输出字符串区分大小写,请注意输出小写字符串,不带双引号
示例1
输入:
5
1 0
2 1
3 2
4 6
5 8
输出:
red
red
blue
blue
blue
说明:
第 1 个字符串:R -> 第0个字符为R
第 2 个字符串:BR -> 第1个字符为R
第 3 个字符串:RBBR -> 第2个字符为B
第 4 个字符串:BRRBRBBR -> 第6个字符为B
第 5 个字符串:RBBRBRRBBRRBRBBR -> 第8个字符为B
示例2
输入:
1
64 73709551616
输出:
red
解题思路:
算法1:
例:
1
5 8
n=5,k=8
第 5 个字符串:RBBRBRRBBRRBRBBR 总字符串个数 2^(5-1) = 16,半数half=16/2=8;
k=8 == half(8),说明第k=8个字符在后半部分,这串字符是继承的第4个字符串,没有进行翻转,且此字符在第4个字符串的位置为 8 - half(8)=0;
第 4 个字符串:BRRBRBBR 总字符串个数 2^(4-1) = 8,半数half=8/2=4;
k=0<half(4),说明第k=0个字符在前半部分,这串字符是经过第3个翻转的,则位置不变。
第 3 个字符串:RBBR 总字符串个数 2^(3-1)=4,半数half=4/2=2;
k=0<half(2),说明第k=0个字符在前半部分,这串字符是经过第2个翻转的,则位置不变;
第 2 个字符串:BR 总字符串个数 2^(2-1)=2,半数half=2/2=1;
k=0<half(1),说明第k=0个字符在前半部分,这串字符是经过第1个翻转的,则位置不变;
第 1 个字符串:R 总字符串个数 2^(1-1)=1,到了第一个R。
求出总共经过3次翻转,R->B->R->B,得到结果为blue
算法2:
主要使用回溯求出所有字符串,然后获取其对应索引的字符。
代码实现一:
package com.codernav.demo.hwod.exam; import java.util.Scanner; /** * @title 对称字符串 * @Description 对称就是最大的美学,现有一道关于对称字符串的美学。已知: * 第 1 个字符串:R * 第 2 个字符串:BR * 第 3 个字符串:RBBR * 第 4 个字符串:BRRBRBBR * 第 5 个字符串:RBBRBRRBBRRBRBBR * 相信你已经发现规律了,没错!就是第 i 个字符串 = 第 i - 1 号字符串的取反 + 第 i - 1 号字符串;取反(R->B, B->R); * 现在告诉你 n 和 k,让你求得第 n 个字符串的第 k 个字符是多少。(k的编号从 0 开始) * @Author 开发者导航 * @website https://codernav.com * @date 2023/5/13 */ public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int T = sc.nextInt(); for (int i = 0; i < T; i++) { int n = sc.nextInt(); long k = sc.nextLong(); long charNum = (long) Math.pow(2, n - 1); //第n行的总字符个数 int re = doProcess(charNum, k, 0); if (re % 2 == 0) { System.out.println("red"); //翻转次数为2的倍数 } else { System.out.println("blue"); } } } /** * 翻转次数 * * @param count 总字符的个数 * @param cur 字符的索引 * @param reverse 翻转次数 * @return */ public static int doProcess(long count, long cur, int reverse) { if (count == 1) { return reverse; } long half = count / 2; if (cur < half) { //小于半数说明是经过翻转的部分 reverse++; return doProcess(half, cur, reverse); } else { return doProcess(half, cur - half, reverse); } } }
代码实现二:这是一种普通的解法,有些用例可能会超时。
package com.codernav.demo.hwod.exam; import java.util.Scanner; /** * @title 对称字符串 * @Description 对称就是最大的美学,现有一道关于对称字符串的美学。已知: * 第 1 个字符串:R * 第 2 个字符串:BR * 第 3 个字符串:RBBR * 第 4 个字符串:BRRBRBBR * 第 5 个字符串:RBBRBRRBBRRBRBBR * 相信你已经发现规律了,没错!就是第 i 个字符串 = 第 i - 1 号字符串的取反 + 第 i - 1 号字符串;取反(R->B, B->R); * 现在告诉你 n 和 k,让你求得第 n 个字符串的第 k 个字符是多少。(k的编号从 0 开始) * @Author 开发者导航 * @website https://codernav.com * @date 2023/5/13 */ public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int T = sc.nextInt(); for (int i = 0; i < T; i++) { int n = sc.nextInt(); int k = sc.nextInt(); String string = doProcess(n); String res = string.charAt(k) == 'R' ? "red" : "blue"; System.out.println(res); } } /** * 第n行字符串 * * @param n 字符串行数 * @return */ public static String doProcess(int n) { if (n == 1) { //当n为1时输出R return "R"; } String str = doProcess(n - 1); //当n大于等于2时需要对字符进行反转处理 String reverseStr = ""; for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); if (c == 'R') { reverseStr += 'B'; } else { reverseStr += 'R'; } } return reverseStr + str; } }