题目描述
奶牛贝茜正在学习如何在不同进制之间转换数字。
但是她总是犯错误,因为她无法轻易的用两个前蹄握住笔。
每当贝茜将数字转换为一个新的进制并写下结果时,她总是将其中的某一位数字写错。
例如,如果她将数字 1414 转换为二进制数,那么正确的结果应为 11101110,但她可能会写下 01100110 或 11111111。
贝茜不会额外添加或删除数字,但是可能会由于写错数字的原因,写下包含前导 00 的数字。
给定贝茜将数字 NN 转换为二进制数字以及三进制数字的结果,请确定 NN 的正确初始值(十进制表示)。
输入格式
第一行包含 NN 的二进制表示,其中一位是错误的。
第二行包含 NN 的三进制表示,其中一位是错误的。
输出格式
输出正确的 NN 的值。
数据范围
0≤N≤1090≤N≤109,且存在唯一解。
输入样例:
1010 212
输出样例:
14
样例解释
1414 在二进制下的正确表示为 11101110,在三进制下的正确表示为 112112。
解题思路:
假设输入二位数是m,三位数是n。
注意“每当贝茜将数字转换为一个新的进制并写下结果时,她总是将其中的某一位数字写错。”
说明m和n位数中的一位是错的,数据大小是10e9,二位数和三位数的位数最多也就是几十位,那么我们可以枚举每个位数,假设这个位数是错的,并改变这个位数。如果二进制和三进制改变结果的十位数是相同的,则取得了正确答案。
所以整体思路是将所有可能的二进制数和所有可能的三进制数求交集,因为题目说明是唯一解,所以这种方法得到的是正确答案
程序流程图
将m的每一位改变,该位是0变为1,该位是1变为0一共得到了m.length()个可能的数,将其存入数组或集合、列表等
将n的每一位数改变,该位是0变为1和2,该位是1变为0和2,该位是2变为0和1。
求交集,如果用数组存储所有可能,则使用一个二重循环求交集,可能最多是十位数,时间复杂度可以接受。如果用集合HashSet存储,则直接使用HashSet中的contains(s)方法,检查s是否在集合中求交集。因为是唯一解,所以找到二进制和三进制的交集直接输出。
代码如下:
事实上,这题使用char数组修改也可以很方便
import java.util.Scanner;
import java.util.HashSet;
public class Main
{
public static void main(String[] args)
{
Scanner input=new Scanner(System.in);
StringBuffer m,n;
m=new StringBuffer(input.nextLine());
n=new StringBuffer(input.nextLine());
HashSet<Integer>BinaryNumber=new HashSet<Integer>();
HashSet<Integer>TernaryNumber=new HashSet<Integer>();
for(int i=0;i<m.length();i++)
{
StringBuffer bookM=new StringBuffer(m.toString());
//将二进制数尝试换位
String testBinary=bookM.replace(i,i+1,oppositeBinary(m.charAt(i))).toString();
//将换位的二进制字符串转换成数字
int BinaryInteger=Integer.parseInt(testBinary,2);
//将数字存入哈希表集合中
BinaryNumber.add(BinaryInteger);
}
for(int i=0;i<n.length();i++)
{
StringBuffer bookN=new StringBuffer(n.toString());
for(int j=0;j<3;j++)
{
//如果三进制数对应位数的数不是j,则进行换位操作
if(j+'0'!=n.charAt(i))
{
String testTernary=bookN.replace(i,i+1,String.valueOf(j)).toString();
int TernaryInteger=Integer.parseInt(testTernary,3);
if(BinaryNumber.contains(TernaryInteger))
{
System.out.print(TernaryInteger);
}
}
}
}
}
public static String oppositeBinary(char x)
{
if(x=='0') return "1";
else return "0";
}
}