Mengeluarkan Watak Berulang dari Rentetan

1. Gambaran keseluruhan

Dalam tutorial ini, kita akan membincangkan beberapa teknik di Java tentang cara membuang watak berulang dari rentetan.

Untuk setiap teknik, kami juga akan membincangkan secara ringkas mengenai kerumitan masa dan ruangnya.

2. Menggunakan yang berbeza

Mari mulakan dengan membuang pendua dari rentetan kami menggunakan kaedah berbeza yang diperkenalkan di Java 8.

Di bawah, kita mendapatkan suatu unsur yang Int S Tream dari objek string diberikan. Kemudian, kami menggunakan kaedah berbeza untuk membuang pendua. Akhirnya, kami memanggil kaedah forEach untuk mengatasi watak yang berbeza dan menambahkannya ke StringBuilder kami :

StringBuilder sb = new StringBuilder(); str.chars().distinct().forEach(c -> sb.append((char) c));

Kerumitan Masa: O (n) - jangka masa gelung berkadar terus dengan ukuran rentetan input

Ruang Auxiliary: O (n) - kerana berbeza menggunakan LinkedHashSet secara dalaman dan kami juga menyimpan rentetan yang dihasilkan dalam objek StringBuilder

Mengekalkan Tertib: Ya - kerana LinkedHashSet mengekalkan susunan elemennya

Dan, walaupun bagus Java 8 melakukan tugas ini untuk kita dengan baik, mari kita bandingkan dengan usaha untuk melancarkan usaha kita sendiri.

3. Menggunakan indexOf

Pendekatan naif untuk membuang pendua dari rentetan hanya melibatkan perulangan input dan menggunakan kaedah indexOf untuk memeriksa sama ada watak semasa sudah ada dalam rentetan yang dihasilkan :

StringBuilder sb = new StringBuilder(); int idx; for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); idx = str.indexOf(c, i + 1); if (idx == -1) { sb.append(c); } } 

Kerumitan Masa: O (n * n) - untuk setiap watak, kaedah indexOf berjalan melalui rentetan yang tinggal

Ruang Auxiliary: O (n) - ruang linear diperlukan kerana kami menggunakan StringBuilder untuk menyimpan hasilnya

Mengekalkan Pesanan: Ya

Kaedah ini mempunyai kerumitan ruang yang sama dengan pendekatan pertama tetapi melakukan jauh lebih perlahan.

4. Menggunakan Array Karakter

Kami juga dapat membuang pendua dari rentetan kami dengan menukarnya menjadi array char dan kemudian melingkar setiap watak dan membandingkannya dengan semua watak seterusnya .

Seperti yang dapat kita lihat di bawah, kita membuat dua untuk gelung dan kita memeriksa sama ada setiap elemen diulang dalam rentetan. Sekiranya pendua ditemui, kami tidak menambahkannya ke StringBuilder :

char[] chars = str.toCharArray(); StringBuilder sb = new StringBuilder(); boolean repeatedChar; for (int i = 0; i < chars.length; i++) { repeatedChar = false; for (int j = i + 1; j < chars.length; j++) { if (chars[i] == chars[j]) { repeatedChar = true; break; } } if (!repeatedChar) { sb.append(chars[i]); } } 

Kerumitan Masa: O (n * n) - kita mempunyai gelung dalaman dan luaran yang melintasi rentetan input

Ruang Auxiliary: O (n) - ruang linear diperlukan kerana pemboleh ubah chars menyimpan salinan input rentetan baru dan kami juga menggunakan StringBuilder untuk menyimpan hasilnya

Mengekalkan Pesanan: Ya

Sekali lagi, percubaan kedua kami berprestasi rendah berbanding dengan tawaran Core Java, tetapi mari kita lihat di mana kita dapat dengan usaha seterusnya.

5. Menggunakan Pengisihan

Sebagai alternatif, watak berulang boleh dihapuskan dengan menyusun rentetan input kami ke kumpulan pendua. Untuk melakukan itu, kita harus menukar rentetan menjadi char rray dan menyusunnya menggunakan Arrays . kaedah menyusun . Akhirnya, kami akan melakukan lelaran ke atas array char yang disusun .

Semasa setiap lelaran, kita akan membandingkan setiap elemen array dengan elemen sebelumnya. Sekiranya elemennya berbeza, kami akan menambahkan watak semasa ke StringBuilder:

StringBuilder sb = new StringBuilder(); if(!str.isEmpty()) { char[] chars = str.toCharArray(); Arrays.sort(chars); sb.append(chars[0]); for (int i = 1; i < chars.length; i++) { if (chars[i] != chars[i - 1]) { sb.append(chars[i]); } } }

Kerumitan Masa: O (n log n) - jenis menggunakan Quicksort dual-pivot yang menawarkan prestasi O (n log n) pada banyak set data

Ruang Auxiliary: O (n) - kerana kaedah toCharArray membuat salinan String input

Menjaga Pesanan: Tidak

Mari cuba lagi dengan percubaan terakhir kami.

6. Menggunakan Set

Cara lain untuk membuang watak berulang dari rentetan adalah dengan menggunakan Set . Sekiranya kita tidak peduli dengan susunan watak dalam rentetan output kita, kita boleh menggunakan HashSet . Jika tidak, kita boleh menggunakan LinkedHashSet untuk mengekalkan pesanan penyisipan.

Dalam kedua-dua kes, kami akan memasukkan rentetan input dan menambahkan setiap watak ke Set . Setelah watak dimasukkan ke dalam set, kami akan mengulanginya untuk menambahkannya ke StringBuilder dan mengembalikan rentetan yang dihasilkan:

StringBuilder sb = new StringBuilder(); Set linkedHashSet = new LinkedHashSet(); for (int i = 0; i < str.length(); i++) { linkedHashSet.add(str.charAt(i)); } for (Character c : linkedHashSet) { sb.append(c); } 

Kerumitan Masa: O (n) - jangka masa gelung berkadar terus dengan ukuran rentetan input

Ruang Auxiliary: O (n) - ruang yang diperlukan untuk Set bergantung pada ukuran rentetan input; juga, kami menggunakan StringBuilder untuk menyimpan hasilnya

Mengekalkan Pesanan: LinkedHashSet - Ya, HashSet - Tidak

Dan sekarang, kami telah menyesuaikan pendekatan Core Java! Tidak mengejutkan apabila mengetahui bahawa ini sangat serupa dengan apa yang sudah ada.

7. Kesimpulannya

Dalam artikel ini, kami membahas beberapa cara untuk membuang watak berulang dari rentetan di Java. Kami juga melihat kerumitan masa dan ruang setiap kaedah ini.

Seperti biasa, coretan kod boleh didapati di GitHub.