确定数组是算术还是几何级数(来自Coderbyte)

时间:2013-08-17 04:48:26

标签: javascript

就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]);

6 个答案:

答案 0 :(得分: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是真的,如果我找到一个不正确的例子,我将其值设置为false。请注意,您的代码有两个for循环,条件完全相同。这是一个很好的指示,您的代码可以压缩成一个循环。

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

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

答案 1 :(得分: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]));

答案 2 :(得分:2)

它可能不是解决问题的最有效方法,但它没有解决 Antti Haapala 提到的epsilon问题,但这是我解决问题的方法:

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;        
}

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

答案 3 :(得分: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的回答是正确的。

答案 4 :(得分:0)

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

}

答案 5 :(得分: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])