对于真正大于整数最大值的巨大数,求解递归关系的最佳方法应该是什么

时间:2014-11-03 09:37:35

标签: java arrays recurrence

我想找到递归方程的第N个数

T(n)=T(n-1)+3T(n-2)+3T(n-3)+(n-4),T(1)=T(4)=1,T(2)=T(3)=3

因此,如果您输入2,5,9作为输入,则输出应为T(2)=3,T(5)=20,T(9)=695

我所做的是创建一个大小等于所有输入值的最大值的数组,并在索引i处存储T(i)的解。然后查找数组中的特定索引。例如,T(3)的数组[3],T(5)的数组[5]等

代码工作正常,直到最大数量不大于系统可以容纳的最大整数值,即

Integer.MAXValue.

因为数组的索引只能是整数 如果数字是n=1855656959555656,那么找到解决方案的最佳方法应该是什么 T(1855656959555656)? 显然我无法创建一个size=1855656959555656..

数组

我甚至尝试过来自java.Math BigInteger ,但没有成功。 我必须找到一些其他方法。请提出一些想法..

由于

6 个答案:

答案 0 :(得分:4)

您不需要存储每个T(i),您只需要存储3个值T(i-1),T(i-2),T(i-3)。在循环i时,检查当前i是否应该是输出的一部分,如果是,请立即将其输出或将其保存到"输出" -array。

编辑:这部分效率很低。您需要每次迭代检查所需的输出。

        for (int k = 0; k < arr.length; ++k) {
            if (count == arr[k])
                T[k] = temp[i];
            else if (arr[k] == 1)
                T[k] = 1;
            else if (arr[k] == 2)
                T[k] = 3;
            else if (arr[k] == 3)
                T[k] = 3;
            else if (arr[k] == 4)
                T[k] = 1;
        }

所以你的代码及时运行(max * arr.length)你可以将它减少到(max)。使用带有key = neededPosition(= count)value = arr

中的位置的HashMap

按照以下方式启动地图:

 Map<Long, Integer> map = new HashMap<Long, Integer>();
 for (int i = 0; i < arr.length; i++) {
        map.put(arr[i], i);
    }

if (map.containsKey(count)) {
    T[map.get(count)] = temp[i]
}

在整个事情之后只检查1-4值!

答案 1 :(得分:1)

不可能。数组大小最大为Integer.MAX_VALUE(减去通常为5或8的内容,具体取决于JVM功能)。为什么?。数组的索引应该是整数限制

答案 2 :(得分:1)

无法完成。因此,您需要通过引入分片机制来解决问题。最简单的方法是只拥有固定长度的数组数组。

答案 3 :(得分:1)

编辑:你真的不需要这么多存储空间来解决你的问题(正如另一个答案所指出的那样;这个代码片段完全避免了数组以避免边界检查/间接):

public void t(long n) {
  if (n < 5) {
    return (n == 2 || n == 3) ? 3 : 1;
  }
  long i = 5;     // Initialize variables for n == 5;
  long tn_1 = 1;  // T(n-1) = T(4) = 1;
  long tn_2 = 3;  // T(n-2) = T(3) = 3;
  long tn_3 = 1;  // T(n-3) = T(2) = 1;
  long tn_4 = 3;  // T(n-4) = T(1) = 3;
  while (true) {
    long tn = tn_1 + 3*tn_2 + 3*tn_3 + tn_4;
    if (i++ == n) {
      return tn;
    }
    tn_4 = tn_3;
    tn_3 = tn_2;
    tn_2 = tn_1;
    tn_1 = tn;
  }
}

无论如何要回答标题中的问题

如果您的数组稀疏,请使用TreeMapHashMap的地图(LongBigInteger):

Map<Long,Long> t = new TreeMap<Long,Long>()

稀疏数组的内存消耗取决于实际存储的元素数量,因此您可能希望从地图中删除不再需要的值。

如果您的数组不稀疏,请使用2级数组(内存消耗仅取决于预先分配的大小):

public class LongArray {
  static final long BLOCK_SIZE = 0x40000000;
  long[][] storage;

  public LongArray(long size) {
    long blockCount = (size + BLOCK_SIZE - 1) / BLOCK_SIZE;
    storage = new long[][(int) blockCount];
    for (long i = 0; i < blockCount; i++) {
      if (i == blockCount - 1) {
        storage[i] = new long[(int) size - BLOCK_SIZE * (blockCount - 1)];
      } else {
        storage[i] = new long[(int) BLOCK_SIZE];
      }
    }
  }

  public long get(long index) {
    return storage[(int) (index / BLOCK_SIZE)][(int) (index % BLOCK_SIZE)];
  }

  public void put(long index, long value) {
    storage[(int) (index / BLOCK_SIZE)][(int) (index % BLOCK_SIZE)] = value;
  }
}

在这两种情况下,使用t.get(index)t.put(index, value)代替t[index]来访问您的数组(如果t是数组的名称)。

答案 4 :(得分:0)

使用递归调用:

int T(int n){
    if (n==1 || n==4){
       return 1;
    } else if (n==2 || n==3){
       return 3;
    } else {
       return T(n-1)+3*T(n-2)+3T*(n-3)+T(n-4);
    }
}

编辑:耗费时间。赢得了大量工作

答案 5 :(得分:0)

你可以做一件事。检查n的值是否在开头等于1855656959555656,或者是否为其倍数。假设,n的值是1855656959555656的两倍。然后,您可以创建两个数组并虚拟地将它们链接在一起。这应该解决您的问题,但它将涉及很多开销。