N进制正反累加判回文数(洛谷P1015题题解,Java语言描述)
題目要求
P1015題目鏈接
分析
開(kāi)始的時(shí)候?qū)懥诉@么一個(gè)代碼,應(yīng)該是比較基礎(chǔ)的,是十進(jìn)制的。
private static void low() {Scanner scanner = new Scanner(System.in);int num = scanner.nextInt();String str = Integer.toString(num);int i;for (i = 0 ; i < 30; i++) {StringBuilder reverse = new StringBuilder(str).reverse();//是回文數(shù)if (str.equals(reverse.toString())) {break;}//不是回文數(shù),就增加數(shù)值num += Integer.parseInt(reverse.toString());str = Integer.toString(num);}if (i == 30) {System.out.println("Impossible!");} else {System.out.println("STEP=" + i);}scanner.close();}但本題是N進(jìn)制的,數(shù)據(jù)要求是 2 <= N <= 10 || N == 16 。
要將十六進(jìn)制和N進(jìn)制區(qū)分開(kāi)來(lái),分情況討論。
十六進(jìn)制的話,在我們使用char的時(shí)候,由于大寫字母與阿拉伯?dāng)?shù)字在ASCII里是不連續(xù)的,所以我覺(jué)得可以建立一個(gè)Integer與Character之間的雙射關(guān)系。
雙射關(guān)系的“一一對(duì)應(yīng)”不是很容易實(shí)現(xiàn),那就可以建立兩個(gè)HashMap,一個(gè)從Integer到Character,另一個(gè)從Character到Integer,利用HashMap的高效性來(lái)快速的存取。
讀題的話,字符串反轉(zhuǎn)是要做的。
Java不像C,貌似沒(méi)有直接的reverse(),但可以使用StringBuilder實(shí)現(xiàn):
還要做回文判定,既然有了reverse,那就直接利用String的equals()即可。二者結(jié)合就可以判定是否是回文數(shù)啦:
/*** 判斷是否為回文數(shù)* @param num 待判數(shù)值* @return 是否為回文數(shù)*/private static boolean isPalindrome(String num) {if (num.equals(reverse(num))) {return true;} else {return false;}}核心是如何操作至多100位的加法呢?(雖然洛谷里本題評(píng)測(cè)數(shù)據(jù)沒(méi)那么變態(tài))
只能是純粹的利用串和字符進(jìn)行加法,這也是核心的難點(diǎn)。
下面是十六進(jìn)制的加法:
/*** 十六進(jìn)制加法* @param num1 加數(shù)1* @param num2 加數(shù)2(位數(shù)與加數(shù)1相同)* @return 十六進(jìn)制和*/private static String hexAdd(String num1, String num2) {//獲取char[]char[] chars1 = num1.toCharArray();char[] chars2 = num2.toCharArray();//長(zhǎng)度int length = chars1.length;//結(jié)果的char[]char[] result = new char[length+1];for (int i = length-1; i >= 0; i--) {//實(shí)際上是intint temp = charMap.get(chars1[i]) + charMap.get(chars2[i]) + result[i+1];if (temp >= 16) {//本位溢出,進(jìn)位result[i+1] = intMap.get(temp-16);result[i]++;} else {result[i+1] = intMap.get(temp);}}//最終溢出if (result[0] == 0) {return new String(result).substring(1);}result[0] += 48;return new String(result);}因?yàn)槭怯蠥/B/C/D/E/F,但上面也說(shuō)了原因,這是不好操作的,就利用Map的映射來(lái)獲取對(duì)應(yīng)的“真值”。
原本想的是先判進(jìn)位,但是后來(lái)發(fā)現(xiàn)不行,下面打個(gè)比方:
如果先判高位相加時(shí)候溢出,是不能滿足所有可能的,很多測(cè)試數(shù)據(jù)用上去都會(huì)WA掉。
十進(jìn)制的599+499,明顯是會(huì)溢出進(jìn)位的,但5+4不會(huì)達(dá)到10,如果這就認(rèn)為不能滿足進(jìn)位,顯然就錯(cuò)了。
所以我會(huì)開(kāi)一個(gè)長(zhǎng)一位的數(shù)組,當(dāng)高位是0的時(shí)候(不進(jìn)位)就利用字符串的取得子串來(lái)消去第一位。
進(jìn)位一定要處理好啊!!!
下面是2~10進(jìn)制的加法:
/*** 2-10進(jìn)制的加法* @param num1 加數(shù)1* @param num2 加數(shù)2(位數(shù)與加數(shù)1相同)* @param format 兩個(gè)數(shù)所屬進(jìn)制* @return N進(jìn)制和(2 <= N <= 10)*/private static String normallyAdd(String num1, String num2, int format) {//獲取char[]char[] chars1 = num1.toCharArray();char[] chars2 = num2.toCharArray();//長(zhǎng)度int length = chars1.length;//結(jié)果的char[]char[] result = new char[length+1];for (int i = length-1; i >= 0; i--) {//實(shí)際上是charint temp = chars1[i] + chars2[i] + result[i+1];if (temp >= 96 + format) {//本位溢出,進(jìn)位result[i+1] = (char)(temp - format - 48);result[i]++;} else {result[i+1] = (char)(temp - 48);}}//最終溢出if (result[0] == 0) {return new String(result).substring(1);}result[0] += 48;return new String(result);}這里就可以不用Map啦,其實(shí)單純的操作char就可以啦!!
很多都是類似的,可以看看上面的。
評(píng)測(cè)數(shù)據(jù)集Share
我遇到了一些WA和RE問(wèn)題。
一共有4份測(cè)試數(shù)據(jù)集,我這里有第一個(gè)、第二個(gè)、第四個(gè)。
數(shù)據(jù)1
in
2
10011
out
STEP=4
數(shù)據(jù)2
in
16
AC27
out
STEP=6
數(shù)據(jù)4
in
2
101111
out
Impossible!
AC代碼(Java語(yǔ)言描述)
import java.util.HashMap; import java.util.Map; import java.util.Scanner;public class Main {private static Map<Character, Integer> charMap;private static Map<Integer, Character> intMap;static {charMap = new HashMap<>();charMap.put('0', 0);charMap.put('1', 1);charMap.put('2', 2);charMap.put('3', 3);charMap.put('4', 4);charMap.put('5', 5);charMap.put('6', 6);charMap.put('7', 7);charMap.put('8', 8);charMap.put('9', 9);charMap.put('A', 10);charMap.put('B', 11);charMap.put('C', 12);charMap.put('D', 13);charMap.put('E', 14);charMap.put('F', 15);intMap = new HashMap<>();intMap.put(0, '0');intMap.put(1, '1');intMap.put(2, '2');intMap.put(3, '3');intMap.put(4, '4');intMap.put(5, '5');intMap.put(6, '6');intMap.put(7, '7');intMap.put(8, '8');intMap.put(9, '9');intMap.put(10, 'A');intMap.put(11, 'B');intMap.put(12, 'C');intMap.put(13, 'D');intMap.put(14, 'E');intMap.put(15, 'F');}/*** 字符串反轉(zhuǎn)* @param string 待翻轉(zhuǎn)字符串* @return 翻轉(zhuǎn)后的字符串*/private static String reverse(String string) {return new StringBuilder(string).reverse().toString();}/*** 十六進(jìn)制加法* @param num1 加數(shù)1* @param num2 加數(shù)2(位數(shù)與加數(shù)1相同)* @return 十六進(jìn)制和*/private static String hexAdd(String num1, String num2) {//獲取char[]char[] chars1 = num1.toCharArray();char[] chars2 = num2.toCharArray();//長(zhǎng)度int length = chars1.length;//結(jié)果的char[]char[] result = new char[length+1];for (int i = length-1; i >= 0; i--) {//實(shí)際上是intint temp = charMap.get(chars1[i]) + charMap.get(chars2[i]) + result[i+1];if (temp >= 16) {//本位溢出,進(jìn)位result[i+1] = intMap.get(temp-16);result[i]++;} else {result[i+1] = intMap.get(temp);}}//最終溢出if (result[0] == 0) {return new String(result).substring(1);}result[0] += 48;return new String(result);}/*** 2-10進(jìn)制的加法* @param num1 加數(shù)1* @param num2 加數(shù)2(位數(shù)與加數(shù)1相同)* @param format 兩個(gè)數(shù)所屬進(jìn)制* @return N進(jìn)制和(2 <= N <= 10)*/private static String normallyAdd(String num1, String num2, int format) {//獲取char[]char[] chars1 = num1.toCharArray();char[] chars2 = num2.toCharArray();//長(zhǎng)度int length = chars1.length;//結(jié)果的char[]char[] result = new char[length+1];for (int i = length-1; i >= 0; i--) {//實(shí)際上是charint temp = chars1[i] + chars2[i] + result[i+1];if (temp >= 96 + format) {//本位溢出,進(jìn)位result[i+1] = (char)(temp - format - 48);result[i]++;} else {result[i+1] = (char)(temp - 48);}}//最終溢出if (result[0] == 0) {return new String(result).substring(1);}result[0] += 48;return new String(result);}/*** 判斷是否為回文數(shù)* @param num 待判數(shù)值* @return 是否為回文數(shù)*/private static boolean isPalindrome(String num) {if (num.equals(reverse(num))) {return true;} else {return false;}}public static void main(String[] args) {Scanner scanner = new Scanner(System.in);//進(jìn)制(2-10、16)int format = Integer.parseInt(scanner.nextLine());String num = scanner.nextLine();int counter = 0;if (format == 16) {while (!isPalindrome(num) && counter <= 30) {num = hexAdd(num, reverse(num));counter++;}} else {while (!isPalindrome(num) && counter <= 30) {num = normallyAdd(num, reverse(num), format);counter++;}}if (counter > 30) {System.out.println("Impossible!");} else {System.out.println("STEP=" + counter);}scanner.close();}}感悟
這個(gè)題的代碼基本寫了半天,充滿了各種失敗,是很大的挑戰(zhàn)。
但這次以后,我想我對(duì)利用串和字符處理進(jìn)制有了很好的認(rèn)識(shí),這部分內(nèi)容對(duì)我是重要的,以后希望能做得更好。
希望能對(duì)大家有所幫助!!
加油!!奧利給!!(晚安啦)
總結(jié)
以上是生活随笔為你收集整理的N进制正反累加判回文数(洛谷P1015题题解,Java语言描述)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Boost asio 官方教程简介
- 下一篇: Java每次输入一个字符+高精度取整计算