实现一个算法来确定一个字符串是不是具有所有唯一字符(大于 U+FFFF 的字符)
Posted
技术标签:
【中文标题】实现一个算法来确定一个字符串是不是具有所有唯一字符(大于 U+FFFF 的字符)【英文标题】:implement an algorithm to determine if a string has all unique characters (characters greater than U+FFFF)实现一个算法来确定一个字符串是否具有所有唯一字符(大于 U+FFFF 的字符) 【发布时间】:2016-04-26 17:30:22 【问题描述】:我正在练习示例面试问题,其中之一是: “实现一个算法来确定一个字符串是否具有所有唯一字符”。
当我们假设它是 ASCII/ANSI 时,这很容易。 implement-an-algorithm-to-determine-if-a-string-has-all-unique-charact
但我的问题是:如果假设字符串可以包含例如象形文字符号或其他(代码点大于 U+FFFF...?)。
所以如果我理解正确,我可以很容易地想到解决方案,如果给定的字符串包含属于从 U+0000 到 U+FFFF 的字符集的字符 - 它们可以转换为 16 位字符,但是如果我遇到代码点大于 U+FFFF... 的字符?
码位大于 U+FFFF 的字符称为补充字符。 Java 平台在 char 数组以及 String 和 StringBuffer 类中使用 UTF-16 表示。在此表示中,补充字符表示为一对 char 值,第一个来自高代理范围 (\uD800-\uDBFF),第二个来自低代理范围 (\uDC00-\uDFFF)
但我不知道在这种情况下如何解决这个难题,我该如何处理这些代理对?
谢谢!
【问题讨论】:
字符或代码点?这已经是完全不同的东西了。 Unicode 目前仅限于 17*2^16 个代码点,因此您可以轻松地将它们存储在一个整数中 - 根据您使用的编码,您将不得不担心代理,但您已经想出了一个。如果真的是关于字符 Knuth 会帮助你的灵魂,因为我什至不想考虑其中的所有复杂性(我什至不能说如果你知道你应该使用的语言是不可能的检查 - 据我所知,可能存在一些理论上的可能性)。 您可以改用代码点。 无论是代码点还是 ASCII 字符,这将减少到从特定范围识别重复的 整数。细度无关紧要。 @Voo 我们可以放心地假设 OP 意味着代码点。否则除了你已经说过的话,没有什么好回答的。 (“真的,真的很难。”) @Voo:为避免混淆,您可能希望使用 graphemes 或 user-perceived characters 作为您的 characters , 以避免与 codepoints 混淆,也称为 programmer-perceived characters,以避免与 Javachar
s (code-units),或者用 C 的多字节字符和宽字符。 字符这个词真的重载了。
【参考方案1】:
Java 8 有一个CharSequence#codePoints
method,它在字符串中生成一个IntStream
的Unicode 代码点。从那里开始,只需编写代码来测试IntStream
中元素的唯一性。
如果您仍在使用 Java 7 或更低版本,那么其中也有基于代码点的方法可以用来解决这个问题,但它们的使用要复杂得多。您必须遍历字符串的char
s 并检查每个值以判断您是否正在处理代理对。类似的东西(完全未经测试):
for (int i = 0; i < str.length(); i++)
int codepoint = str.codePointAt(i++);
if (Character.isHighSurrogate(str.charAt(i)))
// This will fail if the UTF-16 representation of
// this string is wrong (e.g., high surrogate `char`
// at the end of the string's `char[]`).
i += 1;
// do stuff with codepoint...
【讨论】:
如果你使用的是 Java 8,那甚至不是“编写代码来测试IntStream
中元素的唯一性的问题”,就像 string.codePoints().distinct().count()==string.codePoints().count()
一样简单以上是关于实现一个算法来确定一个字符串是不是具有所有唯一字符(大于 U+FFFF 的字符)的主要内容,如果未能解决你的问题,请参考以下文章