算法设计与分析第一周练习

##目录

  1. Container With Most Water(数组)
  2. First Missing Positive(数组)
  3. Largest Rectangle in Histogram(栈)
    #Container With Most Water
    ###题目
    Given n non-negative integers a1, a2, …, an , where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.

Note: You may not slant the container and n is at least 2.
这里写图片描述
###分析
这种比较大小的题目,一看题目最容易想到的方法是全部遍历,但这样的方法在leetcode中是不可能出现的,所以肯定还有简单的遍历的办法。从图中我们可以观察,当容器的高是底的纵坐标较少的一条的时候,如果遍历的下一条比这条边要短的时候,容器的大小肯定要比原来的小,这样我们直接就可以跳过这条边,遍历下一条,当边比前一条边长的时候,这是个临界点,这个时候换成从另一边遍历。从这样一个特征出发,我们的做法可以如下:

  1. 从两边向中间遍历。
  2. 如果遍历的时候下一条高的长度比前一条高的长度要短,那么容器的大小肯定要比原来的要少,这是直接跳过这条边,继续遍历下一条边。
  3. 如果遍历的时候下一条高的长度要长,那么容器的大小可能比原来的大,也可能比原来的小,此时选择从另一边开始遍历。
  4. 遍历结束的标志是前一个下标比下一个下标要大。这种方法的优点源于可以快速筛选掉一些不符合条件的边,能够大量的缩短遍历的时间。
    ###源码
class Solution {
public:
    int maxArea(vector<int>& height) {
    	//max存遍历到当前为止的最大值
        int max = 0;
        int size = height.size();
        int i = 0, j = size - 1;
        int temp = 0;
        //找最大值
        while(i < j) {
        	//在左边的下一条边小与前一条边的时候继续遍历
        	if(height[i] < height[j]) {
        		temp = height[i]*(j-i);
        		i++;
        	} else {//在左边的下一条边大与前一条边的时候换一个方向遍历
        		temp = height[j]*(j-i);
        		j--;
        	}
        	if(max < temp) {//找最大的值max
        		max = temp;
        	}
        }
        return max;
    }
};

#First Missing Positive
###题目
Given an unsorted integer array, find the smallest missing positive integer.
这里写图片描述
###分析
这题的目的非常明显,刚开始学编程的时候我们做的大概是这类题目,但这题有了时间和空间的限制,这便使得题目的难度增加不少。题目要求时间复杂度为O(n)并且使用常量个空间,如果按照一般的做法,算法复杂度为O(n*n)。而且不能有多的空间,这说明我们应该尽量在原数组的基础上处理,不能申请大量的空间。首先我们明确下面的特点:

  1. 大小为n的容器,容器中最小的数必须在n的范围内,这是最坏的情况。
  2. 下标本身有序,利用下标标记容器元素的顺序可以减少使用的空间。
  3. 当下标的数值与容器的数值不是i +1 =nums[i]的关系时,i+1便是要找的最小的数。

###源码

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        int size = nums.size();
        //第一次遍历将数组重新调整顺序,将容器大小范围内的数调整好,
        //如nums[0]放1,nums[1]放2
        for(int i = 0; i < size; i++) {
        	while(nums[i] <= size&&nums[i] > 0&&nums[nums[i] - 1] != nums[i]) {
        		int temp = nums[nums[i] - 1];
        		nums[nums[i] - 1] = nums[i];
        		nums[i] = temp;
        	}
        }
        //第二次遍历找出第一个下标与其值不对应的,即nums[i]!=i+1的
        for(int i = 0; i < size; i++) {
        	if(nums[i] != i+1) {
        		return (i+1);
        	}
        }
        //当容器的数字交换后刚好是顺序排列时返回size+1
        return (size+1);
    }
};

Largest Rectangle in Histogram

##题目
Given n non-negative integers representing the histogram’s bar height where the width of each bar is 1, find the area of largest rectangle in the histogram.
这里写图片描述
###Example

Input: [2,1,5,6,2,3]
Output: 10

##分析
这题用的是栈来解决,构造一个升序栈:

  1. 当入栈的元素比栈顶元素大的时候,直接将元素push进栈。
  2. 当入栈的元素比栈顶元素小的时候,这是个临界条件,表示需要对结果进行计算,从当前下标表示的元素开始往前计算,与此前计算的结果比较,选择大的作为结果。
  3. 当栈中的元素都是升序表示的时候,再用一个复杂度为O(n)的循环计算结果,与此前计算的结果比较。
    这个算法的核心是:中间的短板没有用!
    ##源码
class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
    	int max = 0;
    	stack<int> s;
    	for(int i = 0; i < heights.size(); i++) {
    		while((!s.empty())&&heights[s.top()] > heights[i]) {
    			int top = s.top();
    			s.pop();
    			int temp = 0;
    			if(s.empty()) {
    				temp = i*heights[top];
    			} else {
    				temp = heights[top]*(i-s.top()-1);
    			}
    			if(temp > max) {
    				max = temp;
    			}
    		}
    		s.push(i);
    	}

    	while(!s.empty()) {
    		int top = s.top();
    		int h = heights[top];
    		s.pop();
    		int sum = 0;
    		if(s.empty()) {
    			sum = heights.size()*h;
    		} else {
    			sum = h*(heights.size() - 1 - s.top());
    		}
    		if(sum > max) {
    			max = sum;
    		}
    	}
    	return max;
    }
};

更多技术博客https://vilin.club/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值