一、Problem
求a/b的小數表現形式。如果a可以整除b則不需要小數點。如果是有限小數,則可以直接輸出。如果是無限循環小數,則需要把小數循環的部分用"()"括起來。
輸入描述:
兩個整數a和b,其中
0 <= a <= 1000 000
1 <= b <= 10 000
輸出描述:
一個字符串,該分數的小數表現形式
輸入
1 3
輸出
0.(3)
說明
1/3 = 0.333333...
輸入
1 6
輸出
0.1(6)
說明
1/6 = 0.16666666....
輸入
1 7
輸出
0.(142857)
說明
1 / 7 = 0.1428571428...
二、Solution
方法一:不斷除並取餘數
關鍵點:得到小數部分的循環節,怎麼才能知道哪一部分是循環節呢,這肯定需要記錄,而且沒有捷徑,只能手動算一遍,例如:1/7:
被除數 商 餘數
7 0 1
10 1 4
40 5 5
50 7 1
10 1 3
30 4 2
20 2 6
60 8 4
40 5 5
被除數 40 再次出現,那麼用 40 作爲除數再除一遍得到的上還是那一列,所以商的變化就是循環節即:5、7、1、4、2、8、5;我們還需要記錄循環節的開始位置,所以我們需要用一個映射來記錄每個除數在 sb 中的位置,以便實現插入左括號 '('
上面是討論了 a/b 有循環節的情況,如果 a/b 的小數部分很長,但最後可以終止,那麼此時餘數 a 就是 0 了,但只要餘數不爲 0 就一直除下去。
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
static class Solution {
void init() {
Scanner sc = new Scanner(new BufferedInputStream(System.in));
int a = sc.nextInt(), b = sc.nextInt();
StringBuilder sb = new StringBuilder();
sb.append(a/b);
int r = a % b;
if (r != 0) {
sb.append('.');
Map<Integer, Integer> mp = new HashMap<>();
while (r != 0) {
r *= 10;
if (mp.containsKey(r)) {
sb.insert(mp.get(r), "(");
sb.append(')');
break;
}
mp.put(r, sb.length());
sb.append(r/b);
r %= b;
}
}
System.out.println(sb);
}
}
public static void main(String[] args) throws IOException {
Solution s = new Solution();
s.init();
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,