算法设计与分析课作业【week11】leetcode--动态规划简单难度题目合集

题目1--121. Best Time to Buy and Sell Stock

Say you have an array for which the ith element is the price of a given stock on day i.

If you were only permitted to complete at most one transaction (i.e., buy one and sell one share of the stock), design an algorithm to find the maximum profit.

Note that you cannot sell a stock before you buy one.

Example 1:

Input: [7,1,5,3,6,4]
Output: 5
Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
             Not 7-1 = 6, as selling price needs to be larger than buying price.

Example 2:

Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.

这个题目的要求是每天的石头都有不一样的价格,求买一个石头然后将其卖出能获得的最大收益。那我们的做法是从头开始遍历数组,记录在当前位置之前数组中最小的值,用当前位置的值减掉之前数组中最小的值,也就获得了在当前位置如果卖出石头能获得的最大收益。

C++代码如下:

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        if (prices.size() == 0)
            return 0;
        int min = prices[0];
        vector<int> profit(prices.size());
        for (int i = 1; i < prices.size(); ++i) {
            if (prices[i] < min)
                min = prices[i];
            else
                profit[i] = prices[i] - min;
        }
        return *max_element(profit.begin(), profit.end());
    }
};

 

题目2--746. Min Cost Climbing Stairs

On a staircase, the i-th step has some non-negative cost cost[i] assigned (0 indexed).

Once you pay the cost, you can either climb one or two steps. You need to find minimum cost to reach the top of the floor, and you can either start from the step with index 0, or the step with index 1.

Example 1:

Input: cost = [10, 15, 20]
Output: 15
Explanation: Cheapest is start on cost[1], pay that cost and go to the top.

Example 2:

Input: cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1]
Output: 6
Explanation: Cheapest is start on cost[0], and only step on 1s, skipping cost[3].

Note:

  1. cost will have a length in the range [2, 1000].
  2. Every cost[i] will be an integer in the range [0, 999].

题目的要求是数组每个位置上的值代表从在位置上移动需要的开销,从数组的0或1的位置开始,每次走1步或2步,直到走到数组的末尾为止,求出走到末尾的最小开销。那我们可以从数组下标2的位置开始遍历,判断走到位置 i 所需要的最小总开销,走到位置 i 时,要么是从 i - 2 移动到 i,要么是从  i - 1 移动到 i, 所以最小的总开销就从 i-2 或i - 1到 i 的开销最小获得,不断推下去,到达数组末尾时,最小的总开销就时数组最后一个或最后第二个两个之间所记录的总开销中最小的一个。

C++代码如下:

class Solution {
public:
    int minCostClimbingStairs(vector<int>& cost) {
        if (cost.size() == 0)
            return 0;
        if (cost.size() <= 2)
            return *min_element(begin(cost), end(cost));
        vector<int> pay(cost);
        for (int i = 2; i < cost.size(); ++i)
            pay[i] += min(pay[i - 2], pay[i - 1]);
        return min(pay[pay.size() - 1], pay[pay.size() - 2]);
    }
};

题目3--70. Climbing Stairs

You are climbing a stair case. It takes n steps to reach to the top.

Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?

Note: Given n will be a positive integer.

Example 1:

Input: 2
Output: 2
Explanation: There are two ways to climb to the top.
1. 1 step + 1 step
2. 2 steps

Example 2:

Input: 3
Output: 3
Explanation: There are three ways to climb to the top.
1. 1 step + 1 step + 1 step
2. 1 step + 2 steps
3. 2 steps + 1 step

题目的要求是我们每次可以走1步或者两步,给出总的步数n,计算总共有多少种方式能走到n。这题的方法跟上一题的类似,每个n都是由n-1或n-2走来,我们只要从头开始计算走到n-1,n-2最多的方式,就可以获得走到n最多的方式,也可以看作是斐波纳契数列的一个应用:0,1,2,3,5,8,.....。

C++代码如下:

class Solution {
public:
    int climbStairs(int n) {
        if (n < 2)
            return n;
        int step[n + 1] = {1, 1};
        for (int i = 2; i <= n; ++i) {
            step[i] = step[i - 1] + step[i - 2];
        }
        return step[n];
    }
};

题目4--53. Maximum Subarray

Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.

Example:

Input: [-2,1,-3,4,-1,2,1,-5,4],
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.

题目的要求是在一个数组中,找到一个连续子数组的和最大,那我们可以先这样想,在数组的某个位置中,如果在该个位置上前面的子数组的和是负数,那自然不要加,否则只会更小,如果是正数,那就可以加入前面的数组,所以我们在每个位置上记录在当前位置所属于的子数组和的最大值即可。

C++代码如下:

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        if (nums.size() == 0)
            return 0;
        for (int i = 1; i < nums.size(); ++i)
            nums[i] = nums[i - 1] < 0 ? nums[i] : nums[i] + nums[i - 1];
        return *max_element(nums.begin(), nums.end());
    }
};

题目5--198. House Robber

You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night.

Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.

Example 1:

Input: [1,2,3,1]
Output: 4
Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
             Total amount you can rob = 1 + 3 = 4.

Example 2:

Input: [2,7,9,3,1]
Output: 12
Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1).
             Total amount you can rob = 2 + 9 + 1 = 12.

题目的要求是数组的每个位置上的值代表一个家庭中的财物,我们可以偷取,但不能偷数组相邻位置上的财物,否则会被抓,那我们可以在数组的每个位置上记录从0偷到该位置上能够获得的最大的值,当数组长度大于4时,我们可以看到n上的最大值是加上n-2 或n-3的值上得到的。所以不断循环,数组的最后一个或倒数第二个中的记录的值其实有一个是最大值。

C++代码如下:

class Solution {
public:
    int rob(vector<int>& nums) {
        if (nums.size() == 0)
            return 0;
        if (nums.size() < 3)
            return *max_element(nums.begin(), nums.end());
         nums[2] += nums[0];
        for (int i = 3; i < nums.size(); ++i) {
            nums[i] += max(nums[i - 2], nums[i - 3]);
        }
        return max(nums[nums.size() - 1], nums[nums.size() - 2]);
    }
};

题目6--303. Range Sum Query - Immutable

Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive.

Example:

Given nums = [-2, 0, 3, -5, 2, -1]

sumRange(0, 2) -> 1
sumRange(2, 5) -> -1
sumRange(0, 5) -> -3

Note:

  1. You may assume that the array does not change.
  2. There are many calls to sumRange function.

这个题目要求很简单,给定数组,然后让求范围内的和。如果再每次求和的时候用一个循环来求,是可以解决,但这也太没意思了,而且我们要注意题目提示到会调用sumRange很多次,这题目又是属于动态规划类,我们自然是要使用动态规划的方式来做才行。我们可以用一个数组来记录从数组到当前位置的所有数的和,即sum[i] = nums[0] + nums[1] +... + num[i - 1] + num[i],这样sunRange的执行我们只需要使用sum[j] - sum[i - 1],i = 0 时再特殊处理下就行。

C++代码如下:

class NumArray {
public:
    vector<int> sum;
    
    NumArray(vector<int> nums) {
        sum.assign(nums.begin(), nums.end());
        for (int i = 1; i < sum.size(); ++i)
            sum[i] += sum[i - 1];
    }
    
    int sumRange(int i, int j) {
        if (i == 0)
            return sum[j];
        return sum[j] - sum[i - 1];
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值