最高的“有价值”回文

时间:2013-12-17 17:56:04

标签: java c algorithm

所以几个月前我正在接受编程采访,这个问题由于某种原因而惹恼了我。我能想到几种解决方案,但大多数解决方案效率极低。虽然我多年来一直在编程,但我目前正在大学攻读CS学位,所以我的参考点可能不完整。我希望有人可以提供一些可能的解决方案:

“给定一组字符串和相关的数字'值,'从这些字符串组合回文,其值(由用于创建它的字符串之和定义)是最高的。”

可以提供多少个字符串没有限制,可能不会使用某些字符串。

实施例: “asd” - 3 “dsa” - 5 “appa” - 1

结果将是“asdappadsa”,其值为9.

我的想法是尝试所有顺序中的所有字符串,然后从最低值的一个开始删除一个,但是该解决方案是O(N!)并且我认为不行。

(首选语言是C和Java,但无论什么都有效)

编辑:澄清。提供的每个字符串只能使用一次,并且必须完全按照提供的方式使用,但您可以选择不使用回文中的任何字符串。您不能使用提供的字符串的子字符串,也不能反转字符串。

2 个答案:

答案 0 :(得分:5)

用“所有回文”替换“所有字符串”,问题空间变得更小。

将字符串分成26个子集。

 Strings beginning with x (for 'a' <= x <= 'z')  
   [or whatever the set of "letters" is]

现在将它们分成另外26个子集

 Strings ending with y ( for 'a' <= y <= 'z')

注意每个字符串出现在“开头”设置和“结束时”设置。

使用这些集来指导创建所有可能的回文。

 Start with two empty strings:  prefix and suffix
 for each string in the original set
    assign it to the prefix
    call recursiveFunction(prefix, suffix)

 def recursiveFunction(prefix, suffix):
    if prefix + <anything> + suffix cannot form a palindrome return
    if prefix + suffix is a palindrome, remember it
    while you have unused strings
      if the suffix is shorter than the prefix
           Look at the first unmatched character in the prefix
           for each unused string that ends in that character
              call recursiveFunction(prefix, string + suffix)

      else if prefix is shorter than suffix
         look at the last unmatched character in the suffix
            for each unused string that ends with that character
               call recursiveFunction(prefix + string, suffix)
      else // suffix and prefix have equal lenghths
         for each unused string
           call recursiveFunction(prefix + string, suffix)   

确保在使用时标记用于开头的字符串和结束时使用的字符串。 并且一定要考虑递归对“使用”标记的影响。

然后选择得分最高的回文。

答案 1 :(得分:0)

使用palindrones,您可以将字符串拆分为3个子字符串ABC。在集合中有可能找到字符串反转,因此当你获得一个点击时,你可以跟踪这些字符串以用于子字符串A和C中。如果你没有在整个集合中获得反转命中,你只需要找到最大的字符串(或具有最高值的字符串),它是自身的反映。不是最好的解决方案,我敢肯定,但无论如何我都是为了好玩,所以我也可以分享。此外,我没有努力使这个代码“干净”,所以它有点难看,但它的工作原理。

public class Main {

    private static String[] set = new String[] { "asdf" , "kjdij", "skjdihi", "ddidid" , "ididid", "iddid", "oihu", "uhio", "fdsa", "ajsja" };

    public static void main(String[] args){
        //Used for a couple of for loops...
        int count;

        Map<String, String> map = new HashMap<String,String>(); //Hold the strings and their reversals in a hashmap for quick lookups.

        /* Think of the palindrome as 3 substrings, A, B, and C. */
        ArrayList<String> A = new ArrayList<String>();
        ArrayList<String> B = new ArrayList<String>(); 
        ArrayList<String> C = new ArrayList<String>();


        count = set.length;
        String[] reverse_set = new String[count];
        for(int x = 0; x < count; x++){

            String reverse = new StringBuilder(set[x]).reverse().toString();

            /* Check strings that would work for section B, since it's a set, we know that if it could work for B, 
             * it couldn't work for A or C - since a set contains no duplicates. */
             if(reverse.equals(set[x])){
                 B.add(set[x]);
             } else {
                 /* Otherwise, we'll have to check to see if it would work for A and C */
                 reverse_set[x] = reverse;
                 map.put(set[x], reverse);               
             }

        }

        /* Check the map for reverse string hits, we know that if another string exists in set S such that S(X) == R(X) it can work for substring
         * A and C. */
        int map_size = map.size();
            int hit_count = 0;
        for(int i = 0; i < map_size; i++){
            String s = map.get(reverse_set[i]);
            if(s != null){
                            hit_count++;
                A.add(set[i]);
                C.add(reverse_set[i]);
                map.remove(set[i]);  //remove the reflection, so we don't get duplicates
            }
        }

        /* Find the longest string in B, since we'll have to do this even if was had any hits in the previous loop. */
        String b = null;
        if(B.size() > 0){
            int length = 0;
            for(String x : B){
                int mLength = x.length();
                if(mLength > length){
                    b = x;
                    length = mLength;
                }
            }
        }

        /* Build the palinedrome */
        String palineString = "";
        if(hit_count == 0 && b != null){
            palineString = b;
        } else {
            for(String x : A){
                palineString += x;
            }
            if(b != null){
                palineString += b;
            }
            count = C.size();
            for(int y = (count - 1); y >= 0; y--){
                palineString += C.get(y); 
            }
        }

        if(checkPalindrome(palineString)){
            System.out.print("The Palindrone is: " + palineString + " Score: " + Integer.toString(palineString.length()));
        } else {
            System.out.print("Oops...");
        }
    }

    private static boolean checkPalindrome(String x){
        if(x.equals(new StringBuilder(x).reverse().toString())){
            return true;
        } else {
            return false;
        }
    }

}

输出:

The Palindrone is: asdfoihuajsjauhiofdsa Score: 21

编辑:

注意:暂时,我使用字符串的长度作为“指定值”,我稍后会进行编辑,以便为字符串分配随机值,但不会产生太大差异,因为它只增加了一些额外的用例来检查。