leetcode/nowcoder-huawei-6-双指针

文章介绍了使用双指针解决LeetCode中的两道题目:674.最长连续递增序列和17.最长回文子串。在最长连续递增序列问题中,通过比较相邻元素调整最大长度和结束位置。而在最长回文子串问题中,通过反转子串并对比来寻找符合条件的子串。此外,还提出了28.最小覆盖子串的问题,目标是在给定字符串中找到包含另一个字符串所有字符的最短子串。
摘要由CSDN通过智能技术生成

6.双指针

leecode 674.最长连续递增序列

  1. 描述

    给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。
    连续递增的子序列 可以由两个下标 l 和 r(l < r)确定,如果对于每个 l <= i < r,都有 nums[i] < nums[i + 1] ,那么子序列 [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]] 就是连续递增子序列。 
    
    示例 1:
    输入:nums = [1,3,5,4,7]
    输出:3
    解释:最长连续递增序列是 [1,3,5], 长度为3。
    尽管 [1,3,5,7] 也是升序的子序列, 但它不是连续的,因为 5 和 7 在原数组里被 4 隔开。 
    示例 2:
    输入:nums = [2,2,2,2,2]
    输出:1
    解释:最长连续递增序列是 [2], 长度为1。 
    
    提示:
    1 <= nums.length <= 104
    -109 <= nums[i] <= 109
    
  2. 思路

    指向最大的数字,数字变小时候更新长度值,否则增加

  3. 代码

    #include <iostream>
    using namespace std;
    #include <vector>
    
    class Solution {
    public:
        int findLengthOfLCIS(vector<int>& nums) {
            if (nums.size() == 0)   return 0;
            int m = 1;
            int n = 1;
            int e = 0;
            for (int i = 1; i < nums.size(); i++) {
                if (nums[i] <= nums[e]) {
                    m = max(m, n);
                    n = 1;
                } else {
                    n++;
                }
                e = i;
            }
            m = max(m, n);
            return m;
        }
    };
    
    int main() {
        vector<int> nums = {1,3,5,7};
        Solution sol;
        cout << sol.findLengthOfLCIS(nums) << endl;
        return 0;
    }
    

NC17. 最长回文子串

  1. 描述

    对于长度为n的一个字符串A(仅包含数字,大小写英文字母),请设计一个高效算法,计算其中最长回文子串的长度。
    
    数据范围:1≤n≤1000
    要求:空间复杂度O(1),时间复杂度O(n^2)
    进阶:  空间复杂度O(n),时间复杂度O(n)
    
    示例1
    输入:
    	"ababc"
    返回值:
    	3
    说明:
    最长的回文子串为"aba"与"bab",长度都为3
    
    示例2
    输入:
    	"abbba"
    返回值:
    	5
    
    示例3
    输入:
    	"b"
    返回值:
    	1
    
  2. 描述

    确定子串长度,子串和反转子串对比,对比相等直接返回长度

  3. 代码

    #include <iostream>
    using namespace std;
    #include <algorithm>
    
    class Solution {
    public:
        int getLongestPalindrome(string str) {
            if(str.size() <= 1) return  str.size();
            int len = str.size();
            string revStr;
            while(len) {
                for(int i = 0; i <= str.size() - len; i++) {
                    revStr.assign(str.substr(i,len));
                    reverse(revStr.begin(),revStr.end());
                    if(str.substr(i,len).compare(revStr) == 0)  return len;
                }
                len--;
            }
            return len;
        }
    };
    
    int main() {
        string str;
        cin >> str;
        Solution sol;
        cout << sol.getLongestPalindrome(str) << endl;
        return 0;
    }
    

NC28. 最小覆盖子串

  1. 描述

    给出两个字符串 s 和 t,要求在 s 中找出最短的包含 t 中所有字符的连续子串。
    
    数据范围:0≤∣S∣,∣T∣≤10000,保证s和t字符串中仅包含大小写英文字母
    要求:进阶:空间复杂度O(n) , 时间复杂度O(n)
    例如:S="XDOYEZODEYXNZ" T="XYZ"
    找出的最短子串为"YXNZ".
    注意:
    如果 s 中没有包含 t 中所有字符的子串,返回空字符串 “”;
    满足条件的子串可能有很多,但是题目保证满足条件的最短的子串唯一。
    
    示例1
    输入:
    	"XDOYEZODEYXNZ","XYZ"
    返回值:
    	"YXNZ"
    示例2
    输入:
    	"abcAbA","AA"
    返回值:
    	"AbA"
    
  2. 思路

    • 记录所有t包含的字符
    • [low,high]记录范围,外层循环增加high,同时增加len记录包含t的字符个数
    • [low, high]有所有t字符时,进入子循环
    • 记录最短子串,并不断增加下界。如果下界指向元素存在于t中,len–
  3. 代码

    #include <iostream>
    using namespace std;
    #include <algorithm>
    #include <map>
    
    class Solution {
    public:
    
        string minWindow(string s, string t) {
            int count[256] = {0};
            for(auto ch:t)
                count[ch]++;
            int minLen = s.size();
            //len记录包含t中字符的个数
            int low = 0, high = 0, len = 0;
            string res;
            for (;high < s.size(); high++) {
                //右移上界,如果包含t元素,len++
                if(count[s[high]]-- > 0)  len++;
                // count[s[high]]--;
                //包含所有t中的字符,进入子循环
                while (len == t.size()) {
                    if(high - low + 1 <= minLen) {
                        minLen = high - low + 1;
                        res = s.substr(low, minLen);
                        cout << len <<"     "<< res << endl;
                    }
                    //移动下界
                    printf(">>>>  %c  %d\n",s[low],count[s[low]]);
                    if(++count[s[low++]] > 0){
                        len--;
                    }
                }
                
            }
            return res;
        }
    };
    
    int main() {
        string S,T;
        cin >> S;
        cin >> T; 
        Solution sol;
        cout << sol.minWindow(S,T) << endl;
        return 0;
    }
    
### 回答1: 好的,我来用中文回复这个链接:https://leetcode-cn.com/tag/dynamic-programming/ 这个链接是 LeetCode 上关于动态规划的题目集合。动态规划是一种常用的算法思想,可以用来解决很多实际问题,比如最长公共子序列、背包问题、最短路径等等。在 LeetCode 上,动态规划也是一个非常重要的题型,很多题目都需要用到动态规划的思想来解决。 这个链接里包含了很多关于动态规划的题目,按照难度从简单到困难排列。每个题目都有详细的题目描述、输入输出样例、题目解析和代码实现等内容,非常适合想要学习动态规划算法的人来练习和提高自己的能力。 总之,这个链接是一个非常好的学习动态规划算法的资源,建议大家多多利用。 ### 回答2: 动态规划是一种算法思想,通常用于优化具有重叠子问题和最优子结构性质的问题。由于其成熟的数学理论和强大的实用效果,动态规划在计算机科学、数学、经济学、管理学等领域均有重要应用。 在计算机科学领域,动态规划常用于解决最优化问题,如背包问题、图像处理、语音识别、自然语言处理等。同时,在计算机网络和分布式系统中,动态规划也广泛应用于各种优化算法中,如链路优化、路由算法、网络流量控制等。 对于算法领域的程序员而言,动态规划是一种必要的技能和知识点。在LeetCode这样的程序员平台上,题目分类和标签设置十分细致和方便,方便程序员查找并深入学习不同类型的算法LeetCode的动态规划标签下的题目涵盖了各种难度级别和场景的问题。从简单的斐波那契数列、迷宫问题到可以用于实际应用的背包问题、最长公共子序列等,难度不断递进且话题丰富,有助于开发人员掌握动态规划的实际应用技能和抽象思维模式。 因此,深入LeetCode动态规划分类下的题目学习和练习,对于程序员的职业发展和技能提升有着重要的意义。 ### 回答3: 动态规划是一种常见的算法思想,它通过将问题拆分成子问题的方式进行求解。在LeetCode中,动态规划标签涵盖了众多经典和优美的算法问题,例如斐波那契数列、矩阵链乘法、背包问题等。 动态规划的核心思想是“记忆化搜索”,即将中间状态保存下来,避免重复计算。通常情况下,我们会使用一张二维表来记录状态转移过程中的中间值,例如动态规划求解斐波那契数列问题时,就可以定义一个二维数组f[i][j],代表第i项斐波那契数列中,第j个元素的值。 在LeetCode中,动态规划标签下有众多难度不同的问题。例如,经典的“爬楼梯”问题,要求我们计算到n级楼梯的方案数。这个问题的解法非常简单,只需要维护一个长度为n的数组,记录到达每一级楼梯的方案数即可。类似的问题还有“零钱兑换”、“乘积最大子数组”、“通配符匹配”等,它们都采用了类似的动态规划思想,通过拆分问题、保存中间状态来求解问题。 需要注意的是,动态规划算法并不是万能的,它虽然可以处理众多经典问题,但在某些场景下并不适用。例如,某些问题的状态转移过程比较复杂,或者状态转移方程中存在多个参数,这些情况下使用动态规划算法可能会变得比较麻烦。此外,动态规划算法也存在一些常见误区,例如错用贪心思想、未考虑边界情况等。 总之,掌握动态规划算法对于LeetCode的学习和解题都非常重要。除了刷题以外,我们还可以通过阅读经典的动态规划书籍,例如《算法竞赛进阶指南》、《算法与数据结构基础》等,来深入理解这种算法思想。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值