如何在一个数组中找到不重复的数?

时间:2021-08-18 09:54:29
例如:
3 4 4 5 6 3 2 3 6 7
结果出来是
2 5 7

想法如下
1 排序
 2 3 3 3 4 4 5 6 6 7
2 查找
i = 0
j = 1
Do While i <= UBound(a) - 1
  If a(i) = a(i + 1) Then
    j = j + 1
  Else
    If j = 1 Then Debug.Print a(i)
    j = 1
  End If
  i = i + j
Loop


请大家帮我给排序和查找的最佳算法,或者重新给一个思路,谢谢

74 个解决方案

#1


建议使用集合的方法

#2


都是一位数吗?

#3


rushing(勇敢的心),具体点

#4


I_168_888(瓜棚下),不一定,可以是很大的数

#5


把这些数放入数据库表a的字段b中,用SQL语句:select distinct b from a
再从返回的记录集中读出所有记录。

#6


xsp(),那样出来的结果是2 3 4 5 6 7.而不是2 5 7

#7


XSP说的好!用VB就要用彻底么。
不过可惜还有一点点小错误,没仔细看题吧?
SQL语句应该是
select b from a group by b having count(b)=1
才对啊。

#8


a表b字段,
select b from a where b not in
(select b from a
group by b
having count(*) > 1);

#9


junglerover(灌木丛),这个法子我知道,谢谢,问题是我不和数据库打交道的情况呢?

#10


sorry, 没想清楚,junglerover 的算法简单

#11


对不起,看错了。
设返回的记录集是rec
dim rec2 as new adodb.recordset
rec.movefirst
for i=1 to rec.recordcount
  rec2.open "select b from a where b=" & rec!b,cn
  if rec2.recordcount=1 then print rec2!b
  rec2.close
  rec.movenext
next i

#12


一个很简单的算法:
假设你的数组中每个元素都是数字
Private Sub Command1_Click()
    Dim arr(100) As String
    Dim upperbound As Integer
    Dim lowerbound  As Integer
    Dim i As Integer
    
    upperbound = 1
    lowerbound = 30
    For i = 1 To 100 '创建一个1~30的随机数组
        Randomize
        arr(i - 1) = CStr(Int((upperbound - lowerbound + 1) * Rnd + lowerbound))
    Next
    
    Dim Arr2Str As String
    Arr2Str = "," & Join(arr, ",") '将数组元素连结成一个字符串,注意:第一个元素前也必须加一个,
    Debug.Print Arr2Str
    Dim iLen As Integer
    Dim tmpValue As String
    For i = LBound(arr) To UBound(arr)
        iLen = Len(Arr2Str)
        If iLen <= 0 Then 'iLen=0表示我们已经遍历了所有的元素
            Exit For
        End If
        tmpValue = "," & arr(i) '读取每个数组元素
        Arr2Str = Replace(Arr2Str, tmpValue, "") 
        If iLen - Len(Arr2Str) = Len(tmpValue) Then '只有一个元素
            Debug.Print Right(tmpValue, Len(tmpValue) - 1) '输出,你可以保存这个元素值
        End If
        
    Next
End Sub

#13


hydnoahark(诺亚方舟),不错,谢谢

#14


看我的代码,极短无比:
Private Sub Command1_Click()
  Dim a(0 To 10) As String
  a(0) = "1"
  a(1) = "3"
  a(2) = "12"
  a(3) = "3"
  a(4) = "1"
  a(5) = "4"
  a(6) = "4"
  a(7) = "4"
  a(8) = "6"
  a(9) = "3"
  a(10) = "5"
  
  Text2 = ""
  Text1 = ""
  
  For i = 0 To UBound(a)
      If InStr(Text1, a(i)) = 0 Then
         If InStr(Text2, a(i)) = 0 Then
            Text2 = Text2 & "," & a(i) & ","
         Else
            Text1 = Text1 & "," & a(i) & ","
            Text2 = Replace(Text2, "," & a(i) & ",", "")
         End If
      End If
  Next
End Sub

#15


a(1-10)=   3 4 4 5 6 3 2 3 6 7
k = 0
For i = 1 To 10
  temp = 0
  For j = 1 To 10
    If a(i) = a(j) Then temp = 1: Exit For
  Next
  If temp = 0 Then k = k + 1: b(k) = a(i)
Next

b数组为所求

#16


不好意思,前面漏了几个字符:
代码如下:
Private Sub Command1_Click()
  Dim a(0 To 10) As String
  a(0) = "1"
  a(1) = "3"
  a(2) = "12"
  a(3) = "3"
  a(4) = "1"
  a(5) = "4"
  a(6) = "4"
  a(7) = "4"
  a(8) = "6"
  a(9) = "3"
  a(10) = "5"
  
  Text2 = ""
  Text1 = ""
  
  For i = 0 To UBound(a)
      If InStr(Text1, "," & a(i) & ",") = 0 Then
         If InStr(Text2, "," & a(i) & ",") = 0 Then
            Text2 = Text2 & "," & a(i) & ","
         Else
            Text1 = Text1 & "," & a(i) & ","
            Text2 = Replace(Text2, "," & a(i) & ",", "")
         End If
      End If
  Next
End Sub

#17


我的是不是太简单了

#18


面:不是,你用了双层循环,慢了。效率就低了。

#19


to :fraser01(王晓栋)
你不觉得你的算法会产生大量无用逗号吗

#20


to :fraser01(王晓栋)
我觉得把你我的方法结合起来就最好了,先把数组变成带逗号的字符串,在用Instr循环一下,结果就出来了。

#21


不会的,到时候再去掉就行了。
你的我没说错啊!只是我不喜欢多重循环罢了。
再说你是一种阶层调用,数据量大的话,一定会有问题的。

#22


那样就是单重循环,只不过我见是10个变量,所以忽略了这一点

#23


9494
面:我好喜欢你啊!,我们的算法结合一下,可能就天下无敌了。
    哈哈哈!!!!!!

#24


fraser01(王晓栋) 的好

#25


好好,下次有好程序别忘了和我结合一下

#26


一定一定。绝配嘛!

#27


a(1-10)=  3 4 4 5 6 3 2 3 6 7
Str = "3 4 4 5 6 3 2 3 6 7"
k = 0
For i = 1 To 10
    temp = 0
    If InStr(Str, a(i)) Then temp = 1
    If temp = 0 Then k = k + 1: b(k) = a(i)
Next

b数组为所求 

#28


是不是像这样

#29


SORRY 都怪我太罗嗦 应该是这样
a(1-10)=  3 4 4 5 6 3 2 3 6 7 '此处我略了
Str = "3 4 4 5 6 3 2 3 6 7" '此处我也略了
k = 0
For i = 1 To 10
    If InStr(Str, a(i))=0 Then k = k + 1: b(k) = a(i)
Next

b数组为所求 

#30


好象有点问题,我用
1 3 12 13 1 14 4 4 6 3 5
试,但结果错误

#31


是马,我随手写的,没调试过

#32


确实有。

#33


果然错得一塌糊涂,我忘了考虑字符串里有一个自身的值了,光想着重复

#34


看来太追求高速也没什么好处

#35


没关系的,慢慢该BUG,程序员本色嘛

#36


Dim a(10), str, b(10),i,k
  a(1) = "3"
  a(2) = "12"
  a(3) = "3"
  a(4) = "1"
  a(5) = "4"
  a(6) = "4"
  a(7) = "4"
  a(8) = "6"
  a(9) = "3"
  a(10) = "5"
str = " 3 12 3 1 4 4 4 6 3 5" 
k = 0
For i = 1 To 10
    If InStr(Right(str, Len(str) - InStr(str, a(i)) - Len(a(i)) + 1), a(i)) = 0 Then k = k + 1: b(k) = a(i)
Next
For i = 1 To k
    Debug.Print b(i)
Next



调通了,总算没丢大脸

#37


不错,很好的,比我的还短。
看来以后要多讨教了。
你在上海吗》

#38


SORRY,我在北京,我的邮箱是aizen@263.net
以后还望多多指教

#39


好啊!
我的是Fraser01@sohu.com

#40


我上的不多,所以常联系,88

#41


建一个一样的数组b(10),值设为0,表示没有重复

对于a数组扫描,方法如下:

for i =1 to 10
  if b(i)=0 then  '/*前面未有数值与其重复
    for j=i to 10   '/*扫描后面的数值
      if a(i)=a(j) then  '/*找到重复值
        b(i)=1
        b(j)=1
      end if
    next j
  end if
next i

借助于instr,我不知道其时间复杂度为多少
况且上面连续使用了两个instr,而且不直观
我不赞成这种做法

#42


如果更好的方法,我想是使用链表

扫描方法一样,如果有重复值,将其摘除

#43


progame(来来往往,不知所云.......) 
    其实你一样也犯了多重循环的毛病。多重循环是一个在问题无法用单一循环解决的情况下使用的东西。因为他的循环次数是随数据量而阶层递增的。
    instr的复杂度很底,时间很短,他的解释函数并不是一一查找比对,而是内存指针的比对。
    对大数使用来说,你的方法应该舍弃。

#44


对大数来说,先排序绝对是唯一的方法,把时间复杂度降到log(N)

否则上面的方法都不行

instr的复杂度到底有多低,你有多少把握,内存指针的比对?如何比对?

两个instr,两个len,加上一个right,时间复杂度和N的比较会有什么优势?

我不认为上面那种方法的时间复杂度好过N * N

#45


天,先排序,不用谈了。太慢了
我说的大数是指有10000个数据怎么办?
10000的阶层可不是好玩的。
不如用我的方法吧。

#46


作了个测试,数据10000都是12S

全部行不通:(              

#47


大数据量时只有先排序了,时间复杂度LOG(N),如果你不清楚的话

可以去查一下

到此为止了,不直观的程序代码我宁可不要

#48


<script language=vbscript>
aN = array(1,2,1,2,12,3,12,9,8,11)
str = "^" & join(aN, "^") & "^"   '^ 在最前最后都有
For i = 0 To ubound(aN)
  aTmp = split( Str, "^" & aN(i) & "^") 
'如果Str中只有一个^aN(i)^,aTmp就有两个元素,上标为1
'否则aTmp上标大于1:
'aTmp = split("de","d"), ubound(aTmp)=1: aTmp(0) = "", aTmp(1) = "e"
'aTmp = split("dde","d"), ubound(aTmp)=2: aTmp(0) = "", aTmp(1) = "", aTmp(2) = "e"
  if ubound(aTmp) = 1 then sResult = sResult & "," & aN(i)
Next
msgbox mid(sResult,2) '去掉第一个逗号
</script>

测试通过

#49


去掉注释
aN = array(1,2,1,2,12,3,12,9,8,11,9)
str = "^" & join(aN, "^") & "^"   '^ 在最前最后都有
For i = 0 To ubound(aN)
  aTmp = split( Str, "^" & aN(i) & "^") 
  if ubound(aTmp) = 1 then sResult = sResult & "," & aN(i)
Next
msgbox mid(sResult,2) '去掉第一个逗号

#50


huzy100(阿寅)的大于12S,没戏。

#1


建议使用集合的方法

#2


都是一位数吗?

#3


rushing(勇敢的心),具体点

#4


I_168_888(瓜棚下),不一定,可以是很大的数

#5


把这些数放入数据库表a的字段b中,用SQL语句:select distinct b from a
再从返回的记录集中读出所有记录。

#6


xsp(),那样出来的结果是2 3 4 5 6 7.而不是2 5 7

#7


XSP说的好!用VB就要用彻底么。
不过可惜还有一点点小错误,没仔细看题吧?
SQL语句应该是
select b from a group by b having count(b)=1
才对啊。

#8


a表b字段,
select b from a where b not in
(select b from a
group by b
having count(*) > 1);

#9


junglerover(灌木丛),这个法子我知道,谢谢,问题是我不和数据库打交道的情况呢?

#10


sorry, 没想清楚,junglerover 的算法简单

#11


对不起,看错了。
设返回的记录集是rec
dim rec2 as new adodb.recordset
rec.movefirst
for i=1 to rec.recordcount
  rec2.open "select b from a where b=" & rec!b,cn
  if rec2.recordcount=1 then print rec2!b
  rec2.close
  rec.movenext
next i

#12


一个很简单的算法:
假设你的数组中每个元素都是数字
Private Sub Command1_Click()
    Dim arr(100) As String
    Dim upperbound As Integer
    Dim lowerbound  As Integer
    Dim i As Integer
    
    upperbound = 1
    lowerbound = 30
    For i = 1 To 100 '创建一个1~30的随机数组
        Randomize
        arr(i - 1) = CStr(Int((upperbound - lowerbound + 1) * Rnd + lowerbound))
    Next
    
    Dim Arr2Str As String
    Arr2Str = "," & Join(arr, ",") '将数组元素连结成一个字符串,注意:第一个元素前也必须加一个,
    Debug.Print Arr2Str
    Dim iLen As Integer
    Dim tmpValue As String
    For i = LBound(arr) To UBound(arr)
        iLen = Len(Arr2Str)
        If iLen <= 0 Then 'iLen=0表示我们已经遍历了所有的元素
            Exit For
        End If
        tmpValue = "," & arr(i) '读取每个数组元素
        Arr2Str = Replace(Arr2Str, tmpValue, "") 
        If iLen - Len(Arr2Str) = Len(tmpValue) Then '只有一个元素
            Debug.Print Right(tmpValue, Len(tmpValue) - 1) '输出,你可以保存这个元素值
        End If
        
    Next
End Sub

#13


hydnoahark(诺亚方舟),不错,谢谢

#14


看我的代码,极短无比:
Private Sub Command1_Click()
  Dim a(0 To 10) As String
  a(0) = "1"
  a(1) = "3"
  a(2) = "12"
  a(3) = "3"
  a(4) = "1"
  a(5) = "4"
  a(6) = "4"
  a(7) = "4"
  a(8) = "6"
  a(9) = "3"
  a(10) = "5"
  
  Text2 = ""
  Text1 = ""
  
  For i = 0 To UBound(a)
      If InStr(Text1, a(i)) = 0 Then
         If InStr(Text2, a(i)) = 0 Then
            Text2 = Text2 & "," & a(i) & ","
         Else
            Text1 = Text1 & "," & a(i) & ","
            Text2 = Replace(Text2, "," & a(i) & ",", "")
         End If
      End If
  Next
End Sub

#15


a(1-10)=   3 4 4 5 6 3 2 3 6 7
k = 0
For i = 1 To 10
  temp = 0
  For j = 1 To 10
    If a(i) = a(j) Then temp = 1: Exit For
  Next
  If temp = 0 Then k = k + 1: b(k) = a(i)
Next

b数组为所求

#16


不好意思,前面漏了几个字符:
代码如下:
Private Sub Command1_Click()
  Dim a(0 To 10) As String
  a(0) = "1"
  a(1) = "3"
  a(2) = "12"
  a(3) = "3"
  a(4) = "1"
  a(5) = "4"
  a(6) = "4"
  a(7) = "4"
  a(8) = "6"
  a(9) = "3"
  a(10) = "5"
  
  Text2 = ""
  Text1 = ""
  
  For i = 0 To UBound(a)
      If InStr(Text1, "," & a(i) & ",") = 0 Then
         If InStr(Text2, "," & a(i) & ",") = 0 Then
            Text2 = Text2 & "," & a(i) & ","
         Else
            Text1 = Text1 & "," & a(i) & ","
            Text2 = Replace(Text2, "," & a(i) & ",", "")
         End If
      End If
  Next
End Sub

#17


我的是不是太简单了

#18


面:不是,你用了双层循环,慢了。效率就低了。

#19


to :fraser01(王晓栋)
你不觉得你的算法会产生大量无用逗号吗

#20


to :fraser01(王晓栋)
我觉得把你我的方法结合起来就最好了,先把数组变成带逗号的字符串,在用Instr循环一下,结果就出来了。

#21


不会的,到时候再去掉就行了。
你的我没说错啊!只是我不喜欢多重循环罢了。
再说你是一种阶层调用,数据量大的话,一定会有问题的。

#22


那样就是单重循环,只不过我见是10个变量,所以忽略了这一点

#23


9494
面:我好喜欢你啊!,我们的算法结合一下,可能就天下无敌了。
    哈哈哈!!!!!!

#24


fraser01(王晓栋) 的好

#25


好好,下次有好程序别忘了和我结合一下

#26


一定一定。绝配嘛!

#27


a(1-10)=  3 4 4 5 6 3 2 3 6 7
Str = "3 4 4 5 6 3 2 3 6 7"
k = 0
For i = 1 To 10
    temp = 0
    If InStr(Str, a(i)) Then temp = 1
    If temp = 0 Then k = k + 1: b(k) = a(i)
Next

b数组为所求 

#28


是不是像这样

#29


SORRY 都怪我太罗嗦 应该是这样
a(1-10)=  3 4 4 5 6 3 2 3 6 7 '此处我略了
Str = "3 4 4 5 6 3 2 3 6 7" '此处我也略了
k = 0
For i = 1 To 10
    If InStr(Str, a(i))=0 Then k = k + 1: b(k) = a(i)
Next

b数组为所求 

#30


好象有点问题,我用
1 3 12 13 1 14 4 4 6 3 5
试,但结果错误

#31


是马,我随手写的,没调试过

#32


确实有。

#33


果然错得一塌糊涂,我忘了考虑字符串里有一个自身的值了,光想着重复

#34


看来太追求高速也没什么好处

#35


没关系的,慢慢该BUG,程序员本色嘛

#36


Dim a(10), str, b(10),i,k
  a(1) = "3"
  a(2) = "12"
  a(3) = "3"
  a(4) = "1"
  a(5) = "4"
  a(6) = "4"
  a(7) = "4"
  a(8) = "6"
  a(9) = "3"
  a(10) = "5"
str = " 3 12 3 1 4 4 4 6 3 5" 
k = 0
For i = 1 To 10
    If InStr(Right(str, Len(str) - InStr(str, a(i)) - Len(a(i)) + 1), a(i)) = 0 Then k = k + 1: b(k) = a(i)
Next
For i = 1 To k
    Debug.Print b(i)
Next



调通了,总算没丢大脸

#37


不错,很好的,比我的还短。
看来以后要多讨教了。
你在上海吗》

#38


SORRY,我在北京,我的邮箱是aizen@263.net
以后还望多多指教

#39


好啊!
我的是Fraser01@sohu.com

#40


我上的不多,所以常联系,88

#41


建一个一样的数组b(10),值设为0,表示没有重复

对于a数组扫描,方法如下:

for i =1 to 10
  if b(i)=0 then  '/*前面未有数值与其重复
    for j=i to 10   '/*扫描后面的数值
      if a(i)=a(j) then  '/*找到重复值
        b(i)=1
        b(j)=1
      end if
    next j
  end if
next i

借助于instr,我不知道其时间复杂度为多少
况且上面连续使用了两个instr,而且不直观
我不赞成这种做法

#42


如果更好的方法,我想是使用链表

扫描方法一样,如果有重复值,将其摘除

#43


progame(来来往往,不知所云.......) 
    其实你一样也犯了多重循环的毛病。多重循环是一个在问题无法用单一循环解决的情况下使用的东西。因为他的循环次数是随数据量而阶层递增的。
    instr的复杂度很底,时间很短,他的解释函数并不是一一查找比对,而是内存指针的比对。
    对大数使用来说,你的方法应该舍弃。

#44


对大数来说,先排序绝对是唯一的方法,把时间复杂度降到log(N)

否则上面的方法都不行

instr的复杂度到底有多低,你有多少把握,内存指针的比对?如何比对?

两个instr,两个len,加上一个right,时间复杂度和N的比较会有什么优势?

我不认为上面那种方法的时间复杂度好过N * N

#45


天,先排序,不用谈了。太慢了
我说的大数是指有10000个数据怎么办?
10000的阶层可不是好玩的。
不如用我的方法吧。

#46


作了个测试,数据10000都是12S

全部行不通:(              

#47


大数据量时只有先排序了,时间复杂度LOG(N),如果你不清楚的话

可以去查一下

到此为止了,不直观的程序代码我宁可不要

#48


<script language=vbscript>
aN = array(1,2,1,2,12,3,12,9,8,11)
str = "^" & join(aN, "^") & "^"   '^ 在最前最后都有
For i = 0 To ubound(aN)
  aTmp = split( Str, "^" & aN(i) & "^") 
'如果Str中只有一个^aN(i)^,aTmp就有两个元素,上标为1
'否则aTmp上标大于1:
'aTmp = split("de","d"), ubound(aTmp)=1: aTmp(0) = "", aTmp(1) = "e"
'aTmp = split("dde","d"), ubound(aTmp)=2: aTmp(0) = "", aTmp(1) = "", aTmp(2) = "e"
  if ubound(aTmp) = 1 then sResult = sResult & "," & aN(i)
Next
msgbox mid(sResult,2) '去掉第一个逗号
</script>

测试通过

#49


去掉注释
aN = array(1,2,1,2,12,3,12,9,8,11,9)
str = "^" & join(aN, "^") & "^"   '^ 在最前最后都有
For i = 0 To ubound(aN)
  aTmp = split( Str, "^" & aN(i) & "^") 
  if ubound(aTmp) = 1 then sResult = sResult & "," & aN(i)
Next
msgbox mid(sResult,2) '去掉第一个逗号

#50


huzy100(阿寅)的大于12S,没戏。