`
dengzhi007
  • 浏览: 7895 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

算法面试题(积水问题)

阅读更多

问题描述:在下图里我们有不同高度的挡板。这个图片由一个整数数组所代表,数组中每个数是墙的高度。下图可以表示为数组(2、5、1、2、3、4、7、2)。假如开始下雨了,那么挡板之间的水坑能够装多少水(水足够多)呢?

Wall-1

 

下图是装满水的情况,一个蓝色格子代表一个单位的水。下图中一共装了10个单位的水。

Wall-2

 

上周参加某大型互联网公司面试,结果死在这道算法上。

我给出的算法: 积水面积 = 总面积 - 砖面积 - 无砖无水面积

思想就是化复杂为简单,直接求积水面积不太好求,那就求比它更简单的。

比如总面积,砖的面积都非常简单。

无砖无水面积也不难求,从两侧最小的开始,遇到比自己大的,开始递归。

// 面试时的算法(积水面积=总面积-砖面积-无砖无水面积)
	public static int fill1(int[] nums) {
		if (nums.length < 3) {
			return 0;
		}
		int max = 0;
		int sum = 0;
		for (int i = 0; i <= nums.length - 1; i++) {
			max = Math.max(max, nums[i]);
			sum += nums[i];
		}
		// 积水面积=总面积-砖面积-无砖无水面积
		return max * nums.length - sum - fill1(nums, max, 0, nums.length - 1);
	}

	// 求无砖无水面积(从两侧最小值开始计算,遇上更大的开始递归)
	private static int fill1(int[] nums, int max, int start, int end) {
		int sum = 0;
		if (nums[start] <= nums[end]) {
			int v = nums[start];
			sum += max - v;
			for (int i = start + 1; i <= end; i++) {
				if (nums[i] > v) {
					sum += fill1(nums, max, i, end);
					break;
				} else {
					sum += max - v;
				}
			}
		} else {
			int v = nums[end];
			sum += max - v;
			for (int i = end - 1; i >= start; i--) {
				if (nums[i] > v) {
					sum += fill1(nums, max, start, i);
					break;
				} else {
					sum += max - v;
				}
			}
		}
		return sum;
	}

   无砖无水面积的算法,稍微改动下就可以算砖和水的面积。

   于是我改良了下算法:积水面积 = 砖和水面积 - 砖面积

// 改良后的算法(积水面积=砖和水面积-砖面积)
	public static int fill2(int[] nums) {
		if (nums.length < 3) {
			return 0;
		}
		int sum = 0;
		for (int i = 0; i <= nums.length - 1; i++) {
			sum += nums[i];
		}
		// 积水面积=砖和水面积-砖面积
		return fill2(nums, 0, nums.length - 1) - sum;
	}

	// 求砖和水的面积(从两侧最小值开始计算,遇上更大的开始递归)
	private static int fill2(int[] nums, int start, int end) {
		int sum = 0;
		if (nums[start] <= nums[end]) {
			int v = nums[start];
			sum += v;
			for (int i = start + 1; i <= end; i++) {
				if (nums[i] > v) {
					sum += fill2(nums, i, end);
					break;
				} else {
					sum += v;
				}
			}
		} else {
			int v = nums[end];
			sum += v;
			for (int i = end - 1; i >= start; i--) {
				if (nums[i] > v) {
					sum += fill2(nums, start, i);
					break;
				} else {
					sum += v;
				}
			}
		}
		return sum;
	}

   网上找到一个算法:求砖左右的挡板, 每堆砖积水量 = 最低挡板高 - 砖高

   由于多出两个数组存储和遍历左右挡板,因此性能并不可观。算法出处

  

// 网上找到的算法(仅供性能对比)
	public static int fill0(int[] nums) {
		if (nums.length < 3) {
			return 0;
		}
		int[] l = new int[nums.length];
		int[] r = new int[nums.length];
		int result = 0;
		l[0] = 0;
		r[nums.length - 1] = 0;
		for (int i = 1; i <= nums.length - 2; i++) {
			l[i] = Math.max(l[i - 1], nums[i - 1]);
			r[nums.length - 1 - i] = Math.max(r[nums.length - i], nums[nums.length - i]);
		}
		for (int i = 1; i <= nums.length - 2; i++) {
			if (l[i] > nums[i] && r[i] > nums[i]) {
				result += Math.min(l[i], r[i]) - nums[i];
			}
		}
		return result;
	}

    现在来对比下性能。

   

public static void main(String[] args) {
		int[] nums = new int[] { 2, 5, 1, 2, 3, 4, 7, 2 };
		StringBuilder sb = new StringBuilder();
		if (nums.length > 0) {
			sb.append(nums[0]);
		}
		for (int i = 1; i < nums.length; i++) {
			sb.append("," + nums[i]);
		}
		System.out.println(MessageFormat.format("输入参数: {0}", sb));
		System.out.println(MessageFormat.format("网上算法结果: {0}", FillWater.fill0(nums)));
		System.out.println(MessageFormat.format("面试算法结果: {0}", FillWater.fill1(nums)));
		System.out.println(MessageFormat.format("改良算法结果: {0}", FillWater.fill2(nums)));
		int n = 100000000;
		System.out.println(MessageFormat.format("执行次数: {0} 次", n));
		long time = System.currentTimeMillis();
		for (int i = 0; i < n; i++) {
			FillWater.fill0(nums);
		}
		System.out.println(MessageFormat.format("网上算法耗时: {0} ms", System.currentTimeMillis() - time));
		time = System.currentTimeMillis();
		for (int i = 0; i < n; i++) {
			FillWater.fill1(nums);
		}
		System.out.println(MessageFormat.format("面试算法耗时: {0} ms", System.currentTimeMillis() - time));
		time = System.currentTimeMillis();
		for (int i = 0; i < n; i++) {
			FillWater.fill2(nums);
		}
		System.out.println(MessageFormat.format("改良算法耗时: {0} ms", System.currentTimeMillis() - time));
	}

 

    结果如下:

  

输入参数: 2,5,1,2,3,4,7,2
网上算法结果: 10
面试算法结果: 10
改良算法结果: 10
执行次数: 100,000,000 次
网上算法耗时: 5,445 ms
面试算法耗时: 2,382 ms
改良算法耗时: 1,936 ms

 

    面试时给出的算法: 积水面积 = 总面积 - 砖面积 - 无砖无水面积

    虽然不是最优算法,但也是一种思维,不能算完全错误吧

分享到:
评论

相关推荐

    积水问题 一维及二维解法

    积水问题是一种经典的计算机科学问题,通常出现在算法面试和编程竞赛中。它涉及到寻找二维或一维数组中的“洼地”,并计算在虚拟降雨后能够蓄积的水量。这里我们将详细探讨一维和二维积水问题的解决方案。 对于一维...

    深度学习积水目标检测数据集---坑洼积水数据集

    积水目标检测是这两个领域的交叉应用,通过人工智能的算法和计算机视觉的理论,我们可以训练模型自动识别和理解图像中的积水,进而辅助决策或预警系统。 坑洼积水数据集的文件名称虽然没有提供具体信息,但可以推测...

    积水检测数据集.rar,包含VOC和YOLO数据格式

    积水检测数据集是一个重要的资源,尤其对于那些在计算机视觉领域工作,...通过这个数据集,研究人员和开发者可以训练和评估自己的目标检测算法,尤其是在积水场景的应用,为智能交通、城市规划等领域带来创新解决方案。

    计算机方面 面试题库(算法)

    ### 计算机方面面试题库(算法) #### 1. 中序迭代器 - **难度**: 2 - **问题描述**: 设计一个迭代器,实现对一棵二叉树进行中序遍历的功能。 - **问题提供者**: free - **验证者**: DaLong - **时间复杂度**: O(n)...

    alexnet模型-基于图像分类算法对是否积水识别-不含数据集图片-含逐行注释和说明文档.zip

    alexnet模型_基于图像分类算法对是否积水识别-不含数据集图片-含逐行注释和说明文档 本代码是基于python pytorch环境安装的。 下载本代码后,有个环境安装的requirement.txt文本 如果有环境安装不会的,可自行网上...

    采煤机电控箱内积水问题的研究及改进

    然而,由于煤矿环境潮湿和粉尘较多,电控箱内部积水问题一直是一个技术难题。积水不仅会影响电控箱内电子元件的正常工作,还可能引发短路甚至爆炸,给矿井安全带来极大隐患。因此,研究并解决电控箱内部积水问题显得...

    基于迁移学习算法开发的人工智能脑积水诊断模型的临床应用.pdf

    本研究文档关注于开发一种基于迁移学习算法的人工智能模型,用于脑积水的影像诊断,以及对该模型在临床上的应用和效果评估。脑积水是一种神经科常见的疾病,其特征为脑脊液循环异常导致脑室系统积水。传统的诊断方法...

    中医治积水.pdf

    当这三脏器功能失调,水液代谢就会出现问题,导致积液形成。比如,脾肾阳虚可能导致水湿内停,肺气不足则无法正常疏泄水液,从而形成积水。 中医治疗积水的方法多样,包括中药、针灸、拔罐等。其中,中药治疗积水时...

    工作面采空区积水的治理实践

    我国矿井水文地质类型非常复杂...分析了采空区积水的来源和通道,对8101工作面的采空区积水问题提出了治理的方案。通过在相邻5102巷道打钻孔的方案顺利解决了8101工作面采空区积水问题,实践效果良好,节省资金,优点显著。

    房地产土建工程施工师面试题.doc

    【房地产土建工程施工师面试题解析】 面试房地产土建工程施工师时,面试官可能会提出一系列问题,以评估应聘者的专业技能、项目管理能力和协调沟通技巧。以下是对面试题的详细解答: **问题一:谈谈你自己的优点**...

    采煤机电控箱积水问题改进

    采煤机电控箱是采煤机的核心设备,所以必须要求电控箱可靠、稳定。而在井下工作时电控箱经常出现漏水、积水的现象,导致电器件损坏,设备不能...针对电控箱漏水、积水问题提出了解决办法,为今后采煤机的设计提供了参考。

    矿井采空区积水特征及预防措施

    针对采空区积水问题,文中提出了预防措施,包括严格控制工作面的开采进度和斜长变化,加强工作面斜长变化的调整,提高测量精度,避免积水对开采活动的影响。此外,还应该加强两巷的推进度控制,以避免因斜长变化过大...

    采煤机电控箱内积水问题研究

    电控箱的性能对煤矿的安全高效开采起着关键...电控箱由于水蒸气进入造成的积水问题,经常导致变频器烧毁,给煤矿的安全生产带来较大隐患。分析了电控箱积水原因,并提出增加防爆栅栏的解决方案,具有很好的应用和推广价值。

    [数据集][VOC][正版]道路积水数据集VOC-2759张

    数据集格式:Pascal VOC格式(不包含分割的txt文件,仅仅包含jpg图片和对应的...重要说明:这是检测道路上是否有积水的数据集 特别声明:本数据集不对训练的模型或者权重文件精度作任何保证,数据集只提供准确且合理标注

    基于机器视觉的橡胶输送带积水识别方法

    针对橡胶输送带凹陷处在雨天易形成局部积水无法及时检测的问题,研究并提出了一种基于机器视觉的橡胶输送带积水识别方法。首先对采集图像预处理,通过直方图均衡化提高图像对比度,然后利用图像坐标自动截取感兴趣区域,...

Global site tag (gtag.js) - Google Analytics