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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36124194/article/details/82392678

目录

  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;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_36124194/article/details/82392678