目录
- Container With Most Water(数组)
- First Missing Positive(数组)
- 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;
}
};