【字符串】B051_NK_格式化 a/b 的小數部分(不斷取餘數繼續除 + 找規律)

一、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();
    }
}

複雜度分析

  • 時間複雜度:O(...)O(...)
  • 空間複雜度:O(...)O(...)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章