最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

algorithm - What is the most efficient way to check for a sequence of numbers in a JavaScript array? - Stack Overflow

programmeradmin1浏览0评论

Background

For a technical interview I was tasked with implementing a missing algorithm in JavaScript. The interviewer supplied me with some code and 18 failing unit tests that once the algorithm was successfully implemented would pass. I'm sure there is a more efficient way to have solved this problem as I tried a few different approaches during my allotted time. This way is the first way that I got to work, which for the technical test was enough but I'd like to know a better way of solving the problem.

Problem

Work out if the cards in a poker hand form a straight. (I've already ordered the hand in ascending order.)

My Solution

PokerHand.prototype._check_straight_function = function(arr) {
    var isStraight = false;
    for (var j = i = 4; i >= 0 && j > 1; i--)
        if (arr[i].value() - 1 == arr[--j].value()) {
            isStraight = true;
        } else {
            isStraight = false;
        }
    };
    return isStraight;
};

Other approaches

Things I didn't get working that I think might work faster, I'd really appreciate if someone could talk me through a working version of the below approach(es) and help me understand which is the fastest to evaluate.

  • recursive use of arr.pop().value - 1 == arr.pop().value()
  • filter the array to create a new array that contains only values where the next index (arr[++i])is the current index + 1 and then see if the new array is the same length.
  • a for loop with a break / continue to short circuit as soon as the straight ends.

Background

For a technical interview I was tasked with implementing a missing algorithm in JavaScript. The interviewer supplied me with some code and 18 failing unit tests that once the algorithm was successfully implemented would pass. I'm sure there is a more efficient way to have solved this problem as I tried a few different approaches during my allotted time. This way is the first way that I got to work, which for the technical test was enough but I'd like to know a better way of solving the problem.

Problem

Work out if the cards in a poker hand form a straight. (I've already ordered the hand in ascending order.)

My Solution

PokerHand.prototype._check_straight_function = function(arr) {
    var isStraight = false;
    for (var j = i = 4; i >= 0 && j > 1; i--)
        if (arr[i].value() - 1 == arr[--j].value()) {
            isStraight = true;
        } else {
            isStraight = false;
        }
    };
    return isStraight;
};

Other approaches

Things I didn't get working that I think might work faster, I'd really appreciate if someone could talk me through a working version of the below approach(es) and help me understand which is the fastest to evaluate.

  • recursive use of arr.pop().value - 1 == arr.pop().value()
  • filter the array to create a new array that contains only values where the next index (arr[++i])is the current index + 1 and then see if the new array is the same length.
  • a for loop with a break / continue to short circuit as soon as the straight ends.
Share Improve this question edited Oct 7, 2015 at 5:34 Luke asked Oct 7, 2015 at 5:06 LukeLuke 3,5516 gold badges40 silver badges63 bronze badges 9
  • are the cards in the hand sorted? – stinepike Commented Oct 7, 2015 at 5:09
  • 1 Looks like your question might be a better fit for codereview.stackexchange. – Spencer Wieczorek Commented Oct 7, 2015 at 5:09
  • @StinePike yes, per the line (I've already sorted the cards in ascending order) – Luke Commented Oct 7, 2015 at 5:11
  • 1 The code is incorrect because it will assign isStraight (or clear it) only for the given pair being checked. Thus the "last pair" incorrectly determines the result. – user2864740 Commented Oct 7, 2015 at 5:16
  • 1 Because the array is already ordered, we know that a necessary condition to have a straight is that the difference between the first card value and the last card value is exactly four. You may have a global performance gain by adding this test if you have a large number of arrays to check and most of them are not passing it. Side note : if we know that all cards have distinct values, it bees a sufficient condition. – Arnauld Commented Oct 7, 2015 at 16:24
 |  Show 4 more ments

6 Answers 6

Reset to default 2

There's no need to assign a variable isStraight at all.

PokerHand.prototype._check_straight_function = function(arr) {
    for (var i = i = 4; i++) {        
        if (arr[i].value() - 1 != arr[i-1].value()) {
            return false;
        }
    };

    return true;
};

Just throwing it out there, I think this one does it with the least amount of lines (3), whether or not that is "better" is subjective as it is probably less clear

    var last = arr.pop().value(), popped;
    while ((popped = arr.pop().value()) === --last);
    return popped === undefined;

The [original] code is incorrect because it will assign isStraight (or clear it) only for the given pair being checked. Thus the "last pair" incorrectly determines the result.

In my book the "better way", is to keep it clean:

for (var i = 0; i < 4; i++) {
    var a = arr[i];   // arr[0..3]
    var b = arr[i+1]; // arr[1..4]
    if (!(a.value() + 1 == b.value())) {
        return false; // Not sequential
    }
};
return true;

If a zip higher-order function is available this could be reduced as a variation of

arr.zip(function (a, b) { return [a.value(), b.value()] })
   .every(function (x) { return x[0] + 1 === x[1] })

but zip is not standard.

here is a similar code with some minor optimization ( in java,, check the algorithm)

    boolean isStraight = true;
    for (int i = 0; i < 4; i++) {
        if (arr[i] + 1 != arr[i+1]) {
            isStraight = false;
            break;
        }
    };

Well, this is maybe a tiny bit tidier. I don't see a Ninja way ;( As far as paring the solutions -- I'm an employer, and for my part, I'd prefer the answer which was clear and elegant over one which was a few nanoseconds faster :)

for (var i = 0; i < 5; i++) {
  if (a[i].value() != i + a[0].value())
    return false;
}
return true;

here is another way

var isOrdered = true;
[5, 6, 8, 9].sort(function(a, b) {
  (b - a != 1) ? isOrdered = false: true;
});
alert(isOrdered);

DEMO

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论