我正在尝试用Java来解决我自己的启发。我被告知是设计拼图的人的解决方案,但我自己无法找到它。
这就是谜题:
在Java中实现以下方法
/** * Divides a natural number by two. * * @param n * The number to be divided * @updates n * @ensures n = floor(n/2) */ private static void split(NaturalNumber n) {...}
NaturalNumber类只是一个存储自然数的类 使用字符串。 (也就是说,它可以存储比...更大的数字
Integer.MAX_VALUE
。 )该类提供了这些instance methods和inherited methods以及
NaturalNumber.isZero()
方法, 如果实例的内部字符串值为"0"
,则返回true,false 否则。值得注意的是
NaturalNumber.divideBy10()
方法 基本上从数字中弹出最右边的数字,将其作为一个返回int
并更新实例的内部值。不要在主类上使用静态属性来存储值。 同样,不要编写静态辅助方法。
不要将
n
转换为其他数据类型并对其进行操作。不要使用外部库。此外,
split()
必须使用递归实现。
我有以下 near 解决方案:
private static void split(NaturalNumber n) {
// Initialize local variables.
String stringBuffer = "";
int numerator = 0;
int quotient = 0;
int remainder = 0;
int thisDigit = n.divideBy10();
if (n.isZero()) {
quotient = thisDigit / 2;
remainder = thisDigit % 2;
n.transferFrom(new NaturalNumber2(quotient * 10 + remainder));
} else {
split(n);
numerator = n.divideBy10() * 10 + thisDigit;
quotient = numerator / 2;
remainder = numerator % 2;
if (!n.isZero()) {
stringBuffer += n.toString();
}
stringBuffer += Integer.toString(quotient * 10 + remainder);
n.transferFrom(new NaturalNumber2(stringBuffer));
}
}
以上只是进行长时间划分。但是调用栈中的最后一帧不必要地将其操作的剩余部分附加到解决方案的末尾。
我已经看到类似问题的解决方案,从n
递归地减去两个,计算n
必须减去两次才能变为零。但是那些解决方案依赖于具有返回值的方法;这个难题要求没有回报价值。
我还可以看到如何使用对split()
的一个函数调用和内部循环来解决这个难题。但我被告知解决方案不能依赖循环来操作n
。
有没有人对解决方案有任何见解?
答案 0 :(得分:1)
假设n
的数字为a...yz
。如果y
为偶数,则n / 2
的数字是a...y / 2
和z / 2
的串联。如果y
为奇数,请Y = y - 1
。然后,n / 2
的数字是a...Y / 2
和1z / 2
的串联。
我们可以按如下方式实现:
private static void split(NaturalNumber n) {
int z = n.divideBy10();
int y = n.divideBy10();
if (n.isZero()) {
// Base case.
int result = (y * 10 + z) / 2;
n.multiplyBy10(result / 10);
n.multiplyBy10(result % 10);
} else if (y % 2 == 0) {
n.multiplyBy10(y);
split(n);
n.multiplyBy10(z / 2);
} else {
n.multiplyBy10(y - 1);
split(n);
n.multiplyBy10((10 + z) / 2);
}
}
顺便提一下,这些方法名称很糟糕,使NaturalNumber
可变是一种奇怪的设计选择。