Excel精英培训网

 找回密码
 注册
数据透视表40+个常用小技巧,让你一次学会!
查看: 10909|回复: 52

[已解决]在一个字符串中找到第一个只出现一次的字符(不用字典)

[复制链接]
发表于 2013-9-10 22:16 | 显示全部楼层 |阅读模式
题目:在一个字符串中找到第一个只出现一次的字符。如输入abaccdeff,则输出b。
分析:这道题是2006年google的一道笔试题。


最佳答案
2013-9-11 09:15
本帖最后由 leolee82 于 2013-9-11 09:17 编辑

只对英文有效,用了HASH的方法
  1. '只对英文有效,用了HASH的方法
  2. Sub t()
  3. s = "adfsafgd"

  4. Dim arr(65 To 122) As Byte
  5. Dim b() As Byte
  6. b = StrConv(s, vbFromUnicode) ' 字符串转成数组

  7. '找出只出现一次的字符
  8. For i = 0 To UBound(b)
  9.     Select Case arr(b(i))
  10.         Case 0: arr(b(i)) = 1   '只出现一次
  11.         Case 1: arr(b(i)) = 255 '出现多次
  12.     End Select
  13. Next

  14. '找出上面结果中第一次出现的字符
  15. Dim ipos As Long, iPosMin As Long
  16. ipos = -1
  17. For i = LBound(arr) To UBound(arr)
  18.     If arr(i) = 1 Then
  19.         '这里用InStrRev比InStr速度要快,因为搜索范围会不断减少
  20.         ipos = InStrRev(s, Chr(i), ipos, vbBinaryCompare)
  21.         If ipos Then iPosMin = ipos
  22.     End If
  23. Next
  24. End Sub
复制代码
发表于 2013-9-10 22:35 | 显示全部楼层
回复

使用道具 举报

发表于 2013-9-10 22:42 | 显示全部楼层
  1. Sub 查找第一个不重复的字符()
  2.     Dim st$, st1$, st2$, k
  3.     st = "abaccdeff"
  4.     For k = 1 To Len(st)
  5.         st1 = Mid(st, k, 1)
  6.         st2 = WorksheetFunction.Replace(st, k, 1, "")
  7.         If InStr(st2, st1) = 0 Then Exit For
  8.     Next k
  9.     MsgBox "第一个不重复的字符是:" & st1
  10. End Sub
复制代码
  1. Public Function diyi(st As String)
  2.     Dim st1$, st2$, k
  3.     For k = 1 To Len(st)
  4.         st1 = Mid(st, k, 1)
  5.         st2 = WorksheetFunction.Replace(st, k, 1, "")
  6.         If InStr(st2, st1) = 0 Then Exit For
  7.     Next k
  8.     diyi = st1
  9. End Function
复制代码
回复

使用道具 举报

发表于 2013-9-10 22:59 | 显示全部楼层
如果字符在A1单元格内,用工作表函数解决的就是下公式三键回车:
  1. =MID(A1,MIN(IF(MMULT((MID(A1,TRANSPOSE(ROW(INDIRECT("1:"&LEN(A1)))),1)=MID(A1,ROW(INDIRECT("1:"&LEN(A1))),1))*1,ROW(INDIRECT("1:"&LEN(A1)))^0)=1,ROW(INDIRECT("1:"&LEN(A1))),99)),1)
复制代码
回复

使用道具 举报

发表于 2013-9-10 23:00 | 显示全部楼层
  1. Sub test()
  2. Dim arr(), t As String
  3. t = InputBox("请输入字符串")
  4. ReDim arr(1 To Len(t))
  5. For i = 1 To UBound(arr)
  6.    arr(i) = Mid(t, i, 1)
  7. Next
  8. For i = 1 To UBound(arr)
  9. For Each a In arr()
  10.      If arr(i) = a Then counter = counter + 1
  11.    Next
  12.    If counter = 1 Then
  13.      MsgBox arr(i)
  14.      Exit Sub
  15.    Else
  16.      counter = 0
  17.    End If
  18. Next
  19. End Sub
复制代码
没用excel函数做的。。。初学阶段哈,顺便也学习下
回复

使用道具 举报

发表于 2013-9-10 23:11 | 显示全部楼层
Sub t1()
s$ = "abaccdeff"
i% = 1
Do While i <= Len(s)
   If InStr(s, Mid(s, i, 1)) = InStrRev(s, Mid(s, i, 1)) Then MsgBox Mid(s, i, 1): Exit Sub
   i = i + 1
Loop
MsgBox "no"

End Sub
Sub t2()
s$ = "abaccdeff"
i% = 1
Do While Len(s) - Len(Replace(s, Mid(s, i, 1), "")) > 1
   i = i + 1
Loop
If i <= Len(s) Then
   MsgBox Mid(s, i, 1)
Else
   MsgBox "no"
End If
End Sub

Sub t3()
s$ = "abaccdeff"
i% = 1
Do While UBound(Split(s, Mid(s, i, 1))) > 1
   i = i + 1
Loop
If i <= Len(s) Then
   MsgBox Mid(s, i, 1)
Else
   MsgBox "no"
End If
End Sub

点评

不爱多用变量啊。。。。。%>_<%  发表于 2013-9-10 23:49
第一个方法的,没想到啊。好!  发表于 2013-9-10 23:26

评分

参与人数 1 +10 金币 +10 收起 理由
爱疯 + 10 + 10 学习一个!

查看全部评分

回复

使用道具 举报

发表于 2013-9-10 23:19 | 显示全部楼层
  1. Sub A()
  2.     Const SR As String = "abaccdeff"
  3.     Dim K As Byte
  4.     Dim SR1 As String
  5.     For K = 1 To Len(SR)
  6.         SR1 = Mid(SR, K, 1)
  7.         If InStr(SR, SR1) = InStrRev(SR, SR1) Then Exit For
  8.     Next
  9.     MsgBox "第一个出现的不重复为" & SR1
  10. End Sub
复制代码
凑个热闹

坐等请疯神点评
回复

使用道具 举报

发表于 2013-9-10 23:19 | 显示全部楼层
本帖最后由 wp8680 于 2013-9-10 23:43 编辑

总结为:(省略词“第一个非重复字符”)
1.逐个字符,查在其后面是否存在,不存在的,则是,否则下一个字符。InStr(st2, st1) = 0
2.逐个字符,从前查和从后查,所得的位置一样的,则是,否则继续查下一个。InStr(s, Mid(s, i, 1)) = InStrRev(s, Mid(s, i, 1))
3.逐个替换字符,如果替换前后的字符数相差一个,则是,否则继续循环下一个。Len(s) - Len(Replace(s, Mid(s, i, 1), "")) > 1
4.逐个字符进行分列,所得列的维数为2列的,则是,否则继续分列。UBound(Split(s, Mid(s, i, 1))) > 1
5.工作表函数法,逐个取出字符对比MID(A1,TRANSPOSE(ROW(INDIRECT("1:"&LEN(A1)))),1)=MID(A1,ROW(INDIRECT("1:"&LEN(A1))),1),当其中一个字符与每个字符对比下来只有一个时MMULT(……,……)=1,此字符所在位置MIN(IF((……)=1,ROW(……),99)),就用MID(A1,……,1)得出。
回复

使用道具 举报

 楼主| 发表于 2013-9-10 23:39 | 显示全部楼层
本帖最后由 爱疯 于 2013-9-10 23:44 编辑

提这个问题,只为来学习不同的思路。
现在只看了3楼,是好理解的方法。

Sub test3()
    Dim i&, x$, y$, z$
    x = "abaccdeff"
'    x = "aabb"
    For i = 1 To Len(x)
        y = Mid(x, i, 1)
        ''''''''''''''''''''''''''''''''''''''''''
        z = WorksheetFunction.Replace(x, i, 1, "")
'        z = VBA.Replace(x, y, "", , 1)
        ''''''''''''''''''''''''''''''''''''''''''
        If InStr(z, y) = 0 Then
            MsgBox y
            End
        End If
    Next i
    MsgBox "没有"
End Sub


我想了下:
1)替换第i个字符后,3楼是用工作表函数replace,还可用vba的函数replace
2)如果初值x中没有不重复的字符,如"aabb"。那么3楼就会得到错误结果。我改了。


如果x形如"aabbbccccd",那么3楼这个办法会直到最后,才可得到结果。
如果x超长超长呢,不知能否想个更高效的办法呢?









回复

使用道具 举报

发表于 2013-9-10 23:39 | 显示全部楼层
用公式凑热闹
  1. =MID(A1,MATCH(1,MMULT((MID(A1,ROW(INDIRECT(1&":"&LEN(A1))),1)=TRANSPOSE(MID(A1,ROW(INDIRECT(1&":"&LEN(A1))),1)))*1,ROW(INDIRECT(1&":"&LEN(A1)))^0),0),1)
复制代码

点评

函数方法,我太菜,直接围观学习了。  发表于 2013-9-11 00:11
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|Excel精英培训 ( 豫ICP备11015029号 )

GMT+8, 2024-5-19 02:23 , Processed in 4.619133 second(s), 16 queries , Gzip On, Yac On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表