字符串根据字典值排序问题,就是指对给定的字符串,按照首字母的字典值排序,如果首字母相同的字符串,则按照第二个字母,依次内推,比如说 {“dog”,”dear”,”eye”,”bed”},排序后应该是{“bed”,”dear”,”dog”,”eye”} 刚开始接触到这个问题时候,当时想着排序首先按照第一个字母,如果第一个字母相同的那些字符串,再归为一类,再按照第二个字母排序。。。依次类推。 所以不由自主想到了递归,这样问题就变得比较复杂。 后来仔细想了一下,在这个问题上,我开始时候思路就陷入了一个误区,不妨可以按照以下思路重新思考这个问题:
这个问题和普通的数字排序有什么本质区别? 普通的数字排序是根据数字的”大小“关系排序 ,那么这个问题呢?其实也是根据字符串的”大小“关系排序,只不过数字的大小关系可能比较简单,我们用一个比较运算符立马可以得到结果,而字符串之间的大小关系,稍微复杂了一点点,得将字符串中的字符拆开来,分别比较,直到比较出结果为止。 这样看来,其实这个排序和普通的排序的唯一区别就是:在比较”大小“的方法上,略有差异,其他逻辑居然完全一样。所以,我们依然可以用传统的排序方法,解决这个问题,唯一需要做的就是,重新写一个比较大小的方法即可。 下面是用最简单的”冒泡排序“实现的一段代码:
public class SortByDictionary {
public static boolean bigger(String s1, String s2) {
int length1 = s1.length();
int length2 = s2.length();
int i = 0;
while (i < length1 && i < length2) {
if (s1.charAt(i) > s2.charAt(i)) {
return true;
} else if (s1.charAt(i) < s2.charAt(i)) {
return false;
} else {
i++;
}
}
if (i == length1) {
return false;
} else {
return true;
}
}
public static void main(String[] args) {
String[] s = { "dog", "dear", "eye", "bed", "do", "hello", "zero",
"fire", "hc", "zz" };
for (int i = 0; i < s.length - 1; i++) {
boolean change = false; // 用作冒泡排序的标记,如果一趟排序存在交换,则change设为true,说明还需要下一趟排序
for (int j = 0; j < s.length - i - 1; j++) {
if (bigger(s[j], s[j + 1])) {
// swap(s[j], s[j + 1]);
String tmp = s[j];
s[j] = s[j + 1];
s[j + 1] = tmp;
change = true;
}
}
if (!change) {
break; // 当change为false的时候,说明不需要再冒泡了
}
}
for (int i = 0; i < s.length; i++) {
System.out.print(s[i] + " ");
}
}
}
经测试,结果和预期完全一致,可见有时候对于新问题,我们往往被问题的表象所迷惑,而无意中将其复杂化。其实只要静下心来细想,很可能问题便可以迎刃而解。
值得注意的是,对于字符串类型的变量,在方法调用的时候,传参数的方式和基本类型(如int)一样,类似于传递”形参“,而不是和传递对象一样。可以用下面的代码验证:
public class Test {
public static void swap(String s1, String s2) {
String tmp = s1;
s1 = s2;
s2 = tmp;
}
public static void main(String[] args) {
String[] s = { "ab", "cd" };
swap(s[0], s[1]);
for (int i = 0; i < s.length; i++) {
System.out.print(s[i] + " ");
}
}
}
//output: ab cd
从结果可以看出,swap方法并没有交换s[0]和s[1]的值