我目前正在寻找典型的面试问题,让我处于正确的心态。 我试图找出自己的问题解决方案,而不是试图记住给定的解决方案。
问题在于我不确定我的解决方案是否是最佳解决方案,或者我的设计中存在重大缺陷。
所以这是我提出的解决方案之一,基本的“这个字符串是唯一的”问题,如检查字符串中的所有字符是否都是唯一的。
public static bool IsUnique(string str)
{
bool isUnique = true;
for (int i = 0; i < str.Length; i++)
{
if (str.LastIndexOf(str.ElementAt(i)) != i)
{
isUnique = false;
break;
}
}
return isUnique;
}
是否有人就此代码是否最佳并且具有可接受的时间和空间复杂性提出建议?
答案 0 :(得分:3)
出于本答案的目的,我将引用Big-O表示法来表示算法的复杂性。提高效率的诀窍是实现可以解决问题的最小Big-O测量,然后尝试复制效率。
您可以通过逻辑思考算法来获得一些效率事实:要检查所有字符是否都是唯一的,您需要评估所有字符。所以这是一个O(n)遍历的字符串保证,我怀疑你很容易得到比这更高效。现在,你能在O(n)或O(2n)时间自己解决吗?如果是这样,这是相当不错的,因为你的算法处于线性时间,并且将线性(对于较大的字符串输入,稳定地变慢)。
您当前的算法循环遍历字符串,然后对于每个字符,再次遍历字符串以比较它并找到相等的字符。这使得算法成为遍历,其中每次访问本身都进行遍历,因此是O(n ^ 2)算法。这被称为多项式时间算法,它不是很好,因为它不能线性缩放;它缩放多项式。这意味着你的算法在输入较大时会慢得多,这是一件坏事。
快速更改以使其效率稍高一点就是在字符串+ 1中的当前索引处开始比较等效字符...您知道所有先前检查过的字符都是唯一的,所以你只关心未来的角色。这将成为一个遍历,每次访问从当前点进行子串遍历(遍历字符串时完成的工作量减少),但这也是一个O(n ^ 2)算法,因为它在外循环的平方中运行时间。这也是一个多项式时间算法,如前所述,但效率略高。但是,对于较大的输入,它仍会严重缩放。
考虑避免重复迭代的其他方法。这些通常以记忆为代价,但实用。我知道如何尝试解决它,但告诉你我的答案并没有帮助你学习。 ;)
编辑:根据您的要求,我会分享我的回答
我通过使用HashSet来加载每个访问过的角色。 HashSet查找和添加大约是O(1)操作。 HashSet.Add方法的优点在于,如果它添加了值则返回true,如果值已经存在则返回false(这是确定算法结果的条件)。我的意思是:
var hashSet = new HashSet<char>();
foreach (char c in myString)
{
if (!hashSet.Add(c))
{
return false;
}
}
return true;
优点: O(n)线性算法。
缺点:用于HashSet的额外内存。
EDIT2:每个人都喜欢廉价的LINQ技巧,所以这是另一种方式
var hashSet = new HashSet<char>();
return myString.Any(c => !hashSet.Add(c));
答案 1 :(得分:0)
与使用线性查找时间O(n)查找字符串中的字符相比,使用HashSet更有效,因为它具有恒定的查找时间O(1):
public static bool AreCharsUnique(string str)
{
var charset = new HashSet<char>();
foreach (char c in str) {
if (charset.Contains(c)) {
return false;
} else {
charset.Add(c);
}
}
return true;
}