Note: 子序列,可以不连续;子字符串,必须连续。

以下题目按在我看看来的难度从易到难排列:

最大和子序列(Maximum sum subsequence)

这道题纯属娱乐...应该不会有人出这种题吧。方案是贪心法,遇到正数就放入序列。

  1. vector<int> msseq(vector<int> &num) {
  2. vector<int> result;
  3. for(int i : num)
  4. if(i > )
  5. result.push_back(i);
  6. return result;
  7. }

最大和子字符串(Maximum sum substring)

暴力方案TC为O(n^2)。更好的方案为,贪心法, 设i从0到n遍历,用gmax代表全局最大和,cursum代表当前子字符串的和。cursum为负,则放弃之前的子字符串;为正则继续向后加,每遇到一个正数,都更新一次gmax。TC = O(n),SC = O(1)。

  1. double msstr(vector<double> &nums) {
  2. double gmax = , cur = ;
  3. for(int i : nums) {
  4. if(cur > )
  5. cur += i;
  6. else
  7. cur = i;
  8. gmax = max(gmax, cur);
  9. }
  10. return gmax;
  11. }

最长递增子字符串(Longest increasing substring)

暴力方案TC为O(n^2)。更好的方案为,与最大和子字符串一样,贪心法,设i从0到n遍历,用gmax代表全局最长长度,len代表当前递增substring的长度。遇到递增,则len++;遇到非递增,则更新gmax,并重置len为1。TC = O(n),SC = O(1)

  1. int listr(vector<double> &nums) {
  2. if(nums.empty())
  3. return ;
  4. int gmax = , cur = ;
  5. for(int i = ; i < nums.size(); i++) {
  6. if(nums[i] > nums[i - ]) {
  7. cur++;
  8. gmax = max(gmax, cur);
  9. }
  10. else
  11. cur = ;
  12. }
  13. return gmax;
  14. }

最大乘积子字符串(Maximum product subsequence)

基本操作与最大乘积子序列差不多,不过是需要连续。用邻点动态规划,

  1. double mpstr(vector<double> &nums) {
  2. double gmax, cmax, cmin, pmax, pmin;
  3. gmax = cmax = cmin = pmax = pmin = ;
  4. for(double i : nums) {
  5. cmax = max(i, max(pmax * i, pmin * i));
  6. cmin = min(i, min(pmax * i, pmin * i));
  7. pmax = cmax;
  8. pmin = cmin;
  9. gmax = max(gmax, cmax);
  10. }
  11. return gmax;
  12. }

最大乘积子序列(Maximum product subsequence)

这题与最大和子序列差不多吧...如果无负数,遇到大于1的数就放入序列;不过需要考虑正负号,用邻点动态规划,

  1. double mpseq(vector<double> &nums) {
  2. double cmax, cmin, pmax, pmin;
  3. cmax = cmin = pmax = pmin = ;
  4. for(double i : nums) {
  5. cmax = max(max(i, pmax), max(pmax * i, pmin * i));
  6. cmin = min(min(i, pmin), min(pmax * i, pmin * i));
  7. pmax = cmax;
  8. pmin = cmin;
  9. }
  10. return pmax;
  11. }

最长递增子序列(Longest increasing subsequence)

暴力方案TC为O(2^n)。如果用贪心法,分析知道根据第i个包含的信息,无法覆盖前i个数的情况,故第i+1个数的决策没法做;更好的方案为,全局动态规划,用opt[i]记录到i为止最长的且包含 i上字符的最长递增subsequence,opt[i]初始为1,动态转移方程为opt[i] = max(opt[j] + 1, opt[i])。

  1. vector<int> miseq(vector<int> &num) {
  2. vector<int> result;
  3. if(num.empty())
  4. return num;
  5. vector<int> opt(num.size(), ), record(num.size(), -);
  6. for(int i = ; i < num.size(); i++) {
  7. for(int j = ; j < i; j++) {
  8. if(num[i] > num[j] && opt[j] + > opt[i]) {
  9. opt[i] = opt[j] + ;
  10. record[i] = j;
  11. }
  12. }
  13. }
  14. int last = -, gmax = ;
  15. for(int i = ; i < num.size(); i++) {
  16. if(opt[i] > gmax) {
  17. gmax = opt[i];
  18. last = i;
  19. }
  20. }
  21. while(last >= ) {
  22. result.push_back(num[last]);
  23. last = record[last];
  24. }
  25. reverse(result.begin(), result.end());
  26. return result;
  27. }

最长匹配子字符串(Longest common substring) 

暴力方案TC为O(m*n*max(m,n))。更好的方案为,邻点动态规划,用opt[i][j]记录到M的i - 1位置与N的j - 1位置为止,且包含i - 1,j - 1的最长匹配子字符串。将0位置设为岗哨,其中opt[0][j] = opt[i][0] = 0,动态转移方程为opt[i][j] = M[i] == N[j] ? opt[i - 1][j - 1] + 1 : 0。TC = O(m*n),SC = O(m * n),用滚动数组可以压缩到O(m) or O(n)。

  1. string lcstr(string M, string N) {
  2. //找到最长匹配子字符串的长度
  3. int maxlen = INT_MIN, ri = -;
  4. vector<vector<int> > opt(M.size() + , vector<int>(N.size() + , ));
  5. for(int i = ; i <= M.size(); i++)
  6. for(int j = ; j <= N.size(); j++) {
  7. opt[i][j] = M[i - ] == N[j - ] ? opt[i - ][j - ] + : ;
  8. if(opt[i][j] > maxlen) {
  9. maxlen = opt[i][j];
  10. ri = i;
  11. }
  12. }
  13. //将最大值对应的匹配子字符串输出
  14. string result = "";
  15. int starti = ri - maxlen;
  16. for(int i = starti; i < ri; i++)
  17. result += M[i];
  18. return result;
  19. }

最长匹配子序列(Longest common subsequence) 

更好的方案为,与最长匹配子字符串类似,邻点动态规划,用opt[i][j]记录到M的i - 1位置与N的j - 1位置为止,且包含i - 1,j - 1的最长匹配子字符串。将0位置设为岗哨,其中opt[0][j] = opt[i][0] = 0,动态转移方程为opt[i][j] = M[i] == N[j] ? opt[i - 1][j - 1] + 1 : max(opt[i - 1][j], opt[i][j - 1])。TC = O(m*n),SC = O(m*n),滚动数组同样可以压缩到O(m) or O(n)。

  1. //只是找长度很简单...
  2. int lenlcstr(string M, string N) {
  3. //找到最长匹配子字符串的长度
  4. vector<vector<int> > opt(M.size() + , vector<int>(N.size() + , ));
  5. for(int i = ; i <= M.size(); i++)
  6. for(int j = ; j <= N.size(); j++)
  7. opt[i][j] = M[i - ] == N[j - ] ? opt[i - ][j - ] + : max(opt[i - ][j], opt[i][j - ]);
  8. return opt[M.size()][N.size()];
  9. }
  10. //还要返回一个最长匹配字符串
  11. string lcstr(string M, string N) {
  12. //记录路径
  13. vector<vector<int> > track(M.size() + , vector<int>(N.size() + , -));
  14. //找到最长匹配子字符串的长度
  15. vector<vector<int> > opt(M.size() + , vector<int>(N.size() + , ));
  16. for(int i = ; i <= M.size(); i++)
  17. for(int j = ; j <= N.size(); j++) {
  18. if(M[i - ] == N[j - ]) {
  19. opt[i][j] = opt[i - ][j - ] + ;
  20. track[i][j] = ;
  21. }
  22. else {
  23. if(opt[i - ][j] > opt[i][j - ]) {
  24. track[i][j] = ;
  25. opt[i][j] = opt[i - ][j];
  26. }
  27. else {
  28. track[i][j] = ;
  29. opt[i][j] = opt[i][j - ];
  30. }
  31. }
  32. }
  33. int i = int(M.size()), j = int(N.size());
  34. string result = "";
  35. while(track[i][j] > -) {
  36. if(track[i][j] == ) {
  37. result += M[i - ];
  38. i--;
  39. j--;
  40. }
  41. else if(track[i][j] == )
  42. i--;
  43. else
  44. j--;
  45. }
  46. reverse(result.begin(), result.end());
  47. return result;
  48. }

编辑距离(Edit distance)

更好的方案,与LCS类似,邻点动态规划

  1. int edist(string s1, string s2) {
  2. int m = int(s1.length()), n = int(s2.length());
  3. vector<vector<int> > opt(m + , vector<int> (n + , ));
  4. for(int i = ; i <= m; i++)
  5. opt[i][] = i;
  6. for(int j = ; j <= n; j++)
  7. opt[][j] = j;
  8. for(int i = ; i <= m; i++)
  9. for(int j = ; j <= n; j++) {
  10. opt[i][j] = min(min(opt[i - ][j], opt[i][j - ]), opt[i - ][j - ]) + ;
  11. if(s1[i - ] == s2[j - ])
  12. opt[i][j] = min(opt[i][j], opt[i - ][j - ]);
  13. }
  14. return opt[m][n];
  15. }

最长无重复子字符串(Longest substring with no duplicate characters)

用一个unordered_set<char>里存已有的char,遇到加入一个新的char,则在set里找,如果没找到,则加入set,并且count++;如果找到了,则在substring的循环弹出,更新set,并循环count--,直到弹出新加入的char的重复字符。

[经典] 最X(长 | 大和 | 大积)Y(子序列 | 子字符串)的更多相关文章

  1. 《剑指offer》第四十八题(最长不含重复字符的子字符串)

    // 面试题48:最长不含重复字符的子字符串 // 题目:请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子 // 字符串的长度.假设字符串中只包含从'a'到'z'的字符. #inclu ...

  2. 剑指offer-面试题48-最长不含重复字符的子字符串-动态规划

    /* 题目: 最长不含重复字符的子字符串. */ /* 思路: f(i) = f(i-1) + 1,(未出现过当前字符,distance > f(i-1) distance,当前字符和上一次出现 ...

  3. 剑指 Offer 48. 最长不含重复字符的子字符串 + 动态规划 + 哈希表 + 双指针 + 滑动窗口

    剑指 Offer 48. 最长不含重复字符的子字符串 Offer_48 题目详情 解法分析 解法一:动态规划+哈希表 package com.walegarrett.offer; /** * @Aut ...

  4. 剑指offer面试题48: 最长不含重复字符的子字符串

    Given a string, find the length of the longest substring without repeating characters.(请从子字符串中找出一个最长 ...

  5. 【Java】 剑指offer(48) 最长不含重复字符的子字符串

    本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字 ...

  6. 【Offer】[48] 【最长不含重复字符的子字符串】

    题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度.假设字符串中只包含'a'~'z'的字符.例如,在字符串&q ...

  7. 剑指offer——50最长不含重复字符和子字符串

    题目: 请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度.假设字符串中只包含’a~z”的字符.例如,在字符串“arabcacfr"中,最长的不含重复字符的子字符串 ...

  8. 每日一题 - 剑指 Offer 48. 最长不含重复字符的子字符串

    题目信息 时间: 2019-07-02 题目链接:Leetcode tag: 动态规划 哈希表 难易程度:中等 题目描述: 请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度 ...

  9. 剑指 Offer 48. 最长不含重复字符的子字符串

    题目描述 请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度. 示例1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 & ...

随机推荐

  1. Android开发中用友盟做分享的一些坑

    仅限于用5.1.4版本的 按照友盟分享的API在自己的代码中修改: 1.微信分享需要打包APK文件,数字签名与微信开发申请的要一致 2.此name中属性不能修改 value为友盟的申请的appkey ...

  2. ST3破解命令

      open terminal and input it!   printf '\x39' | dd seek=$((0x6f35)) conv=notrunc bs=1 of=/Applicatio ...

  3. Eclipse中看java源代码

    如何在Eclipse sdk中查看jar源代码如:*.jar 1.点 “window”-> "Preferences" -> "Java" -> ...

  4. 如何清除xcode里面的mobileprovision文件

    通过终端进行删除 首先cd到目录”~/Library/MobileDevice/Provisioning\ Profiles” cd ~/Library/MobileDevice/Provisioni ...

  5. 【BZOJ1036】【LCT版】树的统计Count

    Description 一 棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. ...

  6. fish code

    <embed width="272" height="180" type="application/x-shockwave-flash" ...

  7. YII 小部件 解决多选按钮和单选按钮不在同一水平上 'separator'=>'&nbsp;'

    主要是添加separator属性(这里)$hoddy,$sex在控制器里面定义的数组,然后render传过来的 <td>          <?php echo $form-> ...

  8. jQuery 自动完成文本框

    jQuery自动完成插件开源软件 http://www.oschina.net/project/tag/329/jquery-autocomplete jQuery TextExt http://te ...

  9. 高级停靠(Dock)技术的实现

    高级停靠(Dock)技术的实现 介绍 所谓停靠就是可以用鼠标拖动窗体或者控件,并将其从一个父窗体移出或者移动到另一个父窗体上,可以按水平,垂直方向整齐排列, 并且可以停靠在分页控制组件上.下面的示意图 ...

  10. Sass学习

    1.1下载地址: http://rubyinstaller.org/downloads 2.1 安装 SASS是Ruby语言写的,但是两者的语法没有关系.不懂Ruby,照样使用.只是必须先安装Ruby ...