我将如何解决这个曼哈顿天际线/石墙的方法,我哪里出错了? Javascript

Posted

技术标签:

【中文标题】我将如何解决这个曼哈顿天际线/石墙的方法,我哪里出错了? Javascript【英文标题】:How would I fix my approach to this Manhattan Skyline/Stone Wall and where did I go wrong? Javascript 【发布时间】:2018-12-26 02:27:22 【问题描述】:

我刚刚遇到这个问题,并认为我会尝试一下,但现在我被困住了,如果可能的话需要帮助。

我一直面临的问题是我的回报通常会下降 1 或 2,但我不知道为什么不这样做。我已经追溯了我的代码,但仍然无法弄清楚

问题:

你要编写一个程序来帮助建筑师绘制城市的天际线。建筑物是矩形的,每个建筑物的高度由给定数组中的一个元素表示。

上面的天际线表示为 [1,3,2,1,2,1,5,3,3,4,2]

到目前为止,这是我正在处理的:

const skyline =(H)=> 
let stack = [];
let count = 0;
let height = 0;

 const addBlock = (value) => 
    if (value > height) 
        stack.push(value - height);
        height = value;
        count += 1;
    
 

 const pop = (value) => 
    while (value < height) 
        height -= stack.pop();
      
    if (value > height) 
        addBlock(value)
    
 

  for (let i = 0; i < H.length; i += 1) 
    let value = H[i];
    if (value < height) 
        pop(value)
     else if (value > height)  
        addBlock(value)
     
 

    return count
 

 skyline([1,3,2,1,2,1,5,3,3,4,2]) //Expect 9

// 测试用例:

let strokes = [1,3,2,1,2,1,5,3,3,4,2] // Expect 9
// let strokes = [5,8] // Expect 8
// let strokes = [1,1,1,1] //  Expect 1

skyline(strokes)

【问题讨论】:

对我来说听起来像是一些学校作业......你能至少解释一下你的问题是什么/在哪里吗?您提供了相关源代码的图片,但未能解释什么不起作用以及您尝试了什么。 @NewToJS 这不是学校作业。我一直面临的问题是我的回报通常会减少 1 或 2,但我不知道为什么不这样做。我已经追溯了我的代码,但仍然无法弄清楚。 请用文字描述你的算法。它可能有助于解决代码和预期行为之间的差异。 @bruce:请不要使用图片。否则有人可能会否决你,请参阅idownvotedbecau.se/imageofcode。 【参考方案1】:

这是基本算法吗?

* Big eats small (and equal-sized)

* Small reduces big to small
  adding the difference

* Count last one standing

例子:

[5,8]
-> 8 eats 5, count 8

[1,1,1,1]
-> 1 eats 1 eats 1 eats 1
-> count 1

[1,3,2,1,2,1,5,3,3,4,2]
-> 3 eats 1
-> 2 reduces 3 to 2 and adds 3-2
-> 1 reduces 2 to 1 and adds 2-1
-> 2 eats 1
-> 1 reduces 2 to 1 and adds 2-1
-> 5 eats 1
-> 3 reduces 5 to 3 and adds 5-3
-> 3 eats 3
-> 4 eats 3
-> 2 reduces 4 to 2 and adds 4-2
-> count 2
Total: 1 + 1 + 1 + 2 + 2 + 2 = 9

javascript 代码:

function f(A)
  let result = 0;
  for (let i=1; i<A.length; i++)
    result += Math.max(0, A[i-1] - A[i]);
  return result + A[A.length-1];


console.log(f([1,3,2,1,2,1,5,3,3,4,2]));
console.log(f([5,8]));
console.log(f([1,1,1,1]));

一个班轮:)

function f(A)
  return [0].concat(A).reduce((a,b,i,A) => a + Math.max(0, A[i-1] - b)) + A[A.length-1];

【讨论】:

根据我对问题的理解,我会说你的正确 @bruce 所以我想一种解决方案可能是尝试编写代码。您能否描述一下您尝试编写的算法(如果不同)? 有人发布了更好的解释here。 (@bruce)【参考方案2】:

当前的答案似乎解决了所提出的问题,另外我想指出解决此类问题的一种方法是手动解决它并记下您采取了哪些步骤来解决它。

在这种情况下,他们会要求您在不拿起铅笔的情况下绘制水平线,而手动绘制水平线的一种方法是在同一行上完成所有可能的笔画,然后再传递到下一行,直到没有行留下来检查。

在每一行,你肯定会检查当前点(数组元素)是否大于0,这意味着它是笔画的一部分。

现在用更简洁的话来说:

    虽然有 rowsLeft,但我将遍历数组。在每一个 我会遍历: 检查当前位置是否大于 0 表示存在 newStroke,也表示有rowsLeft,既然你想保留 继续前进,您希望将当前元素减一。 那么,如果有 newStroke 并且当前元素为 0(结束 stroke) 或者如果它是数组的末尾,我会在我的 numOfStrokes 中加 1 计数并声明,因为我刚刚完成了中风,所以有 暂时没有 newStroke

这就是我为解决您发布的案例所做的工作,我相信您可以从那里编写代码,希望对您有所帮助,然后再次,布鲁斯的回答似乎是正确的,我只是想补充一下您的想法有了解决方案,肯定有很多方法可以做到。

【讨论】:

【参考方案3】:
function minimalNumberOfSkylinesIn(array) 

    if(array.length == 0) 
        return 0;

    let result = array[0];

    for(let i=1; i<array.length; ++i) 
        let differnce = array[i] - array[i-1];
        result += difference > 0 ? difference : 0;
    

    return result;

【讨论】:

以上是关于我将如何解决这个曼哈顿天际线/石墙的方法,我哪里出错了? Javascript的主要内容,如果未能解决你的问题,请参考以下文章

资本家和养猪户

资本家和养猪户

如何画出高级感的曼哈顿图,Manhattan++工具介绍

Marvin Chow:Google+ 全球市场总监,旧金山

骚出天际!一个程序员女装照片的开源项目

4面字节跳动拿到Offer,秀出天际!