去除重復字符


1、指定某字符,並將該字符連續部分數目簡化為1個,(20分)
如“SSSSSABCCCCCC33333      DDDD”如指定3,則字符串替換為“SSSSSABCCCCCC3      DDDD”
2、去除所有重復字符,同樣,以上字符串變為“SABC3 D”(30分)
實現很容易,所以我關注的是算法的優化。
要求,復雜度至少要小於遍歷字符串,請提供與他人不同的思路,尋求最優。



25 个解决方案

#1


Public Class Form1
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim s As String = "SSSSSABCCCCCC33333 DDDD"
        Dim s1 As String = "33"
        Dim i As Int32
        For i = 1 To Int(s.Length / 2)
            s = s.Replace("33", "3")
            s = s.Replace("SS", "S")
            s = s.Replace("CC", "C")
            s = s.Replace("DD", "D")
        Next
        MsgBox(s)
    End Sub
End Class

#2


自嘆,小於一次遍歷,不知道如何實現。

#3


不大可能一次遍歷都不做吧,關注下

#4


1樓,實際上也是遍歷,並且只能有這幾個字母,字母多了就不行,而且比遍歷計算的次數要多,
比如
SSSSSSSSSSSSSSABC3 D(長度20個字符)
遍歷執行用20次,這個執行要13*4次,=42次,因為S沒計算完,ABC3D還得計算

我覺得用正則一次搞定,可這得等過客來

#5


關注

#6


逐個字符進行循環,遇到相同的略過,不同的采用

#7


回樓上幾位,順便更正一下,
抱歉,時間復雜度是很難降低,那么在時間復雜度與遍歷相似的情況下,尋求更精煉的代碼或者最少的執行行數。

#8


            String str = "SSSSSABCCCCCC33333 DDDD";

            char c = '3';
            String temp = c.ToString() + c;
            Int32 index = str.IndexOf(temp);
            while (index > -1)
            {
                str = str.Replace(temp, c.ToString());
                index = str.IndexOf(temp);
            }

            Console.WriteLine(str);

#9


2、去除所有重復字符,同樣,以上字符串變為“SABC3 D”(30分)
//相鄰字符沒有重復
            String str = "SSSSSABCCCCCC33333 DDDD";
            StringBuilder strb = new StringBuilder();

            for (Int16 i = 0; i < str.Length; i++)
            {
                if (strb.Length > 0 && str[i] == strb[strb.Length - 1])
                {
                    continue;
                }
                else
                {
                    strb.Append(str[i]);
                }
            }
            Console.WriteLine(strb.ToString());

//字符串中沒有重復字符
            String str = "SSSSSABCCCCCC33333 DDDDAAAA";
            StringBuilder strb = new StringBuilder();

            for (Int16 i = 0; i < str.Length; i++)
            {
                if (strb.Length > 0 && strb.ToString().IndexOf(str[i]) > -1)
                {
                    continue;
                }
                else
                {
                    strb.Append(str[i]);
                }
            }
            Console.WriteLine(strb.ToString());

#10


自嘆,小於一次遍歷,不知道如何實現。

#11


引用 7 樓 kuhura 的回復:
回樓上幾位,順便更正一下,
抱歉,時間復雜度是很難降低,那么在時間復雜度與遍歷相似的情況下,尋求更精煉的代碼或者最少的執行行數。


需求還需要再明確:
1、連續出現的算重復,那間隔出現的算不算,比如AABBABC
2、字符范圍如何,是只有大寫字母、數字和空格,還是任意字符
3、還有最重要的一點,你追求的是效率最優,還是代碼最短

效率最優,本人算法菜到不能再菜,不敢妄言
但正則是不適合這種場景的,因為正則是為適應大多數場景而進行的一種抽象,不是為了適應某一特定場景設計的,所以特定場景下的效率最優肯定是談不上的

但如果是代碼最短,正則或許還可以,一行足矣,但不清楚與LINQ相比哪個更短
話說回來,比哪個代碼更短似乎沒什么實際意義

#12


說明一點,客客也開始用linq了。

#13


我的思路是,想用正則取出,連續的字符
SSSSSABCCCCCC33333 DDDDAAAA

SSSSS
A
B
CCCCCC
33333
DDDD
AAAA
這樣取第一個就行了,
可自己的正則實在不行,只以同一個來,還望過客把關
我的正則是
[A]*|[B]*|[C]*|[E]*
我這樣只能取出放在第一位的字符,
誰解決了, 我開貼加100分

#14


我去回復你的帖子了。但顯然正則不是效率最優。

#15


所有字符均可得到:
"(.)\1*"

只取可見字符:
"([^\r\n\s])\1*"

#16


我只是學習學習,能講一講嗎為什么這樣,

#17



        Dim reg As New Regex("([^\r\n\s])\1*")
        Dim mc As MatchCollection = reg.Matches("SSSSSABCCCCCC33333 DDDD")
        For Each m As Match In mc
            TextBox1.Text += m.Groups(1).Value & vbLf
        Next


這是我的思路,請大家指正

#18


不知道數據庫的replace效率高還是.net里面的replace效率高...

#19


應該為這個,
Dim reg As New Regex("([^\r\n\s])\1*")
        Dim mc As MatchCollection = reg.Matches("SSSSSABCCCCCC33333 DDDD")
        For Each m As Match In mc
            TextBox1.Text += m.Groups(1).Value
        Next

#20


引用 18 樓 liuyj1979 的回復:
不知道數據庫的replace效率高還是.net里面的replace效率高...

要在數據庫里當然數據庫的replace效率高,拿出來計算會很慢,

#21


來一段Lambda的

private void button1_Click(object sender, EventArgs e)
{
    string s = "SSSSSABCCCCCC33333 DDDD";
    StringBuilder resultBuilder = new StringBuilder();
    s.ToCharArray().Aggregate(char.MinValue,(p, n) =>
    {
        if (p != n) resultBuilder.Append(n);
        p = n;
        return p;
    });
    MessageBox.Show(resultBuilder.ToString());            
}

#22


忘記了。這里是vb.net

Private Sub button1_Click(ByVal sender As Object, ByVal e As EventArgs)
    Dim s As String = "SSSSSABCCCCCC33333 DDDD"
    Dim resultBuilder As New StringBuilder
    s.ToCharArray.Aggregate(Of Char, Char)(ChrW(0), Function (ByVal cp As Char, ByVal cn As Char) 
        If (cp <> cn) Then
            resultBuilder.Append(cn)
        End If
        cp = cn
        Return cp
    End Function)
    MessageBox.Show(resultBuilder.ToString)
End Sub

#23



Private Sub button1_Click(ByVal sender As Object, ByVal e As EventArgs)
    Dim s As String = "SSSSSABCCCCCC33333 DDDD"
    Dim resultBuilder As New StringBuilder
    s.ToCharArray.Aggregate(Of Char, Char)(ChrW(0), Function (ByVal p As Char, ByVal n As Char) 
        If ((p <> n) AndAlso New Char() { " "c, ChrW(13), ChrW(10) }.Contains(Of Char)(n)) Then
            resultBuilder.Append(n)
        End If
        p = n
        Return p
    End Function)
    MessageBox.Show(resultBuilder.ToString)
End Sub




結果:
SABC3D

#24


引用 11 樓 lxcnn 的回復:
需求還需要再明確:
1、連續出現的算重復,那間隔出現的算不算,比如AABBABC
2、字符范圍如何,是只有大寫字母、數字和空格,還是任意字符
3、還有最重要的一點,你追求的是效率最優,還是代碼最短


回11樓:
1、間隔的不算,單純指連續並重復的
2、字符不限,為任意字符
3、原則上,更考慮追求效率,但是如果效率不會降低的情況,也想看看有什么樣的處理思路。經常會執行這樣的處理,想找找相對較佳的方案。
我原來用的是這樣的代碼,想換個思路提高一下: 
    Dim S As String = = "SSSSSABCCCCCC33333 DDDD"
    Dim C As String = "3"
    While S.Contains(C & C)
      S = S.Replace(C & C, C)
    End While
樓上回的幾種辦法,稍后我仔細研究一下。

#25



Public Sub test_lambda_and_linq03(ByVal r As Char)
    Dim s As String = "SSSSSABCCCCCC33333 DDDD"
    Dim resultBuilder As New StringBuilder
    s.ToCharArray.Aggregate(Of Char, Char)(ChrW(0), Function (ByVal p As Char, ByVal n As Char) 
        If ((n <> r) OrElse ((n = r) AndAlso (p = r))) Then
            resultBuilder.Append(n)
        End If
        Return n
    End Function)
    MessageBox.Show(resultBuilder.ToString)
End Sub 


調用:

Me.test_lambda_and_linq03("3"c)

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com