StakeOut:使用递归找到最佳期望

时间:2014-09-29 06:13:30

标签: javascript algorithm recursion

我最近接受了一次我正在采访的创业公司的编码任务。他们给了我以下问题并要求解决方案:

  

恭喜!你是一群邪恶的新精英黑客   NE' ER-DO-井

     

幸运的是,这一组比你最后一支痞子队更加邋and,而且   他们期待软件(和你)改善他们的看法。缺点   男子为团队,每个街道都挨家挨户地冒充了   白蚁检查员,所以他可以秘密地将有价值的商品全部包括在内   每个房子。通常这帮人只会抢夺所有宝贵的房屋,   但是有一个问题!每当房子被这个富人抢劫时   邻居,警察看着它和附近的房子   个月。

     

因此,该团伙不能轻易抢劫所有房屋,如果他们选择抢劫   一,他们再也不能抢夺房子两边的房子了。

     

这位头目想知道他应该抢劫什么房子来最大限度地利用这些房屋   团队的利润,他现在想知道。写一个需要的函数   在正整数数组(home值)并返回最大值   抢劫那条街的预期价值。

     

例如:

     

[20,10,50,5,1]应该返回71美元,抢夺第一,第三,   和第五个房子是最佳的[20,x,50,x,1]

     [20,50,10,1,5]应该返回55美元,因为抢劫第二个和   第五个房屋是最佳的[x,50,x,x,5]


基本上,你只能将替代房屋的价值加起来,因为如果房屋遭到抢劫,由于街道安全严重,房屋前后的房屋不能被抢劫。

我使用递归编写了一个解决方案并将其呈现给他们。
我提出了一个解决所有案例的解决方案,除了以下内容:

  

[2,3,2],返回的答案是3,而不是4.

他们告诉我要解决这个问题。因为,这是算法无法运行的唯一情况,我使用以下代码来解决问题(用JavaScript编写):

// The recursive alrogithm doesn't account for arrays of length 3.
    if(array.length === 3) {
        if(array[0] + array[2] > array[1]) {
            return 'Optimal expectation of robbing street: ' + String(array[0] + array[2]);
        } else{
            return 'Optimal expectation of robbing street: ' + String(array[1]);
        }
    }


所以完整的最终解决方案如下(包括上面的代码片段):

    // Global variable for expectation:
    var expectation = 0;

    function optimalExpectation(array) {
        // 'array' contains the home values

        // The recursive alrogithm doesn't account for arrays of length 3.
        if(array.length === 3) {
            if(array[0] + array[2] > array[1]) {
                return 'Optimal expectation of robbing street: ' + String(array[0] + array[2]);
            } else{
                return 'Optimal expectation of robbing street: ' + String(array[1]);
            }
        }
        // Base case for recursion:
        if(array.sum() === 0) {
                return 'Optimal expectation of robbing street: ' + String(expectation);
        } else{
            expectation += array.max();
            var maxIndex = array.indexOf(array.max());
            // Recursive call:
            return optimalExpectation(injectZeros(array, maxIndex));
        }
    }

    //===============================================================================
    // Protypal methods for maximum & sum:
    // All array objects inherit these methods from the Array prototype:

    Array.prototype.max = function(){
        if(this.length === 1){
            return this[0];
        } else if(this.length === 0){
            return null;
        }
        var maximum = 0;
        for(var i = 0; i < this.length; i++){
            if(maximum < Math.max(this[i], this[i + 1])){
                maximum = Math.max(this[i], this[i + 1]);
            }
        }
        return maximum;
    };

    Array.prototype.sum = function(){
        var sum = 0;
        this.forEach(function(el){
            sum += el;
        });
        return sum;
    };

    // Function to replace maximum values, already accounted for, with zeroes:
    function injectZeros(array, index){
        if(array.length > 0){
            if(index < array.length - 1)
                array[index + 1] = 0;
            if(index > 0)
                array[index - 1] = 0;
        }
        array[index] = 0;
        return array;
    }

    //==================================================================================


    console.log(optimalExpectation([2, 3, 2]));  // correctly returns 4, instead of 3

我在提交上述解决方案后被拒绝了。在我最初的解决方案之后,他们并没有拒绝我(他们绝对可以)。他们希望我解释我的思考过程以及如何修复bug。

我很感激我可能出错的地方。有没有办法改进我的算法?我的代码组织得很好吗?这是正确的方法吗?如果您是一名熟悉初创公司招聘决策知识的专业开发人员,您能详细说明可能导致团队拒绝我的原因吗?

3 个答案:

答案 0 :(得分:0)

我不是招聘经理。但是快速检查说你只能尽可能多地选择最大的房子。问题是概念性的,你在地毯下扫描而不是修复你的算法(当你选择[2, 3, 2, 0.5]然后3时,问题也会出现0.5,而不是最佳22 - 长度3)没有什么特别之处。正确的解决方案至少会使用回溯来探索选择不同的元素是否会带来更多的利润,而不是贪婪地选择局部最大值而不考虑上下文。在每个步骤检查最大值和邻居就足够了。

var values = [2, 3, 2, 0.5];

function rob(values) {
  if (values.every(function(e) { return e === null })) return [];
  var len = values.length;
  var max = Math.max.apply(null, values);
  var subMax = -Infinity;
  var subArray = [];
  for (var i = 0; i < len; i++) {
    if (values[i] !== null && (values[i - 1] === max || values[i] === max || values[i + 1] === max)) {
      nextValues = values.slice();
      nextValues[i] = null;
      if (i > 0) nextValues[i - 1] = null;
      if (i < len - 1) nextValues[i + 1] = null;
      var subResult = rob(nextValues);
      var subSum = subResult.reduce(function(a, b) { return a + b; }, 0) + values[i];
      if (subSum > subMax) {
        subArray = subResult;
        subArray.push(values[i]);
        subMax = subSum;
      }
    }
  }
  return subArray;
};

alert(rob(values));

答案 1 :(得分:0)

你应该去观看Roughgarden教授关于路径图中加权独立集的讲座,https://class.coursera.org/algo2-2012-001/lecture/83。它使用动态编程来解决面试问题。解决方案相当简单。您可以使用递归或迭代来完成它。

答案 2 :(得分:0)

function computeRob (arr, index, canRob) {
    if(arr.length == index){
        return 0;
    }

    if (canRob == true) {
        var withRob = arr[index] + computeRob(arr, index + 1, false);
        var withoutRob = computeRob(arr, index + 1, true);
        return Math.max(withRob, withoutRob)
    } else {
        return withoutRob = computeRob(arr, index + 1, true);
    }
}

console.log(computeRob([4,3,8,9,2],0,true));