1. 程式人生 > >PAT乙級——1079(大整數相加 迴文數判斷 邊界點)Java實現

PAT乙級——1079(大整數相加 迴文數判斷 邊界點)Java實現

題目:延遲的迴文數 (20 分)

給定一個 k+1 位的正整數 N,寫成 a​k⋯a1​​ a​0​​ 的形式,其中對所有 i 有 0 ≤ a​i​​ < 10 且 a​k > 0。N 被稱為一個迴文數,當且僅當對所有 i 有 a​i​​ = a​k − ai​​ 。零也被定義為一個迴文數。

非迴文數也可以通過一系列操作變出迴文數。首先將該數字逆轉,再將逆轉數與該數相加,如果和還不是一個迴文數,就重複這個逆轉再相加的操作,直到一個迴文數出現。如果一個非迴文數可以變出迴文數,就稱這個數為延遲的迴文數。(定義翻譯自 https://en.wikipedia.org/wiki/Palindromic_number

給定任意一個正整數,本題要求你找到其變出的那個迴文數。

輸入格式:
輸入在一行中給出一個不超過1000位的正整數。

輸出格式:
對給定的整數,一行一行輸出其變出迴文數的過程。每行格式如下

A + B = C

其中 A 是原始的數字,BA 的逆轉數,C是它們的和。A 從輸入的整數開始。重複操作直到 C 在 10 步以內變成迴文數,這時在一行中輸出 C is a palindromic number.;或者如果 10 步都沒能得到迴文數,最後就在一行中輸出 Not found in 10 iterations.

輸入樣例 197152

輸出樣例 197152
+ 25179 = 122331 122331 + 133221 = 255552 255552 is a palindromic number.
輸入樣例 2196

輸出樣例 2196 + 691 = 887
887 + 788 = 1675
1675 + 5761 = 7436
7436 + 6347 = 13783
13783 + 38731 = 52514
52514 + 41525 = 94039
94039 + 93049 = 187088
187088 + 880781 = 1067869
1067869 + 9687601 = 10755470
10755470 + 07455701 = 18211171
Not found in 10 iterations.

題目分析及實現

這個題是有點麻煩的,尤其是很多容易犯錯的地方
需要注意的是:

  • 超長整數相加,數字很大,以字串儲存並計算,細節可參考這篇部落格
  • 最多判斷十次,失敗則輸出Not found in 10 iterations.
  • 中間步驟輸出相加過程
  • 這裡因為是兩個同長度的數相加,且高位對低位都是相同的,所以在計算的過程中不需要逆置來簡化操作

這個題我做了好久好久,腦子總是有些混亂,小細節一定要考慮好,比如什麼時候判出,什麼時候判斷就是迴文數。

現在發現做題目,敲程式碼的時候一定要清楚地知道邊界是什麼,分界點找到了,就會簡單很多,有時候卡題,大多數的測試點過不去都是由於分界點找的 不對 或者 不全 或者 實現方法不對

繼續努力。

//AC
import java.util.Scanner;

public class Main {
	private static boolean isP = true;// 迴文數標記

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		StringBuilder input = new StringBuilder(in.next());
		in.close();
		boolean find = false;// 判斷十次是否找到
		Loop: for (int time = 0; time < 10; time++) {
			isP(input);
			if (isP) {
				System.out.println(input + " is a palindromic number.");
				find = true;
				break Loop;
			} else
				input = add(input);
			System.out.println(input);
		}
		if (!find)
			System.out.println("Not found in 10 iterations.");
	}

	// 大整數相加
	public static StringBuilder add(StringBuilder input) {
		// 需要建立新的物件等於input,否則只是新建一個引用,原物件也變了
		StringBuilder B = new StringBuilder(input);
		B = B.reverse();
		System.out.print(input + " + " + B + " = ");
		int[] num = new int[B.length() + 1];
		// 1.把兩個大整數用陣列儲存,已經逆置
		char[] charsA = B.toString().toCharArray();
		char[] charsB = input.toString().toCharArray();

		int[] result = new int[charsA.length + 1];
		// 2.遍歷陣列,按位相加
		for (int i = 0; i < result.length; i++) {
			int temp = result[i];
			if (i < charsA.length) {
				temp += charsA[i] - '0' + charsB[i] - '0';
			}

			// 判斷是否進位
			if (temp >= 10) {
				temp = temp - 10;
				result[i + 1] = 1;
			}
			result[i] = temp;
		}

		// 3.把result陣列再次逆序並轉成String
		StringBuilder sb = new StringBuilder();
		// 判斷最後一位是否發生了進位
		int head = result.length - 1;
		if (result[result.length - 1] == 0) {
			head = result.length - 2;
		}
		for (int i = head; i >= 0; i--) {
			sb.append(result[i]);
		}
		return input = new StringBuilder(sb.toString());
	}

	// 判斷是否為迴文數
	public static void isP(StringBuilder input) {
		int time = 0;
		char a = 'c';
		char b = 'd';
		for (int i = 0; i < input.length() / 2; i++) {
			time++;
			a = input.charAt(i);
			b = input.charAt(input.length() - 1 - i);
			if (a != b) {
				isP = false;
				break;
			}
		}
		// 當a==b且遍歷完的時候,可作為更改點
		if (time == input.length() / 2 && a == b)
			isP = true;
	}
}

在這裡插入圖片描述