一、题干
二、代码实现
以下的两种代码书写方式都是利用了哈希思想,只是实现上略有不同。
代码一
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); //多组输入 while (in.hasNextLine()) { String str = in.nextLine(); //创建标记数组flg boolean[] flg = new boolean[129]; //StringBuilder对象用于存放输出结果 StringBuilder sb = new StringBuilder(); for(int i = 0; i < str.length(); i++) { //将字符串中的字符值作为下标,在flg数组中标记 char ch = str.charAt(i); //flg[ch]等于false,说明该字符是第一次出现,需要存入结果 if(flg[ch] == false) { sb.append(ch); //存入后,将flg数组对应位置标记为true,代表已经输出过 flg[ch] = true; } } //输出结果 System.out.println(sb.toString()); } } }
说明:
- 创建标记数组:boolean[] flg = new boolean[129]; 长度设定为129,是因为后续要以字符串中字母字符的值(也就是字符的ASCII码值)作为数组的下标索引进行标记。最后一个字母字符'z'的码值为122,因此这里创建了一个比122长度略长的数组。没有进行空间优化,因此这么做会造成一定的空间浪费。但宏观来讲,空间复杂度仍是O(1)。
- 遍历字符串时:
1. char ch = str.charAt(i); 获取字符串中i下标处的字母字符值。这个值作为数组的索引。
2. 检查flg[ch]在数组的值为true还是false。若为false,说明这个字符没有之前出现过,现在是第一次出现,故应当存入结果并输出。若为true,说明这已经是该字符的重复出现,不用输出。
3. 在sb.append(ch);后,要把标记数组中该字符的位置更改为true,以防之后重复输出。
代码二
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner reader = new Scanner(System.in); while(reader.hasNext()) { String str1 = reader.nextLine(); //创建标记数组 char[] ch = new char[129]; //先遍历一遍字符串,将出现过的字符在数组中标记 for (int i = 0; i < str1.length(); i++) { ch[str1.charAt(i)] = 1; } //再遍历一遍数组,将标记过的字符输出 for (int i = 0; i < str1.length(); i++) { if (ch[str1.charAt(i)] == 1) { System.out.print(str1.charAt(i)); ch[str1.charAt(i)] = 0; } } System.out.println(); } } }