Java中的随机字符排列

3
下面的代码需要接收一个字符串并随机交换两个字符的位置,这样操作将会进行stringLength()次。
但是有时候输出结果会比预期多出两个数字或少出两个数字。我尝试过各种方法,包括修改随机数生成方式和管理子字符串,但仍然无法解决这些异常情况。
Scanner in = new Scanner(System.in);
String word = in.next();
for (int wordLength = word.length(); wordLength >= 0; wordLength--){
    int i = (int) (Math.random() * (wordLength - 1));
    int j = 0;
    // j has to be bigger than i.
    while (j < i){
        j = (int) ((Math.random() * wordLength));
    }
    String first = word.substring(0, i);
    String middle = word.substring(i, j);
    String last = word.substring(j);
    word = first + word.charAt(j) + middle + word.charAt(i) + last;
    System.out.println(word);
}   

这个问题来自于Java for Everyone,但它并不是作业。
谢谢您的想法。

从你所写的问题来看,为什么不通过生成两个随机索引并在 str.length() 次数内交换这些索引处的字符来简化你的代码呢? - hrv
2个回答

3
substring方法在下标较低的位置上是包含的。因此,当您单独添加这些字符时,以及在middlelast的开头时,都会重复包含这些交换后的字符。
您需要从它们各自的索引+1开始middlelast子串,以避免在这些字符串中包含ij处的字符。
如果您在修改word之前放置几个print行(以查看您将要执行的操作),则可以看到我所说的内容。通过这些打印输出,您将能够看到您即将重复一些字符。
System.out.println(String.format("i: %s, j: %s", i, j));
System.out.println("first: "+first);
System.out.println("char i: "+word.charAt(i));
System.out.println("middle: "+middle);
System.out.println("char j: "+word.charAt(j));
System.out.println("last: "+last);

正如Thomas W在评论中指出的那样,当您进行此修复时,还会遇到StringIndexOutOfBoundsError,因为您的循环在顶部和底部都是包含范围的。在完全修复之前,您需要解决这个问题(无论是在循环的开头还是结尾)。


2
外部的 wordLength 循环也存在边界错误 -- 它在顶部和结束边界上都是包含的。在最后一次迭代中,wordLength - 1 将会是 -1。这不是想要的结果。 - Thomas W
是的,将代码更改为String middle = word.substring(i + 1, j); String last = word.substring(j + 1);确实产生了正确的结果。但是我开始收到一个字符串索引超出范围的错误。 - borg123

2
您可以使用Collections.shuffle(List<?> list)进行排列。请参阅此处的文档
String str = "abcdefgh";
Character[] chArr = ArrayUtils.toObject(str.toCharArray());
Collections.shuffle(Arrays.asList(chArr));
System.out.println(ArrayUtils.toString(chArr));

我想这可以使用Apache Commons Lang的ArrayUtils吗? - demongolem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接