扭曲的煎饼分类(Java)

Posted

技术标签:

【中文标题】扭曲的煎饼分类(Java)【英文标题】:Pancake Sorting with a Twist (Java) 【发布时间】:2022-01-18 09:06:01 【问题描述】:

我正在尝试解决煎饼排序算法的一个版本。在这个问题中,我得到一个由字符 A-F 的任意组合组成的字符串,最大长度为 6。例如,我可能会收到字符串“ACFE”。在这个问题中,我尝试使用煎饼排序将字符串固定为按字母顺序排列。所以上面的例子会变成'ACEF'。

这非常简单明了。这是一个问题:输入字符串中的字符可以是大写或小写。每当您翻转字符串中的字符时,翻转的字符都会切换大小写。所以大写的A会变成'a'。最后的目标是将字符串翻转成顺序,并且所有字符也都是大写的。

我将算法放在一起解决算法的排序部分没有问题,但这是我试图确保在字符全部为大写之前我们不会翻转字符的部分遇到问题并且似乎无法解决。

为了让我自己更轻松,我制作了一个字符到整数的 HashMap,以便更容易对字符进行排序(我们可以使用等效的整数值)。我还在开头将字符串拆分为一个 char[] 并将其倒序放置,以使算法对我自己更容易。

这是我用来做所有事情的代码:

private static final HashMap<Character, Integer> numericalEquivalent = new HashMap<>();

    static 
        numericalEquivalent.put('A', 6);
        numericalEquivalent.put('B', 5);
        numericalEquivalent.put('C', 4);
        numericalEquivalent.put('D', 3);
        numericalEquivalent.put('E', 2);
        numericalEquivalent.put('F', 1);
        numericalEquivalent.put('a', 6);
        numericalEquivalent.put('b', 5);
        numericalEquivalent.put('c', 4);
        numericalEquivalent.put('d', 3);
        numericalEquivalent.put('e', 2);
        numericalEquivalent.put('f', 1);
    

    private static int flip(char[] arr, int i, int numFlips) 

        char temp;
        int start = 0;
        if (start < i) 
            while (start < i) 
                temp = (Character.isUpperCase(arr[start]) ? Character.toLowerCase(arr[start]) : Character.toUpperCase(arr[start]));
                arr[start] = (Character.isUpperCase(arr[i]) ? Character.toLowerCase(arr[i]) : Character.toUpperCase(arr[i]));
                arr[i] = temp;
                start++;
                i--;
            
            numFlips++;
        

        return numFlips;
    

    private static int findMax(char[] arr, int n) 

        int mi, i;
        for (mi = 0, i = 0; i < n; ++i)
            if (numericalEquivalent.get(arr[i]) > numericalEquivalent.get(arr[mi]))
                mi = i;
        return mi;
    

    private static int getFlips (char[] pancakes) 

        int n = pancakes.length;
        int numFlips = 0;

        for (int curr_size = n; curr_size > 1; --curr_size) 

            int mi = findMax(pancakes, curr_size);
            if (mi != curr_size - 1) 
                numFlips = flip(pancakes, mi, numFlips);
                if (!isSorted(pancakes))
                    numFlips = flip(pancakes, curr_size - 1, numFlips);
            
        
        
        return numFlips;
    


private static boolean isSorted(char[] arr) 

        for (int i = 0; i < arr.length - 1; i++) 
            if (numericalEquivalent.get(arr[i]) > numericalEquivalent.get(arr[i + 1]))
                return false;
        
        return true;
    


public static void main(String[] args) 

        while(true) 
            String input = scanner.nextLine();
            if (input.equals("0")) break;
            else System.out.println(getFlips(new StringBuilder(input).reverse().toString().toCharArray()));
        
    

我的目标是恢复将字符翻转成顺序所需的最少翻转次数。但是,我如何修改此代码,以确保它考虑到小写字符以及确保它们都以大写结尾的需要?

【问题讨论】:

【参考方案1】:

您可以将停止条件从if (!isSorted(pancakes)) 更改为if (!isSortedAndUppercase(pancakes)),其中isSortedAndUppercase(pancakes) 定义为:

    private static boolean isSortedAndUppercase(char[] arr)    
        return isUpperCase(arr) && isSorted(arr);
    

    private static boolean isUpperCase(char[] arr) 
        String s = String.valueOf(arr);
        return s.equals(s.toUpperCase());
    

只有在满足停止条件时才停止搜索。 考虑为此任务使用广度优先搜索。

旁注:

无需将字符映射为整数。请尝试以下操作:

    char[] chars =   "ABCDEF".toCharArray();

     for (int i = 0; i < chars.length; i++) 
         System.out.println(chars[i] +" int value: "+(int)chars[i]);
         System.out.println(Character.toLowerCase(chars[i]) +" int value: "+(int)Character.toLowerCase(chars[i]));
     

【讨论】:

以上是关于扭曲的煎饼分类(Java)的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C++ 中按向量进行升序和降序排序

想用java自动生成货品编号的代码,生成规则如下:

用java程序怎么查出父分类下面的所有子分类中的站点信息

Java代码利用朴素贝叶斯分类算法实现信息分类

Java代码利用朴素贝叶斯分类算法实现信息分类

使用 Java 的图像分类算法