leetcode(166) Fraction to Recurring Decimal

原题链接:https://leetcode.com/problems/fraction-to-recurring-decimal/

这道题就是做除法,然后如果有无限循环的部分用括号表示

比如1/3=0.3333...用0.(3)来表示,1234/9999=0.123412341234....用0.(1234)来表示

循环判断用一个map来查看前面的一个数(或一串数)是否与后面的一个数(或一串数)做除法后的余数是否相同

具体思路如下图(这张图是从某篇其它博客上发现的,后来找不到原博了,如果有哪位读者发现,请告诉我),就是小学生的除法问题:

除法

首先先说一种错误思路,这种只考虑了1/3,1/6这种答案中只有一个数字循环的条件。实际上一串循环的数也是有的比如上面的例子1234/9999

错误解法(逻辑有问题且超时):

/**
	 * Time Limit Exceeded 无法处理1234/9999这种
	 * 
	 * @param numerator
	 * @param denominator
	 * @return
	 */
	public static String fractionToDecimal(int numerator, int denominator) {
		if (denominator == 0) {
			return null;
		}
		if (numerator == 0) {
			return 0 + "";
		}
		Map<Integer, Integer> map = new HashMap<Integer, Integer>();
		String result = "";
		if (numerator < 0 ^ denominator < 0)
			result += '-';
		numerator = Math.abs(numerator);
		denominator = Math.abs(denominator);
		int temp = 0;
		if ((temp = numerator / denominator) != 0) {
			result += temp + "";
			if ((temp = numerator % denominator) == 0) {
				return result;
			} else {
				result += ".";
			}
		} else {
			temp = numerator % denominator;
			result += "0.";
		}
		while ((temp * 10 % denominator) != 0) {
			int mod = temp * 10 % denominator;
			int divide = temp * 10 / denominator;
			if (map.containsKey(mod)) {
				result = result.substring(0, result.length() - 1);
				result += "(" + divide + ")";
				return result;
			}
			result += divide + "";
			map.clear();
			map.put(mod, mod);
			temp = mod;
		}
		result += (temp * 10 / denominator) + "";
		return result;
	}
见while循环里包含map的if中的处理。只是与上一个数进行比较,下面有一个map.clear然后再put,这样造成了只存取一位数,显然错误。

正确的解法:

public static String fractionToDecimal(int numerator, int denominator) {
		long n = numerator, d = denominator;
		if (n == 0)
			return "0";

		StringBuffer a = new StringBuffer();
		if ((n < 0) ^ (d < 0))
			a.append("-");

		n = Math.abs(n);
		d = Math.abs(d);

		long in = n / d;
		a.append(String.valueOf(in)); // StringBuffer里面没有String的 a = a +

		if (n % d == 0) {
			return a.toString();
		} else {
			a.append(".");
		}
		// 以上是小数点以前的

		HashMap<Long, Integer> map = new HashMap<Long, Integer>();
		// 用hashmap查找循环的地方比较方便
		// System.out.println(map.get(0)); //打印可看出 integer位置上未初始化时存的是null
		long i;
		for (i = n % d; i != 0; i = i % d) { // 注意step
			if (map.get(i) != null) {
				break;
			}
			map.put(i, a.length()); // 将i的值当做key a的位置当做value
			i *= 10;
			a.append(i / d);
		}
		if (i == 0)
			return a.toString();
		a.insert(map.get(i), "("); // 直接在循环的地方加入(
		a.append(")"); // 出现循环就立即跳出了循环,也就是说从i的位置到最后,都是循环体,所以只需在最后面加上)
		return a.toString();
	}
注意循环条件,for(i=n%d;i!=0;i=i%d),i=n%d代表余数(初始值),每次走i%d步,i在循环里有一步是i*10,当余数相同的情况下,说明后面该循环了。然后跳出循环,此时map中记录的位置即是要放左括号"("的位置,结尾是放右括号")"的位置。

以上就是此题的题解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值