IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 动态规划习题总结 -> 正文阅读

[数据结构与算法]动态规划习题总结

目录

一.最小花费爬楼梯

1.题目

2.图解

3.代码

(1)时间复杂度为O(N),空间复杂度为O(N)

(2)时间复杂度为O(N),空间复杂度为O(1)

二.买卖股票的最佳时机

1.题目

2.图解

3.代码?

三.反转数位

1.题目

2.图解

3.代码

?四.最大正方形

1.题目

2.图解

3.代码

五.连续子数组的最大乘积

1.题目

2.图解

3.代码

?六.和为k的子数组

1.题目

2.图解

3.代码

七.和为k的最长连续子数组的长度

1.题目

2.图解

3.代码


一.最小花费爬楼梯

1.题目

给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。

你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。

请你计算并返回达到楼梯顶部的最低花费。

例子:

输入:cost = [1,100,1,1,1,100,1,1,100,1]
输出:6
解释:你将从下标为 0 的台阶开始。
- 支付 1 ,向上爬两个台阶,到达下标为 2 的台阶。
- 支付 1 ,向上爬两个台阶,到达下标为 4 的台阶。
- 支付 1 ,向上爬两个台阶,到达下标为 6 的台阶。
- 支付 1 ,向上爬一个台阶,到达下标为 7 的台阶。
- 支付 1 ,向上爬两个台阶,到达下标为 9 的台阶。
- 支付 1 ,向上爬一个台阶,到达楼梯顶部。
总花费为 6 。

2.图解

3.代码

(1)时间复杂度为O(N),空间复杂度为O(N)

    //使用最小花费爬楼梯
    public int minCostClimbingStairs(int[] cost) {
        //dp每个位置是cost当前位置的最小值,最后一个位置保存前面到顶部的最小值
        int[] dp = new int[cost.length+1];
        //相当于初始化可以从第一个或的第二个开始进行跳跃
        for(int i=2; i<=cost.length; i++) {
            dp[i] = Math.min(dp[i-1]+cost[i-1], dp[i-2]+cost[i-2]);//找前两个中的最小
        }
        return dp[cost.length];
    }

(2)时间复杂度为O(N),空间复杂度为O(1)

public int minCostClimbingStairs2(int[] cost) {
        //动态规划只与i-1和i-2有关,所以使用滑动数组
        int pre = 0;//相当于保存i-2的值
        int cur = 0;//相当于保存i-1的值
        int n = cost.length;
        for(int i=2; i<=n; i++) {
            int next = Math.min(cur+cost[i-1], pre+cost[i-2]);//保存前面的最小值
            pre = cur;
            cur = next;
        }
        return cur;//cur就相当于最后cost.length的位置
    }

二.买卖股票的最佳时机

1.题目

给定一个数组 prices ,它的第?i 个元素?prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

例子:

输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
? ? ?注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2.图解

3.代码?

public int maxProfit(int[] prices) {
        int minValue = Integer.MAX_VALUE;//买进的最低价格
        int maxPrice = 0;//卖出的最高价格
        for(int i=0; i<prices.length; i++) {
            if(minValue > prices[i]) {
        //保存最低买进的价格
                minValue = prices[i];
//判断是否满足当前的价钱是否和最低价格的差是否比最大利益大
            }else if(prices[i]-minValue > maxPrice) {
                maxPrice = prices[i] - minValue;
            }
        }
        return maxPrice;
    }

三.反转数位

1.题目

给定一个32位整数 num,你可以将一个数位从0变为1。请编写一个程序,找出你能够获得的最长的一串1的长度。

示例 1:

输入: num = 1775(11011101111)
输出: 8

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-bits-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2.图解

3.代码

public int reverseBits(int num) {
        int cur = 0;//表示从前非零位置开始到当前位置1的个数
        int insert = 0;//表示插入1个1的最长1的数位
        int res = 0;
        for(int i=0; i<32; i++) {
            //说明第i位的二进制数非零
            if((num&(1<<i))!= 0){
                cur++;
                insert++;
            }else {
                insert = cur+1;//第二次就会将之前插入的1的最长置为上一个开始0开始的位置的长度
                cur = 0;//说明当前有0,cur重新开始
            }
            //取最大值
            res = Math.max(res, insert);
        }
        return res;
    }

?四.最大正方形

1.题目

给定一个由'0'和'1'组成的2维矩阵,返回该矩阵中最大的由'1'组成的正方形的面积,输入的矩阵是字符形式而非数字形式。

示例:

输入:[[1,0,1,0,0],[1,0,1,1,1],[1,1,1,1,1],[1,0,0,1,0]]

返回值:4

2.图解

3.代码

    public int solve (char[][] matrix) {
        // 判断数组是否符合要求
        if(matrix==null || matrix.length==0) {
            return 0;
        }
        int row = matrix.length;
        int col = matrix[0].length;
        int[][] dp = new int[row][col];
        int len = 0;
        //由于数组下标从零开始,需要i-1参与运算,所以先确定第0行和第0列
        for(int i=0; i<col; i++) {
            if(matrix[0][i] == '1') {
                dp[0][i] = 1;
            }
        }
        for(int i=0; i<row; i++) {
            if(matrix[i][0] == '1') {
                dp[i][0] = 1;
            }
        }
        //在dp数组中存放当前位置所能构成的正方形边长,然后与最大边长进行比较
        for(int i=1; i<row; i++) {
            for(int j=1; j<col; j++) {
                if(matrix[i][j]== '1'){
                    dp[i][j] =
                        Math.min(dp[i-1][j],Math.min(dp[i-1][j-1],dp[i][j-1]))+1;
                    if(dp[i][j]>len) {
                        len = dp[i][j];
                    }
                }
            }
        }
        return len*len;
    }

五.连续子数组的最大乘积

1.题目

输入一个长度为n的整型数组nums,数组中的一个或连续多个整数组成一个子数组。求所有子数组的乘积的最大值。

(1)子数组是连续的,且最小长度为1,最大长度为n

(2)长度为1的子数组,乘积视为其本身,比如[4]的乘积为4

(3)该题的数据保证最大的乘积不会超过int的范围,即不超过2^{32}-1232?1

示例:

输入:[3,2,-1,4]

返回值:6

说明:子数组[3,2]的乘积为6,[3,2,-1,4]的乘积为-24,[4]的乘积为4,故返回6

2.图解

3.代码

 public int maxProduct (int[] nums) {
        // write code here
        int n = nums.length;
        //使用dp数组保存当前元素存在的最大连续乘积
        int[] maxDp = new int[n];
        //使用minDp是因为存在负数,可能之前的最小负数和之后的负数乘积变为最大值
        //minDp保存的是以当前元素结尾的最小连续子数组乘积
        int[] minDp = new int[n];
        maxDp[0] = nums[0];
        minDp[0] = nums[0];
        //保存连续数组的最大值乘积值
        int res = nums[0];
        //求前面连续数组乘积与当前元素乘积,当前元素中的最大最小值
        for(int i=1; i<n; i++) {
            maxDp[i] = Math.max(maxDp[i-1]*nums[i], Math.max(minDp[i-1]*nums[i], nums[i]));
            minDp[i] = Math.min(maxDp[i-1]*nums[i], Math.min(minDp[i-1]*nums[i], nums[i]));
            //maxDp【i】保存是以当前元素结尾的最大连续乘积
            res = Math.max(res, maxDp[i]);
        }
        return res;
    }

?

?

?六.和为k的子数组

1.题目

给你一个整数数组?nums?和一个整数?k?,请你统计并返回?该数组中和为?k?的子数组的个数?

输入:nums = [1,2,3], k = 3
结果为:(1,2) (3)
输出:2

2.图解

?

3.代码

 public int subarraySum(int[] nums, int k) {
        Map<Integer,Integer> map = new HashMap<>();
        //首先在map中存放一个(0,1),这里代表的是从i=0到j的数组和满足条件
        map.put(0,1);
        //统计到当前位置的和
        int sum = 0;
        //最终结果
        int res =0;
        for(int i=0; i<nums.length; i++) {
            sum += nums[i];
            //sum指的是从0到i的数组和,而sum-k指的是当前位置到前面某一位置是否存在和为k的数组和
            if(map.containsKey(sum-k)) {
                //这里说明存在,就将出现的次数加起来
                res += map.get(sum-k);
            }
            //如果到当前位置的数组和已经在之前存在,那么就将之前和的次数加1
            //因为下一次计算到该位置,是从i到j的子数组和
            map.put(sum, map.getOrDefault(sum,0)+1);
        }
        return res;
    }

?

七.和为k的最长连续子数组的长度

1.题目

给定一个无序数组 arr , 其中元素可正、可负、可0。给定一个整数 k ,求 arr 所有连续子数组中累加和为k的最长连续子数组长度。保证至少存在一个合法的连续子数组。[1,2,3]的连续子数组有[1,2],[2,3],[1,2,3] ,但是[1,3]不是。

示例:

输入:[1,-2,1,1,0],0

和为0的数组有【1,-2,1】,【0】,最长的长度为3

返回值:3

2.图解

?

3.代码

 public int maxlenEqualK (int[] arr, int k) {
        // write code here
        int sum = 0;
        //res保存数组最大长度
        int res = 0;
        //map的键保存的是从0到i之间的是数组和,思路也是通过从i到j之间的连续数组和
        Map<Integer,Integer> map = new HashMap<>();
        //当从初始位置开始的时候,且数组下标总比长度少了一个,从-1开始,刚好是连续数组区间的长度
        map.put(0, -1);
        for(int i=0; i<arr.length; i++) {
            sum += arr[i];
            //保存从i到j之间是否存在指定的连续数组和的结果
            int tmp = sum-k;
            if(map.containsKey(tmp)) {
                //每次找到一个满足要求的数组和,就找最大长度
                res = Math.max(res, i-map.get(tmp));
            }
            if(!map.containsKey(sum)) {
                //如果map中没有当前和,就添加
                map.put(sum, i);
            }
        }
        return res;
    }

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-04-28 12:04:59  更:2022-04-28 12:07:05 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 6:20:54-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码