タイトル
オリジナル:
ユニークです:文字列はすべてのユニークなキャラクターを持っているかどうかを判断するためのアルゴリズムを実装します。あなたは追加のデータ構造を使用できない場合は?
中国:すべての異なる文字列のかどうかに関係なく、すべての文字を決定するためのアルゴリズムを実装します。それは、追加のデータ構造の使用を許可していないと仮定すると、私は何をすべきでしょうか?
答え
最初に、あなたがインタビュアーをお願いしたいことが、上記の文字列はASCII文字列、または唯一の26文字のですか?大きな文字セットがありますが、
異なる状況のために、私たちはさまざまなソリューションを有していてもよいです。
私たちは、文字セットはASCII文字であると仮定した場合、各文字の外観を特徴づけるためにサイズ256のブール配列を開きます。
配列は、配列位置に対応するbool値が文字は、前に現れた繰り返し文字の文字列であっ導出できることを示す、真のとき、再び、文字の文字列を横断する、falseに初期化されます。
何の値がtrueに配列BOOLの位置によって設定されていません。
コードは以下の通りであります:
FUNC
isUnique(複数の
列
)
BOOL
{
VAR
[
256
]
ブール
用
I
:=
0
; 私は
<
lenの
(S)。I
++
{
IF
[S [I]] {
//文字列に登場しています
返す
偽
}
a[s[i]]
=
true
}
return
true
}
该算法的时间复杂度为O(n)。还可以通过位运算来减少空间的使用量。用每一位表征相应位置字符的出现。
对于ASCII字符,我们需要256位,即一个长度为8的int数组a即可。这里的关键是要把字符对应的数字,映射到正确的位上去。
比如字符'b’对应的代码是98,那么我们应该将数组中的哪一个位置为1呢?
用98除以32,得到对应数组a的下标:3。98对32取模得到相应的位:2。
相应代码如下:
func
isUnique(s
string
)
bool
{
var
a [
8
]
int
for
i
:=
0
; i
<
len
(s); i
++
{
idx, shift
:=
s[i]
/
32
, s[i]
%
32
if
a[idx]
&
(
1
<<
shift) >
0
{
return
false
}
a[idx]
|=
(
1
<<
shift)
}
return
true
}
两个算法的本质是一样的,只不过一个用bool单元来表征字符出现,一个用位来表征。
如果字符集只是a-z(或是A-Z),那就更加好办了,用位运算只需要一个整数型即可。
func
isUnique(s
string
)
bool
{
check
:=
0
for
i
:=
0
; i
<
len
(s); i
++
{
v
:=
s[i]
-
'a'
if
(check
&
(
1
<<
v))
>
0
{
return
false
}
check
|=
(
1
<<
v)
}
return
true
}
全书的Go代码托管在Github上:
github.com/custergo/study_algo