我想找到递归方程的第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 ,但没有成功。
我必须找到一些其他方法。请提出一些想法..
由于
答案 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;
}
}
无论如何要回答标题中的问题:
如果您的数组稀疏,请使用TreeMap
或HashMap
的地图(Long
或BigInteger
):
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的两倍。然后,您可以创建两个数组并虚拟地将它们链接在一起。这应该解决您的问题,但它将涉及很多开销。