如何实现二进制搜索以在通用数组中查找具有特定前缀的字符串(在本例中为字符串[])。我试过compareTo,但这无济于事,因为我必须使用字符串前缀。例如字符串前缀“Bi”bill,bilards ......等..
实现以下方法以返回以给定pre fi x开头的按字母顺序排序的数组中的所有字符串。例如,给定一个pre fi x“bi”,返回的字符串是“Bill Clinton”,“Bill Gates”和“Bill Joy”。请注意,所有字符串比较都应为case INSENSITIVE。返回列表中的字符串必须按它们在数组中出现的顺序排列。您的实现必须基于二进制搜索,并且必须在最坏情况下运行O(log n + k)时间,其中n是数组的长度,k是匹配字符串的数量。假设数组没有重复的条目。如果没有匹配项,则可以返回null或空数组列表。
您可以使用以下String方法(除了您可能记得的任何其他方法): boolean startsWith(String s) int compareTo(String s) int compareToIgnoreCase(String s) String toLowerCase(String s) 字符串toUpperCase(String s) (对于ArrayList,您只需使用add方法将项添加到数组列表的末尾。) 您可以根据需要编写辅助方法(完全实现)。您可能不会调用任何您自己未实现的方法
public static <T extends Comparable<T>> ArrayList prefixMatch(T[] list, String prefix) {
ArrayList<T> result = new ArrayList<T>();
int lo = 0;
int hi = list.length - 1;
while(lo <= hi) {
int mid = (hi + lo) / 2;
list[mid].startsWith(prefix) ? 0 : list[mid].compareTo((T) prefix));
}
return null;
}
答案 0 :(得分:2)
我认为你现在有这样的东西? :
arrayElement.compareTo(prefix)
如果是这样,您可以将其更改为:
arrayElement.startsWith(prefix) ? 0 : arrayElement.compareTo(prefix)
答案 1 :(得分:2)
您可以使用自定义比较器作为基础的默认二进制搜索,然后自行处理我们的范围。我认为正确的算法是:
以下是java中的实现。它适用于快乐的情况,但如果(我将这些检查留下来使代码看起来很简单)会崩溃:
此外,如果您需要二进制搜索实现,您可以查看Arrays.binarySearch
public class PrefixMatch {
public static void main(String[] args) {
final String[] prefixMathces = prefixMatch(new String[] { "Abc", "Abcd", "Qwerty", "Pre1", "Pre2", "Pre3", "Xyz", "Zzz" }, "pre");
for (int i = 0; i < prefixMathces.length; i++)
System.out.println(prefixMathces[i]);
}
public static String[] prefixMatch(final String[] array, final String prefix) {
final Comparator<String> PREFIX_COMPARATOR = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.substring(0, prefix.length()).compareToIgnoreCase(o2);
}
};
final int randomIndex = Arrays.binarySearch(array, prefix, PREFIX_COMPARATOR);
int rangeStarts = randomIndex, rangeEnds = randomIndex;
while (rangeStarts > -1 && array[rangeStarts].toLowerCase().startsWith(prefix.toLowerCase()))
rangeStarts--;
while (rangeEnds < array.length && array[rangeEnds].toLowerCase().startsWith(prefix.toLowerCase()))
rangeEnds++;
return Arrays.copyOfRange(array, rangeStarts + 1, rangeEnds);
}
}
答案 2 :(得分:0)
我建议查看API代码。有一个Arrays类,您可以在java.lang包中查看并从那里学习。
答案 3 :(得分:0)
立即解决类似问题。我相信伪代码会像你的一样。我创建了一个pojo类Song。一首歌由三个字符串艺术家,标题和歌词组成。
创建歌曲对象时,您会得到:
// Artist Title Lyrics..
歌曲a = [“农夫布朗”,“哦'麦克纳达德',”哦,有一个农场呃,我哦,哦,哦)“
public class Song implements Comparable<Song> {
private String _artist;
private String _lyrics;
private String _title;
// constructor
public Song(String artist, String title, String lyrics) {
this._artist = artist;
this._title = title;
this._lyrics = lyrics;
}
public String getArtist() {
return _artist;
}
public String getLyrics() {
return _lyrics;
}
public String getTitle() {
return _title;
}
public String toString() {
String s = _artist + ", \"" + _title + "\"";
return s;
}
//This compare two song objects
public int compareTo(Song song) {
String currentSong = song.toString();
int x = currentSong.compareToIgnoreCase(this.toString());
return x;
}
这是你的方法,它将采用歌曲数组和你的前缀,并使用比较方法来查看它们是否匹配。如果它们匹配compareTo方法返回0.如果你得到0然后你知道你找到了你的歌曲所以返回arrayOfSongs [找到歌曲的索引]。
我还没有对我的搜索进行编码,但我修改了你的搜索以匹配我的代码。我还没有测试过。我认为您甚至不需要compareTo方法,但您可以使用它。此外,对于缩放二进制搜索,应返回可能匹配的歌曲列表,因为您可能有多首以“xyz”开头的歌曲。当你开始在google上搜索前缀为“do”时,你会得到一个“dog,donut,double”的下拉菜单,它可以让用户选择像搜索引擎一样的东西。
public static ArrayList<Song> search (String[] arrayOfSongs , String enteredPrefix) {
ArrayList<Song> listOfMatches = new ArrayList<Song>;
int mid;
int lo = 0;
int hi = arrayOfSongs.length - 1;
while(lo <= hi)
{
mid = (hi + lo) / 2;
if(arrayOfSongs[mid].startsWith(enteredPrefix))
{
System.out.println("Found a match, adding to list");
listOfMatches.add(arrayOfSongs[mid]);
}
}
return listOfMatches;
}
一旦你有一个listOfMatches可能的歌曲嫌疑人你想要你可以以某种方式使用compareTo方法。