找到按字典顺序排列的最大的唯一字符串

时间:2012-04-08 20:32:07

标签: algorithm puzzle

我需要一个算法,通过删除字符(无重新排列)从字符串中查找最大的唯一(无重复字符)子字符串。

如果字符串A满足这两个条件,则字符串A大于字符串B.

1. Has more characters than String B
   Or
2. Is lexicographically greater than String B if equal length

例如,如果输入字符串是 dedede ,那么可能的唯一组合是 de ed d ,和 e 在这些组合中,最大的组合因此 ed ,因为它的字符数多于 d e ,并且按字典顺序大于 de < / em>的

该算法必须比生成所有可能的唯一字符串更有效,并对它们进行排序以找到最大的字符串。

注意:这不是家庭作业。

2 个答案:

答案 0 :(得分:2)

这个怎么样

string getLargest(string s) 
{
        int largerest_char_pos=0;
        string result="";
        if(s.length() == 1) return s;
        for(int i=0;i<s.length();)
        {
            p=i;
            for(int j=i+1;j<s.length();j++)
            {
                if(s[largerest_char_pos]< s[j]) largerest_char_pos =j;
            }
            res+=s[largerest_char_pos];
            i=largerest_char_pos+1;
        }
        return result;      
    }

这是代码片段,只是为您提供了按字典顺序排列的字符串。如果你不想要重复,你可以跟踪已经添加的字符。

答案 1 :(得分:1)

让我以一种我认为更清楚的方式陈述订购规则。

如果

,字符串A大于字符串B.
- A is longer than B
  OR
- A and B are the same length and A is lexicographically greater than B

如果我重述规则是正确的,那么我相信我有一个在O(n ^ 2)时间和O(n)空间运行的解决方案。我的解决方案是基于观察的贪心算法,即在最长的有效子序列中存在与输入字符串中的唯一字符一样多的字符。我在Go中写了这篇文章,希望这些评论足以描述算法。

func findIt(str string) string {
  // exc keeps track of characters that we cannot use because they have
  // already been used in an earlier part of the subsequence
  exc := make(map[byte]bool)

  // ret is where we will store the characters of the final solution as we
  // find them
  var ret []byte

  for len(str) > 0 {
    // inc keeps track of unique characters as we scan from right to left so
    // that we don't take a character until we know that we can still make the
    // longest possible subsequence.
    inc := make(map[byte]bool, len(str))

    fmt.Printf("-%s\n", str)
    // best is the largest character we have found that can also get us the
    // longest possible subsequence.
    var best byte

    // best_pos is the lowest index that we were able to find best at, we
    // always want the lowest index so that we keep as many options open to us
    // later if we take this character.
    best_pos := -1

    // Scan through the input string from right to left
    for i := len(str) - 1; i >= 0; i-- {
      // Ignore characters we've already used
      if _, ok := exc[str[i]]; ok { continue }

      if _, ok := inc[str[i]]; !ok {
        // If we haven't seen this character already then it means that we can
        // make a longer subsequence by including it, so it must be our best
        // option so far
        inc[str[i]] = true
        best = str[i]
        best_pos = i
      } else {
        // If we've already seen this character it might still be our best
        // option if it is a lexicographically larger or equal to our current
        // best.  If it is equal we want it because it is at a lower index,
        // which keeps more options open in the future.
        if str[i] >= best {
          best = str[i]
          best_pos = i
        }
      }
    }


    if best_pos == -1 {
      // If we didn't find any valid characters on this pass then we are done
      break
    } else {
      // include our best character in our solution, and exclude it for
      // consideration in any future passes.
      ret = append(ret, best)
      exc[best] = true

      // run the same algorithm again on the substring that is to the right of
      // best_pos
      str = str[best_pos+1:]
    }
  }
  return string(ret)
}

我相当肯定你可以在O(n)时间做到这一点,但我不确定我的解决方案,所以我发布了这个。