Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/375.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java双方块(2011年Facebook黑客杯)_Java_Algorithm - Fatal编程技术网

Java双方块(2011年Facebook黑客杯)

Java双方块(2011年Facebook黑客杯),java,algorithm,Java,Algorithm,因此它工作正常,需要做的两个主要更改是只检查x的平方根(还需要将我的检查用例从检查余数转换为检查求幂)。另一个变化是,使用双精度显然是鲁莽的,因为数字将远远超过最大双精度。 这是来自CodeEval的挑战,我想这是Facebook首先提出的。这是我的大脑立即吐出来的。它通过了所有手动测试用例(例如10->1、25->2、3->0)。我没有看到任何其他的解决方案,因为我想先看看我是如何用自己的想法解决的。如果我太离谱了,这永远不会成功,我会感激有人这么说:P。如果这永远不会成功,我必须想出一个新的

因此它工作正常,需要做的两个主要更改是只检查x的平方根(还需要将我的检查用例从检查余数转换为检查求幂)。另一个变化是,使用双精度显然是鲁莽的,因为数字将远远超过最大双精度。

这是来自CodeEval的挑战,我想这是Facebook首先提出的。这是我的大脑立即吐出来的。它通过了所有手动测试用例(例如10->1、25->2、3->0)。我没有看到任何其他的解决方案,因为我想先看看我是如何用自己的想法解决的。如果我太离谱了,这永远不会成功,我会感激有人这么说:P。如果这永远不会成功,我必须想出一个新的方法,我会花更多的时间在这一点上

我看不出有任何情况不能满足……但这不是问题所在。我从来都不擅长计算运行时复杂性,但我认为我有太多的嵌套

我认为,通过从右边和左边进行检查(这在代码中更清楚一点),可以大大减少运行时间。我不确定这是不是像我想的那样有效,或者其他循环仍然太多…或者两者兼而有之

有什么想法吗?这是可以挽救的还是我应该放弃它,用一种新的方式来思考

问题和代码如下。感谢您的关注:-)

信用:这项挑战出现在2011年Facebook黑客杯上。
双平方数是一个整数X,可以表示为两个完美平方的和。例如,10是一个双正方形,因为10=3^2+1^2。你在这个问题上的任务是,给定X,确定它可以写成两个平方和的方法的数目。例如,10只能写成3^2+1^2(我们不认为1^2+3^2是不同的)。另一方面,25可以写成5^2+0^2或4^2+3^2。
注意:不要尝试暴力方法。这是行不通的。以下约束适用:

0Edsgar Dijkstra在其1976年的著作《编程规程》中讨论了这个问题。Dijkstra在单个过程中查找所有对,因为x从n的整数平方根向下扫掠,y从零向上扫掠。考虑函数<代码> b(x,y)< /> >,在x和y之间返回所有合适的对,由下面的三个递归规则加上递归基:

  • 如果x²+y²
  • 如果x²+y²=n,则对(x,y)是一个解,B(x,y)=(x,y)&并;B(x-1,y+1),继续扫描
  • 如果x²+y²>n,那么B(x,y)=B(x-1,y),因为没有任何x的可能解
  • 最后,如果x
下面是我如何在Scheme中编写解决方案的;我将把它留给您翻译成Java:

(define (squares n)
  (let loop ((x (isqrt n)) (y 0) (zs '()))
    (cond ((< x y) zs)
          ((< (+ (* x x) (* y y)) n) (loop x (+ y 1) zs))
          ((< n (+ (* x x) (* y y))) (loop (- x 1) y zs))
          (else (loop (- x 1) (+ y 1) (cons (list x y) zs))))))

Edsgar Dijkstra在其1976年的著作《编程规程》中讨论了这个问题。Dijkstra在单个过程中查找所有对,因为x从n的整数平方根向下扫掠,y从零向上扫掠。考虑函数<代码> b(x,y)< /> >,在x和y之间返回所有合适的对,由下面的三个递归规则加上递归基:

  • 如果x²+y²
  • 如果x²+y²=n,则对(x,y)是一个解,B(x,y)=(x,y)&并;B(x-1,y+1),继续扫描
  • 如果x²+y²>n,那么B(x,y)=B(x-1,y),因为没有任何x的可能解
  • 最后,如果x
下面是我如何在Scheme中编写解决方案的;我将把它留给您翻译成Java:

(define (squares n)
  (let loop ((x (isqrt n)) (y 0) (zs '()))
    (cond ((< x y) zs)
          ((< (+ (* x x) (* y y)) n) (loop x (+ y 1) zs))
          ((< n (+ (* x x) (* y y))) (loop (- x 1) y zs))
          (else (loop (- x 1) (+ y 1) (cons (list x y) zs))))))
我的想法是:

  • 生成0和2147483647之间的所有正方形
  • 对于每个X:
    • 计数=0
    • 有两个迭代器-一个从左开始,一个从右开始
    • 如果
      left+right=X
      ,则增加计数,增加左侧迭代器并减少右侧迭代器
    • 如果
      left+right>X
      ,则减小右侧的值
    • 如果左+右,则增加左一个
    • 左侧
      绕过
      右侧
作为一种优化,我们不需要一直从右边开始,我们可以对开始位置进行二进制搜索

测试代码:

private static int binarySearch(long[] a, long key)
{
    int low = 0;
    int high = a.length - 1;

    while (low <= high) {
        int mid = (low + high) >>> 1;
        long midVal = a[mid];

        if (midVal < key)
            low = mid + 1;
        else if (midVal > key)
            high = mid - 1;
        else
            return mid;
    }
    return Math.min(low, a.length-1);
}

public static void main(String[] args)
{
  long[] squares = new long[46341]; // ceil(sqrt(2147483647)) = 46341
  long val = 0;
  int pos = 0;
  while (true)
  {
     long square = val*val;
     // sanity check, can also use pos >= squares.length
     if (square > 2147483647l)
        break;
     squares[pos++] = square;
     val++;
  }
  int X = 10;
  int left = 0;
  int right = binarySearch(squares, X);
  int count = 0;
  for (; left <= right; )
  {
     //Collections.b
     long l = squares[left] + squares[right];
     if (l == X)
     {
        count++;
        left++;
        right--;
     }
     else if (l > X)
     {
        right--;
     }
     else
     {
        left++;
     }
  }
  System.out.println(count);
}
private static int-binarySearch(长[]a,长键)
{
int低=0;
int高=a.长度-1;
而(低>>1;
长中间值=a[中间值];
中频(中频<键)
低=中+1;
else if(midVal>键)
高=中-1;
其他的
中途返回;
}
返回Math.min(低,a.length-1);
}
公共静态void main(字符串[]args)
{
long[]squares=new long[46341];//ceil(sqrt(2147483647))=46341
长val=0;
int pos=0;
while(true)
{
长正方形=val*val;
//健全性检查,也可以使用pos>=squares.length
如果(方形>2147483647l)
打破
正方形[pos++]=正方形;
val++;
}
int X=10;
int左=0;
int right=二进制搜索(正方形,X);
整数计数=0;
对于(;左X)
{
对--;
}
其他的
{
左++;
}
}
系统输出打印项次(计数);
}
我的想法:

  • 生成0和2147483647之间的所有正方形
  • 对于每个X:
    • 计数=0
    • 有两个迭代器-一个从左开始,一个从右开始
    • 如果
      left+right=X
      ,则增加计数,增加左侧迭代器并减少右侧迭代器
    • 如果
      left+right>X
      ,则减小右侧的值
    • 如果左+右private static int binarySearch(long[] a, long key) { int low = 0; int high = a.length - 1; while (low <= high) { int mid = (low + high) >>> 1; long midVal = a[mid]; if (midVal < key) low = mid + 1; else if (midVal > key) high = mid - 1; else return mid; } return Math.min(low, a.length-1); } public static void main(String[] args) { long[] squares = new long[46341]; // ceil(sqrt(2147483647)) = 46341 long val = 0; int pos = 0; while (true) { long square = val*val; // sanity check, can also use pos >= squares.length if (square > 2147483647l) break; squares[pos++] = square; val++; } int X = 10; int left = 0; int right = binarySearch(squares, X); int count = 0; for (; left <= right; ) { //Collections.b long l = squares[left] + squares[right]; if (l == X) { count++; left++; right--; } else if (l > X) { right--; } else { left++; } } System.out.println(count); }
      int count = 0;
      
      for(int i = 0 ; i < right; i++){
      
         if(Math.sqrt(x-squares[i]) == int(Math.sqrt(x-squares[i]))){
      
            count++;
      
         } else if(int(Math.sqrt(x-squares[i])) < squares[i]) {
      
            break;
      
         }
      
      }
      
      System.out.println(x);