我编写了一个以
形式解决丢番图方程的程序5 + B 5 + C 5 + D 5 + E 5 = 0;
它应该在N 3 长(N)时间运行,但输入大小为100通常需要大约10分钟。任何人都可以告诉我什么是错的?
public class EquationSolver {
//Solves Equations of type: A^5 + B^5 + C^5 + D^5 + E^5 = F^5
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Enter a max value: ");
int N = input.nextInt();
long START_TIME = System.nanoTime();
SLinkedList test = new SLinkedList();
SLinkedList test2 = new SLinkedList();
test = setupLeftList(N);
test2 = setupRightList(N);
System.out.println("Note: This program takes about 7 minutes to complete for input of 100");
test = mergeSort(test);
test2 = mergeSort(test2);
long END_TIME2 = System.nanoTime() - START_TIME;
System.out.println("Total Time:" + END_TIME2/1000000000.0);
checkEquality(test, test2);
long END_TIME3 = System.nanoTime() - START_TIME;
System.out.println("Total Time:" + END_TIME3/1000000000.0);
}
public static SLinkedList setupLeftList(long boundary)
{
//Creates and returns an linkedList of all possible A,B,C values and their sums
SLinkedList leftSums = new SLinkedList();
for(long c = 0; c < boundary; c++)
{
for(long b = 0; b < c; b++)
{
for(long a = 0; a < b; a++)
{
long sum = (long)(Math.pow(a+1,5)) + (long)(Math.pow(b+1, 5)) + (int)(Math.pow(c+1, 5));
Node current = new Node (sum, a+1, b+1, c+1, null);
//System.out.println(sum);
leftSums.addLast(current);
}
}
}
return leftSums;
}
public static SLinkedList setupRightList(long boundary)
{
//Creates and returns an linkedList of all possible D,E,F values and their sums
SLinkedList rightSums = new SLinkedList();
for(int f = 0; f < boundary; f++)
{
for(int e = 0; e < f; e++)
{
for(int d = 0; d < e; d++)
{
long sum = (long)(Math.pow(f+1, 5)) - ((long)(Math.pow(d+1, 5)) + (long)(Math.pow(e+1,5)));
Node current = new Node (sum, d+1, e+1, f+1, null);
//System.out.println(current.getSum());
rightSums.addLast(current);
}
}
}
return rightSums;
}
public static SLinkedList mergeSort(SLinkedList sums)
// Sorts each list by the value of the sum
{
if (sums.length() > 1 )
{
SLinkedList[] splitList = split(sums);
SLinkedList s1 = mergeSort(splitList[0]);
SLinkedList s2 = mergeSort(splitList[1]);
sums = merge(s1, s2);
}
return sums;
}
public static SLinkedList[] split(SLinkedList sums)
{
// Splits a linked list into two (somewhat) equal halves
long midpoint = sums.length()/2;
Node midPoint = sums.elementAt(midpoint);
SLinkedList s1 = new SLinkedList(sums.head, midPoint, midpoint);
SLinkedList s2 = new SLinkedList(midPoint, sums.tail, midpoint);
SLinkedList[] both = new SLinkedList[]{s1, s2};
return both;
}
public static SLinkedList merge(SLinkedList s1, SLinkedList s2)
{
// Merges two sorted lists of elements
SLinkedList sMerged = new SLinkedList();
while(!s1.isEmpty() && !s2.isEmpty())
{
if (s1.getFirst().getSum() < s2.getFirst().getSum())
{
sMerged.addLast(s1.removeFirst());
}
else
{
sMerged.addLast(s2.removeFirst());
}
}
while(!s1.isEmpty())
{
sMerged.addLast(s1.removeFirst());
}
while(!s2.isEmpty())
{
sMerged.addLast(s2.removeFirst());
}
return sMerged;
}
public static void checkEquality(SLinkedList left, SLinkedList right)
{
// Checks two linked lists for nodes that contain the same Sum value
boolean ans = false;
while (left.isEmpty() == false && right.isEmpty() == false)
{
long currentLeft = left.getFirst().getSum();
long currentRight = right.getFirst().getSum();
if (currentLeft > currentRight)
{
right.removeFirst();
}
else if(currentLeft < currentRight)
{
left.removeFirst();
}
else
{
if (left.getFirst().getC() <= right.getFirst().getA())
{
System.out.println("Answer Found: " + "A: " + left.getFirst().getA() + " B: " + left.getFirst().getB() + " C: "
+ left.getFirst().getC() + " D: " + right.getFirst().getA() + " E: " + right.getFirst().getB() + " F: " + right.getFirst().getC());
ans = true;
}
Node temp = left.getFirst().getNext();
while (temp.getSum() == currentRight)
{
if (temp.getC() <= right.getFirst().getA())
{
System.out.println("Answer Found: " + "A: " + left.getFirst().getA() + " B: " + left.getFirst().getB() + " C: "
+ left.getFirst().getC() + " D: " + right.getFirst().getA() + " E: " + right.getFirst().getB() + " F: " + right.getFirst().getC());
ans = true;
}
temp = temp.getNext();
}
right.removeFirst();
left.removeFirst();
}
}
if (ans == false)
{
System.out.println("No answer found.");
}
}
}
答案 0 :(得分:2)
明确的答案是:使用分析器查看导致瓶颈的原因......
但是我看到你有Math.pow()个电话,都有长音,还有5号电源。
你可以更快地完成它,甚至可以检测到溢出:
public static long pow5(long base) {
if(base <=6208 && base >=-6208) {
return base*base*base*base*base;
} else {
throw new IllegalArgumentException("Overflow!");
}
}
(幻数免责声明: 6208 5 是〜2 63 ,是一个数字大于那个,5号权力不会适合64位...)
Math.pow使用双打,这本身意味着很多转换......
另外, @Floris 指出它甚至不值得一遍又一遍地计算 - 它可以被放入一个很好的数组中,只是索引
public static long[] pow5 = getPow5(100);
public static long[] getPow5(long numElements) {
long[] toReturn = new long[numElements];
for(long i=0;long<numElements;long++) {
toReturn[i] = i*i*i*i*i;
}
return toReturn;
}
如果需要,可以使用Math.pow(x, 5)
pow5[x]