如何用位运算验证ASCII字符串字符唯一性?大小写字母场景程序报错
搞定位运算验证字符唯一性的大小写问题
嘿,我明白你遇到的麻烦了——你的位运算逻辑是基于原始ASCII值来标记字符是否出现的,但大小写字母的ASCII本身就不一样(比如'A'是65,'a'是97),所以代码会把它们当成完全不同的字符。如果你的需求是不区分大小写来检查唯一性(比如把T和t算重复),那当前逻辑就没处理这种情况,自然会“失效”。
下面咱们一步步解决这个问题:
先补全区分大小写的正确代码
首先把你没写完的代码补全,这是严格区分大小写时的正确实现,能准确检测原始ASCII字符的重复:
import java.util.Scanner; public class Q1_1 { public static void main(String[] args) { long firstHalf = 0; // 存ASCII 0-63的标记位,64位刚好覆盖 long secondHalf = 0; // 存ASCII 64-127的标记位,偏移后也用64位覆盖 Scanner sc = new Scanner(System.in); String input = sc.nextLine(); boolean hasDuplicate = false; for(int i = 0; i < input.length(); i++) { char currentChar = input.charAt(i); int asciiVal = (int) currentChar; // 先检查是否是合法ASCII字符(0-127) if (asciiVal < 0 || asciiVal > 127) { System.out.println("输入包含非ASCII字符,请检查!"); hasDuplicate = true; break; } if (asciiVal < 64) { // 操作firstHalf的对应位 long mask = 1L << asciiVal; if ((firstHalf & mask) != 0) { // 该位已经被标记过,说明字符重复 hasDuplicate = true; break; } firstHalf |= mask; // 标记该位为已出现 } else { // 把64-127转成0-63的偏移量,操作secondHalf int offset = asciiVal - 64; long mask = 1L << offset; if ((secondHalf & mask) != 0) { hasDuplicate = true; break; } secondHalf |= mask; } } if (hasDuplicate) { System.out.println("字符串包含重复字符(区分大小写)"); } else { System.out.println("字符串所有字符唯一(区分大小写)"); } sc.close(); } }
修改为不区分大小写的验证逻辑
如果你的需求是忽略大小写(比如Test里的T和t算重复),只需要在处理每个字符时,先统一转成大写或小写,再获取ASCII值就行,核心改动就一行:
import java.util.Scanner; public class Q1_1 { public static void main(String[] args) { long firstHalf = 0; long secondHalf = 0; Scanner sc = new Scanner(System.in); String input = sc.nextLine(); boolean hasDuplicate = false; for(int i = 0; i < input.length(); i++) { char currentChar = input.charAt(i); // 关键:统一转成小写(也可以用toUpperCase),让大小写字母映射到同一个ASCII值 char normalizedChar = Character.toLowerCase(currentChar); int asciiVal = (int) normalizedChar; if (asciiVal < 0 || asciiVal > 127) { System.out.println("输入包含非ASCII字符,请检查!"); hasDuplicate = true; break; } if (asciiVal < 64) { long mask = 1L << asciiVal; if ((firstHalf & mask) != 0) { hasDuplicate = true; break; } firstHalf |= mask; } else { int offset = asciiVal - 64; long mask = 1L << offset; if ((secondHalf & mask) != 0) { hasDuplicate = true; break; } secondHalf |= mask; } } if (hasDuplicate) { System.out.println("字符串包含重复字符(不区分大小写)"); } else { System.out.println("字符串所有字符唯一(不区分大小写)"); } sc.close(); } }
为啥这么做?
- 用两个
long是因为它刚好64位,两个加起来128位,完美对应0-127的ASCII字符,每个位标记一个字符是否出现过,完全不用额外数据结构,符合你的需求。 - 不区分大小写的核心就是归一化字符:把所有字母转成同一种大小写,这样大小写字母会被映射到同一个ASCII值,位运算就能检测出它们是重复的。
- 加了非ASCII字符的判断,避免超出范围的字符导致位运算越界出错。
内容的提问来源于stack exchange,提问作者Varun
相关产品推荐
相关产品推荐

