面试题之陈利人 数组墙

69 篇文章 0 订阅
60 篇文章 3 订阅

数组墙

  • 题目
给定一个正整数数组如[2,5,1,2,3,4,7,7,6],数组中每个数代表一个墙的高度,如图,
           
  • 分析
一开始我想的太复杂了,时间复杂度都到了O(n*log n),后来看了陈老师的解释的时间复杂度为O(n),心里挺佩服的。后就不看解释了,自己想,想好算法后,开始写代码,调了一下午,发现算法考虑的情况不全,当时心痛呀,那个痛呀。今天上午仔细看了一下陈老师的分析。感觉一个字“棒”。特意整理一下,供大家参考。
我们拿个例子来说吧
陈老师的解法:
有如下标识符 


例子数据,并且标识初始化如下

然后开始双向遍历数组(直至整个数组都遍历完毕才结束)。

比较当前LM和RM,发现 LM<RM,然后LI向右移动一个单位,如下

当前LI指向的数据比LM指向的数据大,则更新LM为当前LI。如下

然后接着比较当前的LM和RM,发现LM>RM,则RI向左移动一位,如下


比较RI不比RM大,所以不更新RM,这时候证明RI可以存水,存水量即 (11 - 1 ) = 10。
然后接着比较当前的LM和RM,发现LM>RM,则RI向左移动一位,如下

接着发现RI可以存水,然后计算存水的量。
然后LM<RM,RI继续左移,如下

发现RI也可以存水,并计算存水的量,
然后继续比较LM<RM,RI继续左移,此时RI不比RM大,RM不更新,继续计算RI的存水量。如下
   
接着LM<RM,RI左移,如下

发现RI>RM,则更新RM ,此时RI不能存水,如下

到这相信大家都明白了吧,汉字我就不多说了,直接看图走过程吧
     


接着最后RI = LI,整个数组遍历完毕,算法结束,所有的存水量加起来就是 结果啦。


  • 实验
        
  • 代码
test.cpp
#include<iostream>
using namespace std;

size_t const size = 10;

//function declare
int Run(int data[],int length);

int main()
{
	int * data = new int[size];
	cout<<"array wall :";
	for(size_t i = 0; i<size; i++)
	{
		data[i] = rand()%19;
		cout<<data[i]<<" ";
	}
	cout<<endl<<"water ";
	cout<<Run(data,size)<<endl;
	system("pause");
	return 0;
}

int Run(int data[],int length)
{
	if(data == NULL && length < 3)
	{
		return 0 ;
	}
	int left_index = 0;
	int right_index = length - 1 ;
	int left_max = data[left_index];
	int right_max = data[right_index];
	int count = 0;
	while( left_index < right_index )
	{
		if( left_max < right_max )
		{
			left_index ++ ;
			if( data[left_index] > left_max )
			{
				left_max = data[left_index];
			}
			else
			{
				count += left_max - data[left_index];
			}
		}
		else
		{
			right_index --;
			if(data[right_index] > right_max)
			{
				right_max = data[right_index];
			}
			else
			{
				count += right_max -data[right_index];
			}
		}
	}
	return count ;
}

再次感谢陈利人老师的题目!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值