动态规划面试常见的三道题总结

1.乘积连续最大子数组

这道题的关键是转换思想,将maxF[i]看作表示以第 i 个元素结尾的乘积最大子数组的乘积,下次每次要求新的maxF[i+1]时可以去前面的maxF数组里面找当前最大值是什么。题目要求连续乘积最大,好就好在连续上,因为要求连续,我们就可以只看上一个的值了,无非是上一个最大值乘以当前值会不会大于当前值,在二者之中取最大即可。有的题不要求连续,比如后面的最长递增子序列,最长公共子序列这道题,那就要从头看一遍我们的动规数组了找出所有存储的之前状态里符合我们要求的值,这就是两层for循环。这也是为什么有的动态规划是一层for循环,有的动态规划题是两层for循环的解释。这种解释应该是比较好理解的那一类了。

如果这道题说明数组nums全为正数的话,应该是一道简单题。但是因为数组里有负数,负负得正的情况必须考虑,所以同时更新一个minF,第一次写确实想不到这种解法,甚至看都看不太明白。minF不多做解释了,多看几遍,多写几遍,写这些破题次数多了时间长了之后,能有一种好像就是本该如此的想法时,觉得正常人就是这该是这么想的时候,对动态规划这种思想就可以说基本掌握了。

 此题有一个注意点是maxF[0]=nums[0];minF[0]=nums[0];初始值要置为nums[0]

public:
    int maxProduct(vector<int>& nums) {
        int n = nums.size();
        vector<int> maxF(n), minF(n);
        maxF[0]=nums[0];
        minF[0]=nums[0];
        for (int i = 1; i < n; ++i) {
            maxF[i] = max(nums[i], max(maxF[i - 1] * nums[i], minF[i - 1] * nums[i]));
            minF[i] = min(nums[i], min(maxF[i - 1] * nums[i], minF[i - 1] * nums[i]));
        }
        return *max_element(maxF.begin(), maxF.end());
    }
};

2.最长递增子序列

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列

这道题是不要求连续,就有点麻烦了,应该知道起码要两层for才能解决了.

值得注意的是第一层for循环每次要把dp[i]置1,然后第二层for循环有一个逆向的想法,以i为标准卡住,遍历的是从j到i的所有元素。在第二层循环里dp[i] = max(dp[i], dp[j] + 1)这句话代码里i是不动的,dp[i]是变化的。有一点从后往前看的意思,不是一般逻辑上for循环从前往后遍历就行了。这破题是真烦,第一次写很难写的出来。


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

第三题更是重量级,脑子没转过来的话很难理清思路。最长公共子序列

给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0 。

一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。

  • 例如,"ace" 是 "abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。

两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。

所有动态规划的关键是dp数组的意义,贯穿整题思路都是这一件事,这题也一样,dp数组的意义是,长度从0到i-1的text1和长度为从0到j-1的text2的最长公共子序列长度为dp[i][j]

    int longestCommonSubsequence(string text1, string text2) {
        vector<vector<int>>dp(text1.size()+1,vector<int>(text2.size()+1,0));
        //dp数组的意义是,长度从0到i-1的text1和长度为从0到j-1的text2的最长公共子序列长度为dp[i][j]
       
        for(int i=1;i<=text1.size();i++)
        {
            for(int j=1;j<=text2.size();j++)
            {
                if(text1[i-1]==text2[j-1])
                {
                    dp[i][j]=dp[i-1][j-1]+1;
                }
                else
                {
                    dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
                }


            }
        }
        return dp[text1.size()][text2.size()];

    }

当text1[i-1]==text2[j-1]相等时,很容易理解直接让dp[i-1][j-1]加1就行了,但是为什么当ext1[i-1]!=text2[j-1]不相等时,dp数组的状态转移是取max(dp[i-1][j],dp[i][j-1])的最大值。这一点是当初卡住我思路的一个点。下图画的就很好,很直观

当最新的字符不相等的时候,比如f和e,直观的思路是:既然已经确定它们不相等了,肯定是退回一个字符,然后去从之前的dp数组存储的中间状态取值,一定是只退text1和text2其中一个的,容易的思维误区是两个字符串要回退一个字符。

  • 24
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
回答: Redis常见面试题包括但不限于以下几个方面: 1. Redis的特点和优势:Redis是一个基于内存的NoSQL数据库,支持多种数据结构和丰富的操作,具有高性能、高并发、持久化、主从同步等特点。 2. Redis的数据结构:Redis支持多种数据结构,包括字符串(string)、列表(list)、集合(set)、有序集合(sorted set)和哈希(hash),每种数据结构都有相应的操作方法。 3. Redis的持久化方式:Redis有两种持久化方式,分别是RDB(Redis Database)和AOF(Append Only File)。RDB是将内存中的数据定期保存到磁盘上,而AOF是将每个写操作追加到文件末尾。 4. Redis的使用场景:Redis可以用于缓存、会话管理、计数器、排行榜、消息队列等多种场景。它的高性能和丰富的数据结构使得它在处理大量并发请求和快速读写的场景下表现出色。 5. Redis的并发访问:Redis采用单进程单线程模式,通过队列模式将并发访问变为串行访问。在Jedis客户端对Redis进行并发访问时可能会出现连接超时、数据转换错误、阻塞等问,需要注意处理这些并发访问的情况。 综上所述,Redis是一个功能强大的基于内存的NoSQL数据库,具有多种数据结构和丰富的操作方法,适用于多种场景。在面试中,了解Redis的特点、数据结构、持久化方式、使用场景和并发访问等方面的知识是非常重要的。 #### 引用[.reference_title] - *1* *2* [redis面试题总结(附答案)](https://blog.csdn.net/guorui_java/article/details/117194603)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [精选 21道 Redis 最常问面试题!收藏一波 !](https://blog.csdn.net/w915209092/article/details/126035419)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值