week_4_ Container With Most Water

Description

Given n non-positive integers  a1a2, ..., an, where each represents a point at coordinate (iai). n vertical lines are drawn such that the two endpoints of line i is at (iai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.

Solution

很容易想到一种暴力直观的解决方法,即二重循环遍历数组,对每一个序对 (i, j) 且 i < j,其组成的容器面积 area = (j - i) * min(height[ai], height[aj])。

在遍历过程中对最大面积进行更新记录即可,整个算法的时间复杂度为O(n²),在leetcode实现并提交后,算法运行时间超出限定值。

这促使我们思考能否提出一种O(nlogn)的算法。

常规的O(nlogn)算法通常为分治,将问题分解为小规模子问题,并通过线性时间对子问题的解进行合并得到最终结果。

然而尝试着将问题划分为两半,在分别得到左右子集的最大容器面积后,很难对线性时间合并给出一个实际而合理的解释。

那能否先对height在O(nlogn)复杂度内进行排序后,通过O(n)得到结果值呢,这样的算法是存在的,其思路大致如下:

重新申请一个结构体,对每个ai的高度与下标值进行记录,因为我希望在排序后,可以检索其原始下标。

对结构体按高度值进行排序后,按从小到大进行遍历。

对于结构体si,其高度值是height数组中最小的,所以如果可以获取height数组中的begin与end位置,结合原始下标即直接可以对其最大可能面积进行计算。

而后删除si,并对begin与end值进行更新。

整个算法结束后可以如期的得到正确的结果,并且将整体算法的复杂度降为O(nlogn)。

如何可以在O(1)的时间内对begin和end的值进行索引并更新呢,如果单纯用数组或者链表存储,在删除原始下标的si后,还需要花费O(n)时间进行移动。

这里我采用的方法是用两个数组来维护类似于双向链表中每个节点的前驱索引值与后驱索引值,是可以在O(1)的时间内完成检索与更新的。

整个算法的实现如下:

struct node {
	int height;
	int index;
};

bool compare(node left, node right) {
	return left.height < right.height;
}

class Solution {
public:
    int maxArea(vector<int>& height) {
	    int size = height.size();
	    int *forwardVisit = new int[size + 2];
	    int *backwardVisit = new int[size + 2];

	    vector<node> heightArray(size);
	    for (int i = 0; i < size; i++) {
		    //init heightArray
		    heightArray[i].height = height[i];
		    heightArray[i].index = i + 1;
	    }

	    //init visit
            for (int i = 0; i < size + 2; i++) {
		forwardVisit[size] = i + 1;
	        backwardVisit[size] = i - 1;
            }
        
	    //排序
	    sort(heightArray.begin(), heightArray.end(), compare);
	    int begin = 1;
	    int end = size;
	    int result = 0;
	    for (int i = 0; i < size - 1; i++) {
		    int pos = heightArray[i].index;
		    int left_max = pos - begin;
		    int right_max = end - pos;
		    int max = left_max > right_max ? left_max : right_max;
		    int area = max * heightArray[i].height;
		    if (area > result)
			    result = area;
	
		    if (pos == begin)
			    begin = forwardVisit[pos];
		    if (pos == end)
			    end = backwardVisit[pos];
		    forwardVisit[backwardVisit[pos]] = forwardVisit[pos];
		    backwardVisit[forwardVisit[pos]] = backwardVisit[pos];
	    }
	    delete[] forwardVisit;
	    delete[] backwardVisit;
	    return result;
    }
};


在leetcode上提交结果如下:




可以看到,虽然通过了测试,但是从运行时间与排名来看还存在更好的解决方案,会在以后的时间进行进一步的思考。

标题基于SpringBoot的马术俱乐部管理系统设计与实现AI更换标题第1章引言介绍马术俱乐部管理系统的研究背景、意义、国内外研究现状、论文方法及创新点。1.1研究背景与意义阐述马术俱乐部管理系统对提升俱乐部管理效率的重要性。1.2国内外研究现状分析国内外马术俱乐部管理系统的发展现状及存在的问题。1.3研究方法以及创新点概述本文采用的研究方法,包括SpringBoot框架的应用,以及系统的创新点。第2章相关理论总结和评述与马术俱乐部管理系统相关的现有理论。2.1SpringBoot框架理论介绍SpringBoot框架的基本原理、特点及其在Web开发中的应用。2.2数据库设计理论阐述数据库设计的基本原则、方法以及在管理系统中的应用。2.3马术俱乐部管理理论概述马术俱乐部管理的基本理论,包括会员管理、课程安排等。第3章系统设计详细描述马术俱乐部管理系统的设计方案,包括架构设计、功能模块设计等。3.1系统架构设计给出系统的整体架构,包括前端、后端和数据库的交互方式。3.2功能模块设计详细介绍系统的各个功能模块,如会员管理、课程管理、预约管理等。3.3数据库设计阐述数据库的设计方案,包括表结构、字段设计以及数据关系。第4章系统实现介绍马术俱乐部管理系统的实现过程,包括开发环境、编码实现等。4.1开发环境搭建介绍系统开发所需的环境,包括操作系统、开发工具等。4.2编码实现详细介绍系统各个功能模块的编码实现过程。4.3系统测试与调试阐述系统的测试方法、测试用例以及调试过程。第5章系统应用与分析呈现马术俱乐部管理系统的应用效果,并进行性能分析。5.1系统应用情况介绍系统在马术俱乐部中的实际应用情况。5.2系统性能分析从响应时间、并发处理能力等方面对系统性能进行分析。5.3用户反馈与改进收集用户反馈,提出系统改进建议。第6章结论与展望总结马术俱乐部管理系统的设计与实现成果,并展望未来的研究
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值