【问题标题】:Move Uppercase alphabets to the end of string将大写字母移动到字符串的末尾
【发布时间】:2013-08-25 13:28:27
【问题描述】:

问题:给定一个字符串作为输入,将所有大写字母移动到字符串的末尾。示例:

move("Hello World")="ello orldHW"

问题是:我的代码不会停在ello orldHW,而是会继续

ello orldHW // Expected output   
ello orldWH // What I am actually getting

代码:

public class MoveUppercaseChars {   
    static String testcase1 = "Hello World";

    public static void main(String args[]){
       MoveUppercaseChars testInstance = new MoveUppercaseChars();
       String result = testInstance.move(testcase1);
       System.out.println("Result : "+result);
    }

    public String move(String str){
       int len = str.length();
       char ch;
       for(int i=0; i<len; i++) {
          ch = str.charAt(i);
          if(((int)ch >= 65) && ((int)ch <= 90)) {
             str = str.substring(0, i) + str.substring(i+1, len) + str.charAt(i);
          }         
       }
       return str;
   }    
}

【问题讨论】:

  • 我不明白您的预期输出和实际输出之间的区别。是不是要打印两次?
  • WH 被反转了,而且似乎打印了两次。
  • 忘记这个语句 System.out.println(str);并以“我的名字是詹姆斯邦德”作为输入。预期输出:y name is ames ondMJB 实际输出:y name is ames ondJMB 希望你现在明白我的问题。

标签: java


【解决方案1】:

分别存储小写字符和大写字符,然后返回两者的连接:

public class MoveUppercaseChars {   

static String testcase1 = "Hello World";

public static void main(String args[]){
    MoveUppercaseChars testInstance = new MoveUppercaseChars();
    String result = testInstance.move(testcase1);
    System.out.println("Result : "+result);
}

public String move(String str){
    int len = str.length();
    String low = "";
    String cap = "";
    char ch;
    for(int i=0; i<len; i++)
    {
        ch = str.charAt(i);
        if(((int)ch >= 65) && ((int)ch <= 90))
        {
            cap  += ch;
        }   
        else {
            low += ch;
        }
    }
    return low + cap;
}   
}

【讨论】:

  • 对于输入“我住在新德里”,输出应该是“住在 ew elhiIND”,但它给出“住在 ew elhiNID”。我希望您现在了解问题所在。
  • @abhishek14d 一开始我还没有弄清楚。我更正了我的代码。试试看。
  • 是的,就是这样。谢谢!
  • 嘿!我首先使用了更有效的字符串缓冲区!太不公平了……
  • @Daren 对不起,但我没有看你的复制,我在 Eclipse 上开发自己的代码。而且它们并不完全相同,我的对初学者来说更干净,尽管你的可能更聪明或更高效,不确定。
【解决方案2】:

我会使用辅助字符串缓冲区以正确的顺序存储大写字母:甚至是小写字母,因此您创建的字符串实例更少。

public String move(String str){
    char ch;
    int len = str.length();
    // we initialize the buffers with the size so they won't have to be increased
    StringBuffer sbUpperCase = new StringBuffer(len+1);
    StringBuffer sbLowerCase = new StringBuffer(len+1);

    for(int i=0; i<len; i++)
    {
        ch = str.charAt(i);

        //if it is an upperCase letter (but only of the normal ones
        if(Character.isUpperCase(ch))
        {
            sbUpperCase.append(ch);
        }   else {
            sbLowerCase.append(ch);
        }        
    }
    return sbLowerCase.append(sbUpperCase).toString();
} 

使用 Eclipse IDE 进行编辑以获得更好的格式设置,并使用 Character.isUpperCase(ch) 检查是否为大写。关于为什么在字符串之间使用 StringBuffer 而不是 + 运算符很有用,请查看以下问题:Why to use StringBuffer in Java instead of the string concatenation operator

【讨论】:

    【解决方案3】:

    最简单最小的代码解决方案:

    public String move(String str) {
        return s.replaceAll("[A-Z]+", "") + s.replaceAll("[^A-Z]+", "");
    }
    

    基于非正则表达式的解决方案:

    使用StringBuilder这个算法可以很简单:

    public String move(String str){
        StringBuilder sb = new StringBuilder(str);
        int d=0;
        for(int i=0; i<str.length(); i++) {
            int ch = str.charAt(i);
            if(ch >= 65 && ch <= 90) {
                sb.deleteCharAt(i-d++).append((char)ch);
            }           
        }
        return sb.toString();
    }  
    

    与多次操作不可变 String 对象相比,这也将更加高效。

    【讨论】:

    • 与原始代码类似,这将跳过任何一对大写字符中的第二个。
    • 除非我以某种方式看错了,否则我认为这行不通。您正在检查str.charAt(i),然后删除i-d。也许int ch = str.charAt(i-d)
    • @JamesMontagne: d(已删除计数器)从 0 开始,每次删除都会递增以从缓冲区中偏移已删除的字符。查看此工作演示:ideone.com/phnKA2
    • 我的错误,您正在查看str 中的字符,因此sb 的操作不会影响那里的索引。我收回之前说过的话。 +1
    • @abhishek14d 我刚刚想到了另一个非常小的解决方案:s.replaceAll("[A-Z]+", "") + s.replaceAll("[^A-Z]+", "");
    【解决方案4】:

    将循环更改为从字符串的末尾开始,然后向后工作。此外,使用 char[] 数组,它会比在循环的每次迭代中构建一个新字符串更快。比如:

    编辑:这可能是最有效的方法:

        char[] input = str.toCharArray();
        int c = input.length; // cursor to start at
        int ip = input.length - 1; // insertion point of next UP character.
        while (c > 0) {
            c--;
            if (Character.isUpperCase(input[c])) {
                char tmp = input[c];
                System.arraycopy(input, c + 1, input, c, ip - c);
                input[ip] = tmp;
                ip--;
            }
        }
        return new String(input);
    

    编辑:下面的循环不是最有效的......所以将这个代码示例向下移动。

    boolean gotUC=true; // do we have upper-case letters, initialize to true
    char[] input = str.toCharArray();
    int len = input.length;
    while (len > 1 && gotUC) {
        len--;
        int c = len;
        while (c > 0 && !Character.isUpperCase(input[c])) {
           c--;
        }
        if (c >= 0) {
            // move the UC Char to before previous UCase letters....
            char tmp = input[c];
            System.arraycopy(input, c + 1, input, c, len - c);
            input[len] = tmp;
        } else {
            gotUC = false;
        }
    }
    return new String(input);
    

    【讨论】:

    • 您的评论对我来说毫无意义......如果您担心 Character.isUpperCase(),那么只需将其更改为您的测试:input[c] >= 'A' &&输入[c]
    【解决方案5】:

    问题是H这个词被处理了两次,而在第二次处理中它被推到最后

    您可能希望跟踪处理的大写单词总数,以便它们不会再次被处理

    另外,您可以使用@987654321@ 来检查字符是否为大写

    public class Test {
    
        public static void main(String[] args){
            System.out.println(move("Hello World"));
        }
    
        public static int getUpperCaseLetters(String str) {
            int r = 0;
            for(char c : str.toCharArray()) {
                if(Character.isUpperCase(c)) {
                    r++;
                }
            }
            return r;
        }
    
        public static String move(String str){
            int len = str.length();
            char ch;
            int totalUppercase = getUpperCaseLetters(str);
            int processed = 0;
            for(int i=0; i<len && processed < totalUppercase; i++)
            {
                ch = str.charAt(i);
                if(Character.isUpperCase(ch))
                {
                    str = str.substring(0, i) + str.substring(i+1, len) + str.charAt(i);                
                    System.out.println(str);
                    processed++;
                }           
            }
            return str;
        }   
    }
    

    【讨论】:

    • 这将跳过任何连续大写字母的第二个大写字母(原始代码也是如此)。 ideone.com/0VBntr
    【解决方案6】:
    public String move(String str) {
        int todo = str.length();
        int i = 0;
        while (i < todo)
        {
            char c = str.charAt(i);
            if (c >= 65 && c <= 90) {
                str = str.substring(0, i) + str.substring(i + 1, str.length())
                        + str.charAt(i);
                --todo;
                --i;
            }
            ++i;
        }
        return str;
    }
    

    这无需额外的 String var 即可工作。基本思路: 如果将大写字符放在字符串的末尾,您就知道不需要转到字符串的末尾。因此,最初的限制是 str.length(),后来会递减。

    此外,如果您找到匹配项,则必须再次检查该确切位置(因此 --i)。使用您的代码或其他代码 sn-ps 尝试“HEllo WOrld”。

    【讨论】:

      【解决方案7】:

      我会循环输入字符串两次,首先复制出小写字母,然后复制出大写字母。

      public static String move(String str) {
          char[] input = str.toCharArray();
          char[] result = new char[input.length];
          int index = 0;
      
          for (char current : input)
              if (!Character.isUpperCase(current))
                  result[index++] = current;
      
          for (char current : input)
              if (Character.isUpperCase(current))
                  result[index++] = current;
      
          return new String(result);
      }
      

      【讨论】:

        【解决方案8】:
        public class MoveUpperCaseToEnd {
        
        public static void main(String[] args) {
            String string = "SoftwareEngineer";
            String result = moveUpperCase(string);
            System.out.println(result);
        
        }
        
        public static String moveUpperCase(String s) {
            String lowerCase = "";
            String upperCase = "";
            for (int i = 0; i < s.length(); i++) {
                char ch = s.charAt(i);
                if (ch >= 'A' && ch <= 'Z') {
                    upperCase += ch;
                } else {
                    lowerCase += ch;
                }
            }
            return lowerCase + upperCase;
        }
        

        }

        【讨论】:

          猜你喜欢
          • 2021-10-04
          • 1970-01-01
          • 2018-02-25
          • 2018-11-05
          • 2017-04-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多