【字符串】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 ( . . . ) O(...) O(...)

你可能感兴趣的:(#,字符串)