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
树的顶部如下图所示:

通过执行级别顺序(宽度优先)来定义序列 树的遍历(由浅虚线指示)。以便:

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),其中 是后面的数据集数。每个数据集都应该是 完全独立地处理。每个数据集由一个 单行输入。它包含数据集编号K,单个 空格,分子p,正斜杠(/)和分母q, 所需分数的

输出

对于每个数据集,都有一行输出。它包含 数据集编号K,后跟一个空格 通过n的值,其中F(n)是p/q。输入将被选择为n 将适合32位整数

我的方法

我创建了堆并计划迭代它,直到找到有问题的元素,但是我的内存不足,所以我很确定我应该在根本不创建堆的情况下完成它

代码

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