Java 算法简单但内存不足
问题 正有理数序列定义如下: 给出了一个用正有理数标记的无限全二叉树 定义如下:Java 算法简单但内存不足,java,algorithm,memory,Java,Algorithm,Memory,问题 正有理数序列定义如下: 给出了一个用正有理数标记的无限全二叉树 定义如下: 根的标签是1/1 标签p/q的左子项为p/(p+q) 标签p/q的右子项为(p+q)/q 树的顶部如下图所示: 通过执行级别顺序(宽度优先)来定义序列 树的遍历(由浅虚线指示)。以便: F(1)=1/1,F(2)=1/2,F(3)=2/1,F(4)=1/3,F(5)=3/2,F(6)=2/3 编写一个程序,找出n的值,其中F(n)是p/q 输入p和q 输入 输入的第一行包含一个整数p,(1≤P≤1000),其
- 根的标签是1/1
- 标签p/q的左子项为p/(p+q)
- 标签p/q的右子项为(p+q)/q
public ARationalSequenceTwo() {
Kattio io = new Kattio(System.in, System.out);
StringBuilder sb = new StringBuilder(10000);
int iter = io.getInt();
// create heap
int parent;
Node[] heap = new Node[Integer.MAX_VALUE];
int counter = 1;
heap[0] = new Node(1, 1);
while (counter < Integer.MAX_VALUE) {
parent = (counter - 1) / 2;
// left node
heap[counter++] = new Node(heap[parent].numerator, heap[parent].numerator + heap[parent].denominator);
// right node
heap[counter++] = new Node(heap[parent].numerator + heap[parent].denominator, heap[parent].denominator);
}
// find Node
int dataSet;
String word;
int numerator;
int denominator;
for (int i = 0; i < iter; i++) {
dataSet = io.getInt();
word = io.getWord();
numerator = Integer.parseInt(word.split("/")[0]);
denominator = Integer.parseInt(word.split("/")[1]);
for (int j = 0; j < Integer.MAX_VALUE; j++) {
Node node = heap[j];
if (node.numerator == numerator && node.denominator == denominator) {
sb.append(dataSet).append(" ").append(j).append("\n");
}
}
}
System.out.println(sb);
io.close();
}
public-ARationalSequenceTwo(){
Kattio io=新的Kattio(系统输入,系统输出);
StringBuilder sb=新StringBuilder(10000);
int iter=io.getInt();
//创建堆
int父代;
节点[]堆=新节点[整数.MAX_值];
int计数器=1;
堆[0]=新节点(1,1);
while(计数器<整数.最大值){
父项=(计数器-1)/2;
//左节点
堆[counter++]=新节点(堆[parent]。分子,堆[parent]。分子+堆[parent]。分母);
//右节点
堆[counter++]=新节点(堆[parent]。分子+堆[parent]。分母,堆[parent]。分母);
}
//查找节点
int数据集;
字符串字;
整数分子;
整数分母;
对于(int i=0;i <代码> > p>让我们考虑节点n=a/b。如果n是其父对象的左子对象,则n=p/(p+q),其中父对象为p/q。即
p = a,
b = p + q
p = a,
q = b - a
如果n是其父级的右子级,则n=(p+q)/q:
那么,举个3/5的例子,它是左撇子还是右撇子?如果它是一个左撇子,那么它的父母将是3/(5-3)=3/2。对于正确的孩子,我们会有(3-5)/5=-2/5。因为这不是正数,显然n是一个左撇子
因此,概括起来:
给定有理数n,我们可以找到根的路径,如下所示:
ArrayList lefts=新的ArrayList()
while(nNum!=nDen){
如果(nNum
既然数组中有了路径,那么如何在最终结果中转换它呢?让我们观察一下
- 如果给定的值是1/1,那么数组是空的,我们应该返回1
- 每次我们从n级转到n+1级时,我们在结果中加上2^n。例如,从级别0到级别1,我们添加1(根)。从级别1到级别2,我们添加级别1的所有两个节点,即2,以此类推
剩下的是最后一块,它将节点添加到我们拥有的最后一个节点的左侧,对应于输入有理数的节点,加上一个。左边有多少个节点?如果尝试用0标记每个向左的弧,用1标记每个向右的弧,您会注意到路径以二进制形式拼写最后一级的节点数。例如,3/5是3/2的左子级。数组将填充false、true、false。二进制,010。最终结果是2^0+2^1+2^2+010+1=1+2+4+2+1=10
最后,请注意总和(2^i)是2^(i+1)-1。因此,我们最终可以为第二部分编写代码:
int s = (1 << lefts.size()) - 1) // 2^(i+1) - 1
int k = 0
for (int i = lefts.size() - 1; i >= 0; i---) {
if (lefts.get(i)) {
k += 1 << i;
}
}
return s + k + 1;
ints=(1=0;i--){
如果(lefts.get(i)){
k+=1 让我们考虑节点n=a/b。如果n是它的父的左子,则n=p/(p+q),其中父是p/q。
p = a,
b = p + q
p = a,
q = b - a
如果n是其父级的右子级,则n=(p+q)/q:
举个例子,3/5,它是左孩子还是右孩子?如果它是左孩子,那么它的父母将是3/(5-3)=3/2。对于右孩子,我们将有(3-5)/5=-2/5。因为这不是正的,显然n是左孩子
因此,概括起来:
给定有理数n,我们可以找到根的路径,如下所示:
ArrayList lefts=新的ArrayList()
while(nNum!=nDen){
如果(nNum
既然数组中有了路径,我们如何在最终结果中转换它呢?让我们观察一下
- 如果给定的值是1/1,那么数组是空的,我们应该返回1
- 每次我们从n级转到n+1级,我们都会在结果中加上2^n
int s = (1 << lefts.size()) - 1) // 2^(i+1) - 1
int k = 0
for (int i = lefts.size() - 1; i >= 0; i---) {
if (lefts.get(i)) {
k += 1 << i;
}
}
return s + k + 1;
import java.util.ArrayList;
public class Z {
public static int func(int num, int den) {
ArrayList<Boolean> lefts = new ArrayList<>();
while (num != den) {
if (num < den) {
//it's a left child
den = den - num;
lefts.add(true);
} else {
num = num - den;
lefts.add(false);
}
}
int s = (1 << lefts.size()) - 1; // 2^(i+1) - 1
int k = 0;
for (int i = lefts.size() - 1; i >= 0; i--) {
if (!lefts.get(i)) {
k += 1 << i;
}
}
return s + k + 1;
}
public static void main(String[] args) {
System.out.println(func(Integer.parseInt(args[0]),
Integer.parseInt(args[1])));
}
}
T(p, q) =
1 if p == q == 1
2 * T(p, q-p) if p < q
2 * T(p-q, q) + 1 if p > q