写一个^ 3 + b ^ 3 = c ^ 3 + d ^ 3的所有解,其中a,b,c,d谎言 在[0,10 ^ 5]之间。
这是一个面试问题,我完全无能为力。
我认为优先队列至少要迭代a
和b
值。一些提示会很棒,会尝试从那里开始。
答案 0 :(得分:21)
使用哈希映射存储(cube,(a,b))
,您可以迭代所有可能的整数对,并在找到所需的多维数据集总和已经在地图中时输出解决方案。
伪代码:
map <- empty hash_map<int,list<pair<int,int>>>
for each a in range(0,10^5):
for each b in range(a,10^5): //making sure each pair repeats only once
cube <- a^3 + b^3
if map.containsKey(cube):
for each element e in map.get(cube):
output e.first(), e.last(), a, b //one solution
else:
map.put(cube,new list<pair<int,int>>)
//for both cases, add the just found pair to the relevant list
map.get(cube).add(cube,new pair(a,b))
此解决方案平均为O(n ^ 2)空间(1)和O(n ^ 2 + OUTPUT)时间,其中OUTPUT是输出的大小。
修改强>
所需空间实际为O(n^2 logn)
,其中n
是范围(10 ^ 5),因为要表示10^5
整数,您需要ceil(log_2(10^15)) = 50
位。所以,你实际上需要500,000,000,000位(+地图和列表的开销),大约是58.2 GB(+开销)。
因为对于大多数机器来说有点太多了 - 你可能想要考虑将数据存储在磁盘上,或者如果你有64位机器 - 只需存入“内存”并让操作系统和virtual memory系统尽可能做到这一点。
(1)正如编辑所阐明的那样,它实际上是O(n^2log(n))
空间,但是如果我们将每个整数存储作为O(1)
(通常就是这种情况),我们会得到O(n^2)
空格。显然,相同的原则适用于时间复杂度。
答案 1 :(得分:4)
使用优先级队列几乎可以肯定是最简单的解决方案,也是最实用的解决方案,因为它是O(n)存储(如果需要bignums,则具有对数因子)。任何涉及计算所有可能总和并将它们放入地图的解决方案都需要O(n ^ 2)存储,这很快就会变得不切实际。
使用优先级队列的原始非优化实现是O(n ^ 2 log(n))时间。即便如此,对于n = 10000,花费不到5秒,对于n = 100000,花费大约750秒,使用几兆字节的存储。它当然可以改进。
根据您的评论,基本思想是使用(1,N)范围内的a对(a,a + 1)初始化优先级队列,然后重复递增最小值的第二个值(通过多维数据集之和)元组直到它达到N.如果队列中最小的两个元素在任何时候都相等,那么你有一个解决方案。 (我可以粘贴代码,但你只是要求提示。)
答案 2 :(得分:2)
快速而简单的解决方案如下:您计算^ 3 + b ^ 3可以拥有的所有值,并使用它存储a和b的所有可能值。这是通过循环a和b,将结果(a ^ 3 + b ^ 3)存储在二叉树中并具有与每个结果相关联的值列表(a和b)来完成的。
在此步骤之后,您需要遍历列表并为每个值选择a,b,c,d的每个可能的分配。
我认为这个解决方案需要O(n ^ 2 log n)时间和O(n ^ 2)空间,但我可能会遗漏一些东西。
答案 3 :(得分:2)
int Search(){
int MAX = 10000000;
for(int a = 0; a < MAX; a++){
int a3 = a * a * a;
if(a3 > MAX) break;
for(int b = a; b < MAX; b ++){
int b3 = b * b * b;
if(a3 + b3 > MAX)break;
for(int c = 0; c < a; c++){
int c3 = c*c*c;
int m = a3 - c3;
int d = b+1;
while(true){
int d3 = d * d * d;
if(d3-b3 <= m){
if((d3 - b3) == m){
count++;
PUSH_Modified(a3, b3, c3, b3, a, b, c, d);
}
d++;
continue;
}
else
break;
}
}
}
}
return 0;
}
答案 4 :(得分:2)
使用Hashmap(O(n ^ 2)解决方案):
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import static java.lang.Math.pow;
/**
* Created by Anup on 10-10-2016.
*/
class Pair {
int a;
int b;
Pair(int x, int y) {
a = x;
b = y;
}
}
public class FindCubePair {
public static void main(String[] args) {
HashMap<Long, ArrayList<Pair>> hashMap = new HashMap<>();
int n = 100000;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
long sum = (long) (pow(i, 3) + pow(j, 3));
if(hashMap.containsKey(sum)) {
List<Pair> list = hashMap.get(sum);
for(Pair p : list) {
System.out.println(i + " " + j + " " + p.a + " " + p.b);
}
} else {
ArrayList<Pair> list = new ArrayList<>();
hashMap.put(sum, list);
}
hashMap.get(sum).add(new Pair(i, j));
}
}
}
}
不幸的是,由于资源限制,打印的整数值在我的计算机上甚至达不到1000.
答案 5 :(得分:1)
让我们假设一个解决方案:
a=A, b=B, c=C, and d=D.
鉴于任何解决方案,我们可以生成另外3个解决方案
abcd
ABCD
ABDC
BACD
BADC
实际上,如果A=B
或C=D
,那么我们可能只有1或2个进一步的解决方案。
我们可以通过订购A <= B
和C <= D
来选择我们首先寻找的解决方案。这将减少搜索空间。我们可以从找到的解决方案中生成错过的解决方案。
始终至少有一个解决方案,其中A=C
和B=D
。我们要找的是A>C
和B<D
。这来自排序:C
不能大于A
,因为我们选择仅查看D>C
的解决方案,因此多维数据集总和会太大。< / p>
我们可以计算A^3 + B^3
,将其作为密钥放在map
中,并将vector
对A,B
作为值。
将会有(n^2)/2
个值。
如果vector
中已有值,则所有值都会降低A
,并且它们是我们正在寻找的解决方案。我们可以立即输出它们以及它们的排列。
我不确定复杂性。
答案 6 :(得分:1)
一种解决方案 - 使用在排序数组中查找2和的概念。这是O(n3)
public static void pairSum() {
int SZ = 100;
long[] powArray = new long[SZ];
for(int i = 0; i< SZ; i++){
int v = i+1;
powArray[i] = v*v*v;
}
int countPairs = 0;
int N1 = 0, N2 = SZ-1, N3, N4;
while(N2 > 0) {
N1=0;
while(N2-N1 > 2) {
long ts = powArray[N1] + powArray[N2];
N3 = N1+1; N4 = N2-1;
while(N4 > N3) {
if(powArray[N4]+powArray[N3] < ts) {
N3++;
}else if(powArray[N4]+powArray[N3] > ts) {
N4--;
}else{
//System.out.println((N1+1)+" "+(N2+1)+" "+(N3+1)+" "+(N4+1)+" CUBE "+ts);
countPairs++;
break;
}
}
N1++;
}
N2--;
}
System.out.println("quadruplet pair count:"+countPairs);
}
答案 7 :(得分:1)
逻辑:
a ^ 3 + b ^ 3 = c ^ 3 + d ^ 3
然后,a ^ 3 + b ^ 3-c * 3-d ^ 3 = 0
尝试通过将a,b,c和d的所有值组合在[0,10 ^ 5]的范围内来解决此等式。
如果方程式被求解,则打印a,b,c和d的值
public static void main(String[] args) {
//find all solutions of a^3 + b^3 = c^3 + d^3
double power = 3;
long counter = 0; // to count the number of solution sets obtained
int limit = 100000; // range from 0 to limit
//looping through every combination of a,b,c and d
for(int a = 0;a<=limit;a++)
{
for(int b = 0;b<=limit;b++)
{
for(int c = 0;c<=limit;c++)
{
for(int d = 0;d<=limit;d++)
{
// logic used : a^3 + b^3 = c^3 + d^3 can be written as a^3 + b^3 - c^3 - d^3 = 0
long result = (long)(Math.pow(a,power ) + Math.pow(b,power ) - Math.pow(c,power ) - Math.pow(d,power ));
if(result == 0 )
{
counter++; // to count the number of solutions
//printing the solution
System.out.println( "a = "+ a + " b = " + b + " c = " + c + " d = " + d);
}
}
}
}
}
//just to understand the change in number of solutions as limit and power changes
System.out.println("Number of Solutions =" + counter);
}
答案 8 :(得分:1)
从蛮力方法开始,很明显它将在O(n ^ 4)时间内执行。 如果空间不是约束,我们可以选择列表和地图的组合。 代码是不言自明的,我们使用嵌套列表来跟踪特定总和(地图中的键)的所有条目。 因此,时间复杂度从O(n ^ 4)减少到O(n ^ 2)
public void printAllCubes() {
int n = 50;
Map<Integer, ArrayList<ArrayList>> resMap = new HashMap<Integer, ArrayList<ArrayList>>();
ArrayList pairs = new ArrayList<Integer>();
ArrayList allPairsList = new ArrayList<ArrayList>();
for (int c = 1; c < n; c++) {
for (int d = 1; d < n; d++) {
int res = (int) (Math.pow(c, 3) + Math.pow(d, 3));
pairs.add(c);
pairs.add(d);
if (resMap.get(res) == null) {
allPairsList = new ArrayList<ArrayList>();
} else {
allPairsList = resMap.get(res);
}
allPairsList.add(pairs);
resMap.put(res, allPairsList);
pairs = new ArrayList<Integer>();
}
}
for (int a = 1; a < n; a++) {
for (int b = 1; b < n; b++) {
int result = (int) (Math.pow(a, 3) + Math.pow(b, 3));
ArrayList<ArrayList> pairList = resMap.get(result);
for (List p : pairList) {
System.out.print(a + " " + b + " ");
for (Object num : p)
System.out.print(num + " ");
System.out.println();
}
}
}
}