【问题标题】:Sub-sequence of Vowels元音的子序列
【发布时间】:2019-01-14 05:45:09
【问题描述】:

我正在练习面试,在一个网站上遇到了这个问题:

字符串S 的神奇子序列是S 的子序列 按顺序包含所有五个元音。查找字符串S 的最大神奇子序列的长度。

例如,如果S = aeeiooua,那么aeiouaeeioou 是神奇的子序列 但aeioaeeioua 不是。

我是动态编程的初学者,我发现很难为此想出一个递归公式。

【问题讨论】:

标签: algorithm dynamic-programming


【解决方案1】:

我是用迭代方法而不是递归方法来做的。我开始构建类似于 LIS(最长递增子序列)的解决方案,然后将其优化到 O(n)。

#include<iostream>
#include<string>
#include<vector>
using namespace std;

string vowel = "aeiou";

int vpos(char c)
{
    for (int i = 0; i < 5; ++i)
        if (c == vowel[i])
            return i;
    return -1;
}

int magical(string s)
{
    int l = s.length();
    int previndex[5] = {-1, -1, -1, -1, -1};    // for each vowel
    vector<int> len (l, 0);
    int i = 0, maxlen = 0;

    // finding first 'a'
    while (s[i] != 'a')
    {
        ++i;
        if (i == l)
            return 0;
    }

    previndex[0] = i;       //prev index of 'a'
    len[i] = 1;

    for ( ++i; i < l; ++i)
    {
        if (vpos(s[i]) >= 0)    // a vowel
        {
            /* Need to append to longest subsequence on its left, only for this vowel (for any vowels) and 
             * its previous vowel (if it is not 'a')
                This important observation makes it O(n) -- differnet from typical LIS
            */
            if (previndex[vpos(s[i])] >= 0)
                len[i] = 1+len[previndex[vpos(s[i])]];

            previndex[vpos(s[i])] = i;

            if (s[i] != 'a')
            {
                if (previndex[vpos(s[i])-1] >= 0)
                    len[i] = max(len[i], 1+len[previndex[vpos(s[i])-1]]);
            }

            maxlen = max(maxlen, len[i]);
        }
    }
    return maxlen;
}

int main()
{
    string s = "aaejkioou";
    cout << magical(s);
    return 0;
}

【讨论】:

    【解决方案2】:

    O(输入字符串长度)运行时 导入 java.util.*;

    public class Main {
        /*
            algo:
            keep map of runningLongestSubsequence that ends in each letter. loop through String s. for each char, try appending
            to runningLongestSubsequence for that char, as well as to runningLongestSubsequence for preceding char.
            update map with whichever results in longer subsequence.
    
            for String s = "ieaeiouiaooeeeaaeiou", final map is:
            terminal letter in longest running subsequence-> longest running subsequence
            a -> aaaa
            e -> aeeeee
            i -> aeeeeei
            o -> aeeeeeio
            u -> aeeeeeiou
    
            naming:
            precCharMap - precedingCharMap
            runningLongestSubMap - runningLongestSubsequenceMap
         */
    
        public static int longestSubsequence(String s) {
    
            if (s.length() <= 0) throw new IllegalArgumentException();
    
            Map<Character, Character> precCharMap = new HashMap<>();
            precCharMap.put('u', 'o');
            precCharMap.put('o', 'i');
            precCharMap.put('i', 'e');
            precCharMap.put('e', 'a');
    
            Map<Character, String> runningLongestSubMap = new HashMap<>();
    
            for (char currChar : s.toCharArray()) {
                //get longest subs
                String currCharLongestSub;
                String precCharLongestSub = null;
                if (currChar == 'a') {
                    currCharLongestSub = runningLongestSubMap.getOrDefault(currChar, "");
                } else {
                    currCharLongestSub = runningLongestSubMap.get(currChar);
                    char precChar = precCharMap.get(currChar);
                    precCharLongestSub = runningLongestSubMap.get(precChar);
                }
    
                //update running longest subsequence map
                if (precCharLongestSub == null && currCharLongestSub != null) {
                    updateRunningLongestSubMap(currCharLongestSub, currChar, runningLongestSubMap);
                } else if (currCharLongestSub == null && precCharLongestSub != null) {
                    updateRunningLongestSubMap(precCharLongestSub, currChar, runningLongestSubMap);
                } else if (currCharLongestSub != null && precCharLongestSub != null) {
                    //pick longer
                    if (currCharLongestSub.length() < precCharLongestSub.length()) {
                        updateRunningLongestSubMap(precCharLongestSub, currChar, runningLongestSubMap);
                    } else {
                        updateRunningLongestSubMap(currCharLongestSub, currChar, runningLongestSubMap);
                    }
                }
            }
    
            if (runningLongestSubMap.get('u') == null) {
                return 0;
            }
            return runningLongestSubMap.get('u').length();
        }
    
        private static void updateRunningLongestSubMap(String longestSub, char currChar,
                                                       Map<Character, String> runningLongestSubMap) {
            String currCharLongestSub = longestSub + currChar;
            runningLongestSubMap.put(currChar, currCharLongestSub);
        }
    
        public static void main(String[] args) {
            //String s = "aeeiooua"; //7
            //String s = "aeiaaioooaauuaeiou"; //10
            String s = "ieaeiouiaooeeeaaeiou"; //9
            //String s = "ieaeou"; //0
            //String s = "ieaeoooo"; //0
            //String s = "aeiou"; //5
            //if u have String s beginning in "ao", it'll do nothing with o and 
            //continue on to index 2.
    
            System.out.println(longestSubsequence(s));
        }
    }
    

    【讨论】:

      【解决方案3】:
      #include <iostream>
      #include<string>
      #include<cstring>
      
      using namespace std;
      unsigned int getcount(string a, unsigned int l,unsigned int r );
      int main()
      {    
          std::string a("aaaaaeeeeaaaaiiioooeeeeuuuuuuiiiiiaaaaaaoo"
                       "oooeeeeiiioooouuuu");
          //std::string a("aaaaaeeeeaaaaiiioooeeeeuuuuuuiiiiiaaaaaaoooooeeeeiiioooo"); 
         //std::string a("aaaaaeeeeaaaaiiioooeeeeiiiiiaaaaaaoooooeeeeiiioooo"); //sol0
        //std::string a{"aeiou"};
        unsigned int len = a.length();
        unsigned int i=0,cnt =0,countmax =0;
        bool newstring = true;
        while(i<len)
        {
            if(a.at(i) == 'a' && newstring == true) 
            {
                newstring = false;
                cnt = getcount(a,i,len);
                if(cnt > countmax) 
                {
                   countmax = cnt;
                   cnt = 0;
                }
              } 
              else if(a.at(i)!='a')
              {
                  newstring = true;
              }
              i++;
          }
          cout<<countmax;
          return 0;
      }
      
      unsigned int getcount(string a, unsigned int l,unsigned int r )
      {
          std::string b("aeiou");
          unsigned int seq=0,cnt =0;
          unsigned int current =l;
          bool compstr = false;
          while(current<r)
          {
              if(a.at(current) == b.at(seq)) 
              {
                  cnt++;
              }
              else if((seq <= (b.size()-2)) && (a.at(current) == b.at(seq+1)))
              {
                  seq++; 
                  cnt++;
                  if (seq == 4) 
                      compstr =true;
              }
              current++;
          }
          if (compstr == true) 
              return cnt;
         return 0;
      }
      

      【讨论】:

      • 我认为这可能不是最好的解决方案,我正在寻找更好的解决方案
      【解决方案4】:

      您可以在这里使用递归方法(这应该适用于最大 int 的字符串长度(可以使用轻松记忆)

      public class LMV {
      
      static final int NOT_POSSIBLE = -1000000000;
      // if out put is this i.e soln not possible 
      
      
      static int longestSubsequence(String s, char[] c) {
      
          //exit conditions
          if(s.length() ==0 || c.length ==0){
              return 0;
          }
      
          if(s.length() < c.length){
              return NOT_POSSIBLE;
          }
      
          if(s.length() == c.length){
              for(int i=0; i<s.length(); i++){
                  if(s.charAt(i) !=c [i]){
                      return NOT_POSSIBLE;
                  }
              }
              return s.length();
          }
      
          if(s.charAt(0) < c[0]){
              // ignore, go ahead with next item
              return longestSubsequence(s.substring(1), c);
          } else if (s.charAt(0) == c[0]){
              // <case 1> include item and start search for next item in chars
              // <case 2> include but search for same item again in chars
              // <case 3> don't include item
      
              return Math.max(
                      Math.max(  ( 1+longestSubsequence(s.substring(1), Arrays.copyOfRange(c, 1, c.length) ) ),
                                  ( 1+longestSubsequence(s.substring(1), c ) ) ),
                      ( longestSubsequence(s.substring(1), c )) );
          } else {
              //ignore
              return longestSubsequence(s.substring(1), c);
          }
      }
      
      
      
      public static void main(String[] args) {
      
          char[] chars = {'a', 'e', 'i', 'o', 'u'};
      
          String s1 = "aeio";
          String s2 = "aaeeieou";
          String s3 = "aaeeeieiioiiouu";
      
          System.out.println(longestSubsequence(s1, chars));
          System.out.println(longestSubsequence(s2, chars));
          System.out.println(longestSubsequence(s3, chars));
      
      }
      

      }

      【讨论】:

        【解决方案5】:
        int func( char *p)
        {
            char *temp = p;
            char ae[] = {'a','e','i','o','u'};
        
            int size = strlen(p), i = 0;
            int chari = 0, count_aeiou=0;
            for (i=0;i<=size; i++){
                if (temp[i] == ae[chari]) {
                    count_aeiou++;
                }
                else if ( temp[i] == ae[chari+1]) {
                    count_aeiou++;
                    chari++;
                }
            }
            if (chari == 4 ) {
                printf ("Final count : %d ", count_aeiou);
            } else {
                count_aeiou = 0;
            }
            return count_aeiou;
        }
        

        根据hackerrank挑战重新计算元音计数的解决方案。

        【讨论】:

          【解决方案6】:
          int findsubwithcontinuousvowel(string str){
              int curr=0;
              int start=0,len=0,maxlen=0,i=0;
              for(i=0;i<str.size();i++){
                  if(str[i]=='u' && (current[curr]=='u' ||  (curr+1<5 && current[curr+1]=='u'))){
                     //len++;
                     maxlen=max(len+1,maxlen);
                  }
          
                  if(str[i]==current[curr]){
                      len++;
                  }
                  else if(curr+1<5 && str[i]==current[curr+1]){
                      len++;
                      curr++;
                  }
                  else{
                      len=0;
                      curr=0;
                      if(str[i]=='a'){
                          len=1;
                      }
                  }
              }
              return maxlen;
          }
          

          【讨论】:

            【解决方案7】:

            检查isInSequence中的元音是否按顺序可用,并在processor上处理结果。

            public class one {
            
            private char[] chars = {'a','e','i','o','u'};
            private int a = 0;
            
            private boolean isInSequence(char c){
                // check if char is repeating
                if (c == chars[a]){
                    return true;
                }
                // if vowels are in sequence and just passed by 'a' and so on...
                if (c == 'e' && a == 0){
                    a++;
                    return true;
                }
                if (c == 'i' && a == 1){
                    a++;
                    return true;
                }
                if (c == 'o' && a == 2){
                    a++;
                    return true;
                }
                if (c == 'u' && a == 3){
                    a++;
                    return true;
                }
                return false;
            }
            
            private char[] processor(char[] arr){
                int length = arr.length-1;
                int start = 0;
                // In case if all chars are vowels, keeping length == arr
                char array[] = new char[length];
            
                for (char a : arr){
                    if (isInSequence(a)){
                        array[start] = a;
                        start++;
                    }
                }
                return array;
            }
            
            public static void main(String args[]){
                char[] arr = {'m','a','e','l','x','o','i','o','u','a'};
                one o = new one();
                System.out.print(o.processor(arr));
             }
            }
            

            【讨论】:

              【解决方案8】:
              #include <bits/stdc++.h>
              #define ios ios::sync_with_stdio(NULL);cin.tie(NULL);cout.tie(NULL);
              #define ll unsigned long long
              using namespace std;
              
              int main() {
                  // your code goes here
               ios
              string s;
              cin>>s;
              int n=s.length();
              int dp[n+1][5]={0};
              for(int i=1;i<=n;i++)
              {
                  if(s[i-1]=='a')
                  {
                      dp[i][0]=1+dp[i-1][0];
                      dp[i][1]=dp[i-1][1];
                      dp[i][2]=dp[i-1][2];
                      dp[i][3]=dp[i-1][3];
                      dp[i][4]=dp[i-1][4];
                  }
                  else if(s[i-1]=='e')
                  {dp[i][0]=dp[i-1][0];
                  if(dp[i-1][0]>0)
                      {dp[i][1]=1+max(dp[i-1][1],dp[i-1][0]);}
                      else
                      dp[i-1][1]=0;
                      dp[i][2]=dp[i-1][2];
                      dp[i][3]=dp[i-1][3];
                      dp[i][4]=dp[i-1][4];
                  }
                   else if(s[i-1]=='i')
                  {dp[i][0]=dp[i-1][0];
                  if(dp[i-1][1]>0)
                      {dp[i][2]=1+max(dp[i-1][1],dp[i-1][2]);}
                      else
                      dp[i-1][2]=0;
                      dp[i][1]=dp[i-1][1];
                      dp[i][3]=dp[i-1][3];
                      dp[i][4]=dp[i-1][4];
                  }
                  else if(s[i-1]=='o')
                  {dp[i][0]=dp[i-1][0];
                  if(dp[i-1][2]>0)
                      {dp[i][3]=1+max(dp[i-1][3],dp[i-1][2]);}
                      else
                      dp[i-1][3]=0;
                      dp[i][2]=dp[i-1][2];
                      dp[i][1]=dp[i-1][1];
                      dp[i][4]=dp[i-1][4];
                  }
                  else if(s[i-1]=='u')
                  {dp[i][0]=dp[i-1][0];
                     if(dp[i-1][3]>0)
                      {dp[i][4]=1+max(dp[i-1][4],dp[i-1][3]);}
                      else
                      dp[i-1][4]=0;
                      dp[i][1]=dp[i-1][1];
                      dp[i][3]=dp[i-1][3];
                      dp[i][2]=dp[i-1][2];
                  }
                  else
                  {
                      dp[i][0]=dp[i-1][0];
                      dp[i][1]=dp[i-1][1];
                      dp[i][2]=dp[i-1][2];
                      dp[i][3]=dp[i-1][3];
                      dp[i][4]=dp[i-1][4];
                  }
              
              
              }
              cout<<dp[n][4];
              
              
              return 0;
              }
              

              【讨论】:

                猜你喜欢
                • 2019-05-28
                • 2011-05-05
                • 1970-01-01
                • 2015-10-06
                • 1970-01-01
                • 1970-01-01
                • 2018-12-14
                • 2014-10-31
                • 1970-01-01
                相关资源
                最近更新 更多