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