【问题标题】:Java Function similar to word game, last letter = first letter of next wordJava函数类似于文字游戏,最后一个字母=下一个单词的第一个字母
【发布时间】:2017-01-24 21:00:12
【问题描述】:

函数 main 接受一个字符串数组作为参数,并将打印一行输出。输出将是输入的顺序,使得每个字符串的第一个字母与前一个字符串的最后一个字母相同,但最后一个字符串的最后一个字母与第一个字符串的第一个字母相同。如果不存在包含所有字符串的订单,则代码将打印无解决方案

输入和输出示例:

输入:松鼠眼类似激光手术

输出:松鼠仿激光眼

输入:为什么我们不能跳舞

输出:没有解决方案

输入:苹果坦帕大象

输出:苹果大象坦帕

我已经编写了大部分代码,但是我的排序方法并不适用于每个测试用例,因为它的编写方式,有人可以帮忙吗??

public class Ring {

    public static void main(String[] args) {

        boolean a = isFlip(args);


        if(a) {
            for (int i = 0; i < args.length; i++) {
                System.out.print(args[i] + " ");
            }
        }else {
            System.out.println("NO SOLUTION");
        }

    }

    public static boolean isFlip(String[] args) {

        for (int i = 0; i <args.length ; i++) {
            args[i]=args[i].toLowerCase();
        }

        for (int i = 0; i < args.length-1 ; i++) {
            for (int j = i+1; j <args.length ; j++) {

                if (args[i].charAt(0)==(args[j].charAt(args[j].length()-1))){
                    String s= args[j];
                    args[j]=args[i];
                    args[i]=s;
                }
            }

        }

        for (int i = 0; i <args.length-1 ; i++) {
            if((args[i+1].charAt(0)!=(args[i].charAt(args[i].length()-1)))){
                 return false;
            }

        }
        if(args[args.length-1].charAt(args[args.length-1].length()-1)!=args[0].charAt(0)) return false;

        return true;
    }
}

【问题讨论】:

  • 我想也许我明白你想要做什么,但可以肯定的是,你能编辑你的问题以包含一些示例输入/输出吗?
  • 对不起,我编辑了它
  • 您是否尝试过使用调试器单步执行您的代码?
  • 另一个澄清问题。您是否希望输入中的多个单词具有相同的第一个字母和/或相同的最后一个字母?因为如果你允许这样做,你的任务将变得更加难以编码,因为你的代码将不得不探索多种排列,然后在找不到具有一种排列的解决方案时回溯。但如果你不允许它,你将不得不决定如何处理它。

标签: java sorting arguments


【解决方案1】:

您可以尝试使用递归方法。主要思想是检查每个单词是否有其他单词可能在链中。

private String[] findRing(String... words) {
    for (int i = 0; i < words.length; i++) {
        String word = words[i];
        String[] result = findRingForHeadAndTail(word, dropElementWithIndex(i, words));
        if ((result.length == words.length - 1) &&
                (word.charAt(0) == result[result.length - 1].charAt(result[result.length - 1].length() - 1))) { //word started from last letter in tail
            return concatHeadAndTail(word, result);
        }
    }
    return new String[]{"NO SOLUTION"};
}

private String[] findRingForHeadAndTail(
        String head, //first word
        String... tail //other words
) {
    if (tail.length == 0) { // if we don't have other words then just return empty array
        return new String[0];
    }

    if (tail.length == 1) { // if we have just one word in tail
        if (tail[0].charAt(0) == head.charAt(head.length() - 1)) { //and this word begins with last letter in head
            return tail; //return this tail
        } else {
            return new String[0]; //otherwise return empty array
        }
    }

    for (int i = 0; i < tail.length; i++) { // for every word
        String word = tail[i];
        if (word.charAt(0) == head.charAt(head.length() - 1)) { // if this word begins with last letter in head
            String[] result = findRingForHeadAndTail( //recursive call for 
                    word, //picked word
                    dropElementWithIndex(i, tail) // all other words in tail
            ); 
            if (result.length == tail.length - 1) { // if recursive call returns the same amount of words as we passed there as tail
                return concatHeadAndTail(word, result); //return array {head, tail}
            }
        }
    }
    return new String[0];
}

//returns array as {head, tail}
private String[] concatHeadAndTail(String head, String... tail) {
    return Stream.concat(Stream.of(head), Stream.of(tail)).collect(Collectors.toList()).toArray(new String[tail.length + 1]);
}

//removes element with index i from words
private String[] dropElementWithIndex(int i, String... words) {
    List<String> result = new ArrayList<>();
    for (int j = 0; j < words.length; j++) {
        if (j != i) {
            result.add(words[j]);
        }
    }
    return result.toArray(new String[words.length - 1]);
}

然后输出:

@Test
public void findRing() {
    System.out.println(Arrays.toString(findRing("squirrel", "eyes", "klondlike", "lasik")));
    System.out.println(Arrays.toString(findRing("why", "cant", "we", "dance")));
    System.out.println(Arrays.toString(findRing("apple", "tampa", "elephant")));
    System.out.println(Arrays.toString(findRing("apple", "elephant", "tampa")));
    System.out.println(Arrays.toString(findRing("elephant", "apple", "tampa")));
    System.out.println(Arrays.toString(findRing("alfa", "alfa", "beta")));
    System.out.println(Arrays.toString(findRing("alfa", "alfa")));
    System.out.println(Arrays.toString(findRing("alfa", "alfa", "bravo")));
}

是:

[squirrel, lasik, klondlike, eyes]
[NO SOLUTION]
[apple, elephant, tampa]
[apple, elephant, tampa]
[elephant, tampa, apple]
[NO SOLUTION]
[alfa, alfa]
[NO SOLUTION]

更新 以前的解决方案在更坏的情况下复杂度为 O(n!)。 FDesu 提出了不同的解决方案,并且基于 Adjacency matrix 的属性之一。

如果 A 是有向或无向图 G 的邻接矩阵,那么矩阵 An(即 A 的 n 个副本的矩阵乘积)有一个有趣的解释:元素 (i, j) 给出 (有向或无向)从顶点 i 到顶点 j 的长度为 n 的游走。

该算法复杂度为O(n^4),但对内存也有额外要求,因为我们要存储所有可能的路径。

private void findRingWithMatrix(String... words) {
    System.out.println("For example: " + Arrays.toString(words));
    boolean[][] initialAdjacencyMatrix = new boolean[words.length][words.length];
    List<String[]> paths = new ArrayList<>();
    //Build initial adjacency matrix
    for (int i = 0; i < words.length; i++) {
        for (int j = 0; j < words.length; j++) {
            initialAdjacencyMatrix[i][j] = (i != j) && (couldBeInChain(words[i], words[j]));
            //if node is reachable
            if (initialAdjacencyMatrix[i][j]) {
                //put this path to possible paths
                paths.add(new String[]{words[i], words[j]});
            }
        }
    }

    //create temporary copy of matrix to multiply
    boolean[][] tempAdjacencyMatrix = initialAdjacencyMatrix.clone();

    //We should multiply matrix N-1 times, because first step in graph we've already done on previous step
    for (int n = 1; n < words.length; n++) {
        boolean[][] bufferAdjacencyMatrix = new boolean[words.length][words.length];

        List<String[]> newPathes = new ArrayList<>();

        //multiply matrices (next step and initial). In result we get [true] in node which is reachable from first node in N steps
        for (int i = 0; i < words.length; i++) {
            for (int j = 0; j < words.length; j++) {
                for (int k = 0; k < words.length; k++) {
                    bufferAdjacencyMatrix[i][j] |= (tempAdjacencyMatrix[i][k] && initialAdjacencyMatrix[k][j]);
                }
                //if node reachable
                if (bufferAdjacencyMatrix[i][j]) {
                    //create new path and put it list of possible paths
                    for (String[] path : paths) {
                        if (couldBeInChain(path[path.length - 1], words[j])) {
                            String[] newPath = new String[path.length + 1];
                            System.arraycopy(path, 0, newPath, 0, path.length);
                            newPath[newPath.length - 1] = words[j];
                            newPathes.add(newPath);
                        }
                    }
                }
            }
        }
        paths = removeDuplicates(newPathes);
        System.out.println("Step #" + n);
        printMatrix(bufferAdjacencyMatrix);
        tempAdjacencyMatrix = bufferAdjacencyMatrix;
    }

    boolean isRing = true;

    //Ring could be just if after (N-1) multiplications we have [true] in main diagonal.
    //In other words, can reach every node in N steps.
    for (int i = 0; i < words.length; i++) {
        isRing = tempAdjacencyMatrix[i][i];
        if (!isRing) {
            break;
        }
    }

    if (!isRing) {
        System.out.println("NO SOLUTION");
        return;
    } else {

        System.out.println("Found solutions:");
        for (String[] path : paths) {
            //we are interested just in solutions when first node is equals to last one
            if (path[0].equals(path[path.length - 1])) {
                String[] toPrint = new String[path.length - 1];
                System.arraycopy(path, 0, toPrint, 0, toPrint.length);
                System.out.println(Arrays.deepToString(toPrint));
            }
        }
    }

    System.out.println("==============================");
}

private boolean couldBeInChain(String first, String second) {
    return first.charAt(first.length() - 1) == second.charAt(0);
}

private List<String[]> removeDuplicates(List<String[]> newPathes) {
    return newPathes
            .stream()
            .map(Arrays::asList)
            .collect(Collectors.collectingAndThen(Collectors.toSet(), new Function<Set<List<String>>, List<String[]>>() {
                @Override
                public List<String[]> apply(Set<List<String>> lists) {
                    List<String[]> result = new ArrayList<>();
                    for (List<String> list : lists) {
                        result.add(list.toArray(new String[list.size()]));
                    }
                    return result;
                }
            }));
}

private void printMatrix(boolean[][] matrix) {
    System.out.println("-------------------------------");

    for (boolean[] row : matrix) {
        System.out.println(Arrays.toString(row));
    }
    System.out.println("-------------------------------");
}

【讨论】:

  • 这段代码是否处理类似输入:“apple”、“tampa”、“tad”、“dot”、“elephant”,输出:“apple”、“elephant”、“tad” 、“点”、“坦帕”?
  • @TJamesBoone 是的,检查过。输出为[apple, elephant, tad, dot, tampa]
  • 甜蜜。这意味着它可以处理这个问题。非常感谢递归的使用!
  • 非常感谢,这很有帮助!我想在没有递归的情况下这样做是行不通的,但是我想办法在接受字符串作为参数的同时使用它,谢谢!!
【解决方案2】:
class T
{
public static void main(String[] args) 
{ 
int k=1;
Scanner sc=new Scanner(System.in); 
String str=sc.nextLine(); 
String[] word=str.split(" "); 
StringBuilder str1=new StringBuilder(word[0]); 
while(str1.toString().length()!=str.length())
{ 
for(int j,i=1;i<word.length;i++)
{ 
for(j=1;j<word.length;j++)
{
if((str1.toString()).endsWith(Character.toString(word[j].charAt(0))))
{ 
str1.append(" "+word[j]);
} 
} 
}
break;
}
for(int i=0;i<word.length;i++)
{
    if((str1.toString()).indexOf(word[i])<0)
    {
        str1.insert(0,word[i]+" ");
        k=k+1;
    }
}
if(k==word.length)
    System.out.println(str);
else
    System.out.println("NO SOLUTION"); 
} 
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-23
    • 1970-01-01
    • 2017-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多