来自字符串数组的所有排列的最长运行序列

时间:2012-12-19 11:48:40

标签: arrays string algorithm data-structures permutation


从最近对亚马逊的采访中,我发现了以下问题。我无法找到解决问题的有效方法 问题如下:
给定一个字符串数组,您需要在数组中所有可能的字符串排列中找到字符中运行时间最长的序列。

输入:
AB

AAC
输出:
一,3

注意:从输入和输出设置来看,我认为不需要对各个字符串进行排列。

如果有人能提供帮助,真的很感激。感谢。

5 个答案:

答案 0 :(得分:2)

可爱的问题。这么多角落案件。我猜这个采访问题的重点在于看看你出现了多少个角落。

我希望我没有错过任何一个。

字符序列基本上有两种方法可以解决这个问题:

1)它是一个内部字符序列(例如adddddddddddddddddb

2)它是后缀的连接,只包含该字符的整个字符串集合和前缀。在这种情况下,不能多次使用任何字符串,包括字符是后缀相同字符串的前缀的情况。 (为避免重新使用同源字符串,后缀和前缀必须严格;即不是整个字符串。)

案例1很简单。我们只记得单个字符和序列长度,以及当前字符和序列长度。当我们读入字符串时,如果当前字符/序列长度超过最大值,我们将替换最大值。我们不需要担心它与案例2的计算冲突,因为它不会影响结果。

案例2还有很多工作要做。对于每个角色,我们需要保留一些数据。我们可以使用固定大小的数组,字母表中每个字符一个条目,如果字母表很小,或者我们可以使用字符的哈希表。两者平均为O(1);由于我们要处理的字符数不能大于所有字符串中的字符总数,因此哈希表的大小要求可以被认为是O(N)。 (实际上,它受字母大小的限制,因此就像固定大小的数组一样,存储要求在技术上是O(1),但在Unicode的情况下,例如,常量相当大。 )

现在,我们需要哪些数据?只是重复单个字符的字符串很容易;我们需要这些字符串的总长度。因此,每次我们找到这样的字符串时,我们都可以将其长度添加到每个字符数据中条目的总长度成员中。

对于(严格)后缀和前缀,似乎我们只需要为每个后缀和前缀保持最大长度。但是,如果我们遇到一个字符串,其前缀和后缀序列是相同的字符,并且这两个序列比我们以前处理的任何序列都长?我们不能将字符串用作后缀和前缀。幸运的是,有一个简单的答案:我们保留三个值:maximum_prefix,maximum_suffix,maximum_sum。如果我们在读完一个单词之后更新表,并且结果是同一个字符同时是前缀和后缀,我们将更新这三个值,如下所示:

maximum_sum = max(maximum_sum, 
                  prefix_length + maximum_suffix,
                  suffix_length + maximum_prefix)
maximum_prefix = max(maximum_prefix, prefix_length)
maximum_suffix = max(maximum_suffix, suffix_length)

请注意,如果prefix_length或suffix_length为0,则上述伪代码可以正常工作(如果有点浪费)。

因此,每个字符总共有四个值:homogenous_length, maximum_sum, maximum_prefix, maximum_suffix。在扫描结束时,我们需要找到homogenous_length + maximum_sum最大的字符;我们可以通过对字符表的简单扫描来做到这一点。

每个字符(初始扫描)的总处理时间为O(1),即O(N)(其中N是问题中的字符总数加上{{1} }对于字符表的最终扫描(O(max(N, |A|))是字母表的大小);换句话说,|A|。空间要求如上所述。

答案 1 :(得分:0)

这是我天真的Ruby实现。我将尝试解释我如何推理和实现它。

在Ruby中,字符串不是可枚举的,因此Ruby不能像Python那样直接枚举它。这就是str.chars.to_a解决的问题。它将字符串转换为字符数组。

我的计划是计算每个字符串中字符出现的次数。 ["ab", "ba", "ccc"]将成为[{"a"=>1, "b"=>1}, {"b"=>1, "a"=>1}, {"c"=>3}]。然后我会添加每个连续的哈希/词典对的出现次数。在此示例中,它将导致[{"a"=>2, "b"=>2}, {"b"=>1, "a"=>1, "c"=>3}]。这个散列数组中的最高值将代表最长的运行顺序。

问题是一遍又一遍地包含相同字符的字符串会使该算法失效。我的解决方案是检查这些类型的字符串,然后如果该字符串包含任何此类字符,则将它们与以下字符串连接。这是在arr_of_chararr.each方法的max_running_sequence中实现的。

成对加法用Hash#merge和一个块实现,除了数组中只有一个元素的特殊情况。

最后,我扫描了哈希数组的最大值。

class Sequence_tester
  def self.max_running_sequence(arr_of_chararr)
    reduced = []
    all_same_chars = []

    arr_of_chararr.each do |str|
      arr = str.chars.to_a
      if arr.all? {|c| c == arr.first}
        all_same_chars += arr
      else
        if !all_same_chars.empty?
          if arr.any? {|c| c == all_same_chars.first}
            arr += all_same_chars
          else
            reduced << count_char_occurrences(all_same_chars)
          end
        end
        reduced << count_char_occurrences(arr)
        all_same_chars.clear
      end
    end

    if !all_same_chars.empty?
      reduced << count_char_occurrences(all_same_chars)
    end

    max_seqs = reduced
    if reduced.length > 1
      max_seqs = reduced.each_cons(2).map do |pair|
        pair.first.merge(pair.last) {|key, oldval, newval| oldval + newval}
      end
    end

    longest_seq = max_seqs.map {|h| h.max_by {|kv| kv[1]} }.max_by {|a| a[1]}
  end

  def self.count_char_occurrences(arr)
    arr.each_with_object(Hash.new(0)) {|o, h| h[o] += 1}
  end
end

input = ["a", "b", "c"]
res = Sequence_tester.max_running_sequence(input)
puts "#{res.first},#{res.last}"
input = ["abc", "abb", "abc"]
res = Sequence_tester.max_running_sequence(input)
puts "#{res.first},#{res.last}"
input = ["ab", "ba", "ccc"]
res = Sequence_tester.max_running_sequence(input)
puts "#{res.first},#{res.last}"
input = ["ada", "dd", "dd", "eedd"]
res = Sequence_tester.max_running_sequence(input)
puts "#{res.first},#{res.last}"

输出:
一,1个
B,3
C,3
d,7

答案 2 :(得分:0)

    #include <iostream>

using namespace std;

class alphabet
{
      string str;
      int chars[26];

public:
       alphabet()
       {
                 for(int i=0; i < 26 ; i++)
                         chars[i] = 0;

       }

       void initialize(string s)
       {
            str = s;
            for(int pos=0 ; pos < s.length(); pos++)
                         chars[s[pos]-'a']++;
       }

       int getCount(int i)
       {
           return chars[i];
       }
};

int main()
{
    int n=3;
    alphabet *arr = new alphabet[n];
    arr[0].initialize("varun");
    arr[1].initialize("ritl");
    arr[2].initialize("hello");
    int Max =0;
    char MaxChar = ' ';
    for(int i=0; i<n-1 ; i++)
    {
            for(int j=0; j<26; j++)
            {
                    int m = arr[i].getCount(j)+ arr[i+1].getCount(j);
                    if(m > Max)
                    {
                         Max = m;
                         MaxChar = char('a' + j);
                    }
            }
    }
    cout<<"Max Char = "<<MaxChar<<" "<<Max<<" times";
    system("pause");    
}

答案 3 :(得分:0)

在一次采访中,我可以提出解决这个问题的基本机制,但是我无法在白板上编写完整的,无错误的解决方案。调试器拐杖。

无论如何,这是我在C#中的解决方案。

1。)我定义了集合。

var set = new List<string>() { "ab", "ba", "aac" };

2。)我组装了一个通用的方法来递归地组装所有的排列。

private static List<List<T>> GetPermutations<T>(List<T> values)
{
    if (values.Count <= 1) return new List<List<T>>() { values };

    var results = new List<List<T>>();

    var perms = GetPermutations(values.Skip(1).ToList());

    foreach (var perm in perms)
    {
        foreach (int i in Enumerable.Range(0, perm.Count + 1))
        {
            List<T> list = new List<T>();

            list.AddRange(perm.Take(i));
            list.Add(values[0]);
            list.AddRange(perm.Skip(i));

            results.Add(list);
        }
    }

    return results;
}

3.)我找到了该组的所有排列。

var perms = GetPermutations<string>(set);

4.。)我定义了一种方法,用于在单个字符串中查找最长的运行序列。

private static string LongestRunningSequence(string s)
{
    if (string.IsNullOrEmpty(s)) return null;
    if (s.Length == 1) return s;

    var seq = new Dictionary<char, int>();

    char prev = s[0];
    int counter = 0;

    foreach (char cur in s)
    {
        if (cur == prev) // chars match
        {
            ++counter; // increment counter
        }
        else // chars don't match
        {
            prev = cur; // store new char
            counter = 1; // reset the counter
        }

        // store the higher number of characters in the sequence
        if (!seq.ContainsKey(prev)) seq.Add(prev, counter);
        else if (seq[prev] < counter) seq[cur] = counter;
    }

    char key = seq.Keys.First();
    foreach (var kvp in seq)
    {
        if (kvp.Value > seq[key]) key = kvp.Key;
    }

    return string.Join("", Enumerable.Range(0, seq[key]).Select(e => key));
}

5.。)我定义了一个方法,该方法在字符串列表中找到了运行时间最长的序列,利用了之前对单个字符串执行此操作的方法。

private static string LongestRunningSequence(List<string> strings)
{
    string longest = String.Empty;
    foreach (var str in strings)
    {
        var locallongest = LongestRunningSequence(str);
        if (locallongest.Length > longest.Length) longest = locallongest;
    }

    return longest;
}

6。)我将每个计算出的排列表示为单个字符串列表。

var strings = perms.Select(e => string.Join("", e)).ToList();

7。)我将此列表传递给先前的方法,该方法在字符串列表中找到运行时间最长的序列。

LongestRunningSequence(strings); // returns aaa

答案 4 :(得分:0)

步骤1:需要保持长度为26的4个表 - 第一个跟踪字符串中最长前缀的长度 - 第二个跟踪字符串中最长后缀的长度 - 第三个跟踪完全由给定字符组成的字符串的TOTAL长度 - 第四个跟踪中间最长的字符

第2步: - 运行0到26的循环并添加第一个[i] +秒[i] +第三个[i]并将它们存储在sum [i]中 - 找到sum [i]和第四个表中的最大元素。 --index是字母(0是A),最大元素是长度

#include <stdio.h>
#include <string.h>
#include <ctype.h>


int pre[26],su[26],single[26],middle[26],sum[26];
int getlength(char str[][10])
{
int i,j,n=3,counter=0,max=-1,index;
char c,p;
for(j=0;j<n;j++)
{
 for(i=0;i<strlen(str[j]);i++)
{
 if(i==0) 
{
  c=str[j][i];
  counter++;
  continue;
  }
    else if(i==strlen(str[j])-1&&c == str[j][i])
  {
    counter =0;
    break;
   }
  else
  {
    if(c == str[j][i])
    counter++;
    else 
     break;
   }

  }
    if(pre[toupper(c)-65]<counter)
      pre[toupper(c)-65]=counter;
      counter=0;
  }
for(j=0;j<n;j++)
{
  for(i=strlen(str[j])-1;i>=0;i--)
  {
    if(i==strlen(str[j])-1)
    {
     c=str[j][i];
      counter++;
      continue;
     }
   else if(i==0&&c == str[j][i])
   {
     counter =0;
     break;
   }
   else
   {
     if(c == str[j][i])
     counter++;
   else
    break;
   }

} 
if(su[toupper(c)-65]<counter)
 su[toupper(c)-65]=counter;
 counter=0;
 }

for(j=0;j<n;j++)
{
for(i=strlen(str[j])-1;i>=0;i--)
  {
  if(i==strlen(str[j])-1)
  {
  c=str[j][i];
  counter++;
  continue;
  }
 else
{
 if(c == str[j][i])
 counter++;
 else
 {
counter=0;   
 break;
 }
}

 }
    if(single[toupper(c)-65]<counter)
      single[toupper(c)-65]=counter;
      counter=0;
}
counter=0;
for(j=0;j<n;j++)
{
  for(i=1;i<strlen(str[j])-1;i++)
{
if(i==1)
 {
   c=str[j][i];

   counter++;
 }
  else
 {
   if(c == str[j][i])
 {

   counter++;
  }
 else
 {
 if(middle[toupper(c)-65]<counter)
   middle[toupper(c)-65]=counter;
   counter=1;
   c=str[j][i];
  }

} 
}
 counter=0;
}

 for(i=0;i<26;i++)
{
  sum[i]=pre[i]+su[i]+single[i];
   if(sum[i]>max)
 {
   max=sum[i];
   index=i;
  }
}

for(i=0;i<26;i++)
{

if(middle[i]>max)
{
max=middle[i];
index=i;
}
  }
   printf("\n length %d index %d",max,index);


  }
void main()
{
char arr[3][10]={"bbbb","dccccccar","vaa"};
getlength(arr);
}