标签 动态规划 下的文章

题目链接:爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

方法一:动态规划

class Solution {
public:
    int climbStairs(int n) {
        int f[50];
        f[1] = 1;
        f[2] = 2;
        f[3] = 3;
        for (int i = 4;i <= n;i++) {
            f[i] = f[i-2] + f[i-1];
        }
        return f[n];
    }
};

方法二:递归

class Solution {
public:
    int nums[50] = {0};

    int f(int x) {
        if (x <= 2) return nums[x];
        if (nums[x] != 0) return nums[x];   // 关键:已经算过就直接返回

        nums[x] = f(x - 1) + f(x - 2);
        return nums[x];
    }

    int climbStairs(int n) {
        nums[1] = 1;
        nums[2] = 2;
        return f(n);
    }
};

题目链接:接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

方法一:动态规划

class Solution {
public:
    int trap(vector<int>& height) {
        int ans = 0;
        int left_i = 0;
        int right_i[10010];
        for (int i = 0;i < height.size();i++) {
            right_i[i] = 0;
        }
        for (int i = height.size()-2;i >= 0;i--) {
            right_i[i] = max(right_i[i+1],height[i+1]);
        }
        for (int i = 1;i < height.size()-1;i++) {
            int right_i = 0;
            left_i = max(left_i,height[i-1]);
            
            if (left_i > height[i] && right_i[i] > height[i]) {
                ans += min(left_i,right_i[i]) - height[i];
            }
        }
        return ans;
    }
};

方法二:双指针

class Solution {
public:
    int trap(vector<int>& height) {
        int n = height.size();
        if (n <= 2) return 0; // 少于3个柱子肯定接不了水

        int left = 0;              // 左指针
        int right = n - 1;         // 右指针
        int left_max = 0;          // 从左往右看到的最高柱子
        int right_max = 0;         // 从右往左看到的最高柱子
        int ans = 0;

        while (left < right) {
            // 谁矮,谁决定当前这边的水位上限
            if (height[left] < height[right]) {
                // 左边更矮,所以水位由左边的最高柱子决定
                if (height[left] >= left_max) {
                    // 更新左边最高柱子
                    left_max = height[left];
                } else {
                    // 左边这个位置可以接的水 = 左边最高 - 当前高度
                    ans += left_max - height[left];
                }
                left++; // 处理完当前 left,往右移
            } else {
                // 右边更矮,水位由右边的最高柱子决定
                if (height[right] >= right_max) {
                    // 更新右边最高柱子
                    right_max = height[right];
                } else {
                    // 右边这个位置可以接的水 = 右边最高 - 当前高度
                    ans += right_max - height[right];
                }
                right--; // 处理完当前 right,往左移
            }
        }

        return ans;
    }
};

题目链接:最大子数组和

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

方法:动态规划

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int ans = nums[0];
        int t = 0;
        for (int num:nums) {
            t = max(num,t+num);
            ans = max(ans,t);
        }
        return ans;
    }
};