水沟添水问题

之前在CSDN看到过这道题,感觉挺有趣的,之后又遇到了,这里分享一下相关问题的解法。(试题分析参考:我的Twitter技术面试失败了


看下面这个图片”

“在这个图片里我们有不同高度的墙。这个图片由一个整数数组所代表,数组中每个数是墙的高度。上边的图可以表示为数组[2,5,1,2,3,4,7,7,6]”

“假如开始下雨了,那么墙之间的水坑能够装多少水呢?”

“以1×1的方块为单位计算容积。所以,在上边的图中下标为1以左的都会漏掉。下标7以右的也会漏掉。剩下的只有在1和6之间的一坑水,容积是10”


逻辑如下:

如果我们从左至右遍历列表,每个下标水的量最多是到现在为止最大的数。这表示如果我们已知右边有相等或更大的,我们可以知道存下的水有多少。反向遍历的时候也一样:如果我们知道左边有比右边最大的数更大的,我们装水是毫无问题的。

基于这个想法,一个解决方法是:先找到最大值,从左遍历到最大值,然后从右遍历到最大值。这个方法需要两次遍历:一次找到最大值,另一次分成了两个子遍历。

一次遍历的方法通过两端的指针相向移动避免了寻找最大值。如果(左指针找到的左指针以左的最大值)小于(右指针找到右指针以右的最大值),将左指针向右移动一位。否则右指针向左移动一位。重复过程直到两个指针相遇。(解释起来很麻烦,但是代码很简单)

相关代码可以参考:https://github.com/CuGBabyBeaR/Interview-questions/tree/master/twitter-puddle

其中C++:

/* 
 * CuGBabyBeaR  
 */

#include "stdio.h"

int volume_calcuate(int[],int);

int main(int argc, char const *argv[]){
    int testcase_1[9] = {2,5,1,2,3,4,7,7,6};
    int testcase_2[10] = {2,5,1,3,1,2,1,7,7,6};
    int testcase_3[9] = {6,1,4,6,7,5,1,6,4};

    printf("Case testcase_1 total volume : %i\n",volume_calcuate(testcase_1,9));
    printf("Case testcase_2 total volume : %i\n",volume_calcuate(testcase_2,10));
    printf("Case testcase_3 total volume : %i\n",volume_calcuate(testcase_3,9));
    return 0;
}

int volume_calcuate(int walls[] , int length){
    int * p_l = &walls[0];
    int * p_r = &walls[length-1];
    int max_l = walls[0];
    int max_r = walls[length-1];

    int total_volume = 0;

    while(p_r > p_l){
        if (max_l < max_r){
            p_l++;
            if (*p_l >= max_l){
                max_l = *p_l;
            }else{
                total_volume += max_l - *p_l;
            }
        }else{
            p_r--;
            if (*p_r >= max_r){
                max_r = *p_r;
            }
            else{
                total_volume += max_r - *p_r;
            }
        }
    }
    return total_volume;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值