4

就 coderbyte 而言,这是我的功能代码。但我有一种感觉,它不应该这么复杂。我错过了一个简单的技巧吗?

function ArithGeo(arr)
{
    var array_type = -1;
    if (arr.length <= 2) return true;

    var a = arr[1], r = a/arr[0], i;
    for (i = 2; i < arr.length; ++i) {
        if ((a *= r) == arr[i]){
            array_type = "Geometric";
        }
        else{
            array_type = -1;
            break;
        }
    }

    if (array_type == "Geometric")
        return array_type;


    a = arr[1], d = a - arr[0], i;
    for (i = 2; i < arr.length; ++i) {
        if ((a += d) == arr[i]){
            array_type = "Arithmetic";
        }
        else {
            array_type = -1;
            break;
        }
    }
    return array_type;
}

ArithGeo([3,9,15,21,27, 28]);
4

6 回答 6

7
function ArithGeo(arr) { 

var diff = arr[1] - arr[0];
var ratio = arr[1] / arr[0];

var arith = true;
var geo = true;

for(var i = 0; i < arr.length - 1; i++)
{
    if( arr[i + 1] - arr[i] !== diff )
      arith = false;
    if(arr[i + 1] / ratio !== arr[i])
      geo = false;
}

if(arith === true)
    return "arithmetic";
else if(geo === true)
    return" geometric";
else
    return -1;

}

这也是一个简单的解决方案。我正在寻找一种几何模式,其中一个给定的元素将被前一个元素整除,或者一个算术模式,其中每个元素都以恒定的量增加。两个变量 diff 和 ratio 包含要在整个数组中搜索的每个模式。

我首先假设 arith 和 geo 为真,如果我找到一个不正确的示例,我将其值设置为假。请注意,您的代码有两个 for 循环,条件完全相同。这很好地表明您的代码可以压缩为一个循环。

每次通过循环时,我都会测试是否存在将 arith 或 geo 设置为 false 的条件。最后,在循环退出后,我将确定 arith 或 geo 是否在整个循环中保持为真。如果不是,我返回 - 1 作为 Coderbyte 请求的问题。

编辑:关于我的 for 循环条件的快速说明。由于我在每次通过时检查 i + 1 的值,因此我通过将退出条件设置为 arr.length - 1 来确保不会超出范围。这样,i + 1 仍然可以到达最后一个元素,并且一定不要过度。

于 2013-10-08T20:05:08.240 回答
6

对于等差数列,从前一个元素中减去每个元素;它们的差异应该相等;对于几何,将每个元素除以前一个元素,比率应该保持不变。至于遇到 0 时除以零,javascript 给你 Inf (当然不是几何级数)。因为浮点数不准确,也许您想存储这些值的最小值和最大值,然后查看它们是否足够接近。

function arithGeo(arr) {
    var minRatio = 1/0,
        maxRatio = -1/0,
        minDiff  = 1/0,
        maxDiff  = -1/0,
        epsilon  = 0.000001,
        i,
        ratio,
        diff;

    if (arr.length <= 2) {
        return;
    }

    for (i = 1; i < arr.length; ++i) {
        diff  = arr[i] - arr[i - 1];
        ratio = arr[i] / arr[i - 1];
        minDiff  = Math.min(diff, minDiff);
        maxDiff  = Math.max(diff, maxDiff);
        minRatio = Math.min(ratio, minRatio);
        maxRatio = Math.max(ratio, maxRatio);
    }

    if (Math.abs(minDiff - maxDiff) < epsilon) {
        return "Arithmetic";
    }

    if (Math.abs(minRatio - maxRatio) < epsilon) {
        return "Geometric";
    }

    return;
}

alert(arithGeo([3,9,15,21,27,28]));
alert(arithGeo([3,9,15,21,27]));
alert(arithGeo([4,2,1,0.5]));
于 2013-08-17T06:09:57.760 回答
2

这可能不是解决问题的最有效方法,也没有解决Antti Haapalaepsilon提到的问题,但这是我对问题的解决方案:

function sequenceMatches(arr, fn) {
  var compare = fn(arr[0], arr[1]);
  for (var i = 2; i < arr.length; i++) {
    if (fn(arr[i - 1], arr[i]) !== compare) return false;
  }
  return true;
}
function ArithGeo(arr) { 
  if (sequenceMatches(arr, function(a, b) { return b - a; })) return 'Arithemetic';
  if (sequenceMatches(arr, function(a, b) { return b / a; })) return 'Geometric';
  return -1;        
}

我选择在两个不同的函数中解决这个问题,因为这有助于清理代码恕我直言。

于 2013-12-05T08:18:34.390 回答
1
function ArithGeo(arr) { 
var apCnt = 1;
 var gpCnt = 1;
  var diff = arr[1] - arr[0]; //ap difference
  var div = arr[1]/arr[0];   //gp difference
  for(var i=1;i<arr.length-1;i++){ //traverse array
    if(arr[i+1] - arr[i] == diff) { //check for ap
      apCnt+=1;
    }
    else if(arr[i+1]/arr[i] == div) { //check for gp
      gpCnt+=1;
    }
    else{
      break;  //break if not ap or gp
    }
  }

  return apCnt == arr.length-1 ? "Arithmetic": gpCnt == arr.length-1 ? "Geometric": -1;  //return if its ap or gp

}
于 2015-06-17T14:46:15.340 回答
0
function ArithGeo(arr){
    if(arr == null || !Array.isArray(arr)){
        return "error";
    }

    var length = arr.length;
    if(length === 0){
        return "neither";
    }
    if(length === 1){
        return "both";
    }

    var arithCount = 0,
        geoCount = 0,
        d = arr[1] - arr[0],
        q = arr[1] / arr[0];
    for(var i = length - 1; i > 0; i--){
        if((arr[i] - arr[i-1]) === d){
            arithCount++;
        }
        if((arr[i] / arr[i-1]) === q){
            geoCount++;
        }
    }

    if(arithCount === length - 1){
        return "Arithmetic";
    }else if (geoCount === length - 1){
        return "Geometric";
    }else if((arithCount === length - 1) && (geoCount === length - 1)){
        return "both";
    }else{
        return "neither";
    }
}

对不起,只考虑整数序列。@Antti Haapala 的回答是正确的。

于 2013-08-17T06:52:23.230 回答
0

非常晚,但我几乎自己做了同样的事情(新手 javascript 用户)。它计算 i + 1 和 i(或 i + 1 / i)之间的差并将其推入一个新数组。然后我使用一个函数来检查数组中的每个元素是否相同。

function numberCheck(array) {
  var arithResult = null;
  var geoResult = null;
  var arithCounter = [];
  var geoCounter = [];
  Array.prototype.allValuesSame = function() {
    for(var i = 1; i < this.length; i++) {
        if(this[i] !== this[0])
            return false;
    } return true;
  }
  for (var b = 0; b < array.length - 1; b++) {
    arithCounter.push(array[b + 1] - array[b]);
  }
  for (var i = 0; i < array.length - 1; i++) {
    geoCounter.push(array[i + 1] / array[i])
  }
  arithResult = arithCounter.allValuesSame();
  geoResult = geoCounter.allValuesSame();
  if (arithResult === true) { return "Arithmetic";}
  else if (geoResult === true) { return "Geometric";}
  else { return "-1";}
}
numberCheck([1,2,4,8])
于 2015-10-07T10:37:14.037 回答