[英]Struggling with finding the closest occurence of character in string
我试图找到字符串中字符的闭合重复出现,但是我被卡住了,不确定如何继续。
问题是这样的,例如:
字符串s =“ babab”,索引为2,找到该字符的最接近出现位置。 所以这里的0和4,其中0最接近2。
我到目前为止所拥有的
public static List<Integer> closest(String s, List<Integer> queries) {
// Write your code here
int min;
int count = 0;
List<Integer> ans = new List<Integer>();
for(int i=0; i<queries.size(); i++){
char a = s.charAt(i);
for(int j=0; j<s.length(); j++){
if(s[j] == a ){
int count = j;
}else{
count = -1;
}
}
}
}
我不确定我是否正确理解了问题,但这是一个潜在的解决方案。 请注意,此程序具有O(n * m)复杂度,其中m =查询数,n =字符串长度。 这可以进一步优化。
import java.util.ArrayList;
import java.util.List;
public class Main {
public static List<Integer> closest(String s, List<Integer> queries) {
List<Integer> result = new ArrayList<Integer>();
//execute each query separately
for(int i=0; i<queries.size(); i++){
char target = s.charAt(queries.get(i));
int index = queries.get(i);
int length = s.length();
int currentStep = 1;
boolean founded = false;
//search for the closest character
while(index-currentStep>=0 || index+currentStep<length){
if(index-currentStep>=0 && s.charAt(index-currentStep)==target){
result.add(index-currentStep);
founded = true;
break;
}else if(index+currentStep<length && s.charAt(index+currentStep)==target){
result.add(index+currentStep);
founded = true;
break;
}
currentStep++;
}
if(!founded){
//we couldn't find the element
result.add(-1);
}
}
return result;
}
public static void main(String[] args) {
String s = "babab";
List<Integer> queries = new ArrayList<Integer>();
queries.add(2);
List<Integer> result = closest(s,queries);
for(Integer res: result){
System.out.println(res);
}
}
}
更新:这是一个复杂度为O(max(n,m))的解决方案。 让我分析一下复杂性。 首先,这个问题不能在小于O(n)的情况下解决,因为我们必须至少访问每个字符一次。 另外,对于每个查询,我们至少可以使用任何一种算法进行访问,因此至少需要m个步骤(如果我们与m个worker并行运行该算法,则复杂度将为O(n))。 现在的解决方案:我们建立了两个数据结构,这些数据结构将对我们有所帮助(在prepareDb中)。 此过程需要3 * n,可以对其进行一些优化,但这仍为O(n)。 然后,我们简单地查询包含最近元素索引的数组,该元素对m个查询(O(m))进行m个步骤。 最后,总和为O(n)+ O(m)或O(max(n,m))。 解决方法如下:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class Main {
public static List<Integer> prepareDb(String s) {
List<Integer> result = new ArrayList<>();
//fron similar
HashMap<Integer, Integer> dbFront = new HashMap<>();
HashMap<Character, Integer> lastSeenFront= new HashMap<>();
for(int i = 0; i<s.length();i++){
Character c = s.charAt(i);
int distance = -1;
if(lastSeenFront.containsKey(c)){
distance = i - lastSeenFront.get(c);
}
lastSeenFront.put(c,i);
dbFront.put(i, distance);
}
//backSimilar
HashMap<Integer, Integer> dbBack = new HashMap<>();
HashMap<Character, Integer> lastSeenBack = new HashMap<>();
for(int i = s.length()-1; i >= 0;i--){
Character c = s.charAt(i);
int distance = -1;
if(lastSeenBack.containsKey(c)){
distance = lastSeenBack.get(c) - i;
}
lastSeenBack.put(c,i);
dbBack.put(i, distance);
}
for(int i = 0; i<s.length();i++){
//distance between i and the closest element
int distance = dbFront.get(i);
if(dbFront.get(i)==-1 || (dbBack.get(i)!=-1 && dbFront.get(i)>dbBack.get(i))){
distance = dbBack.get(i);
}
result.add(distance);
}
return result;
}
public static List<Integer> closest(String s, List<Integer> queries) {
List<Integer> result = new ArrayList<Integer>();
List<Integer> db = prepareDb(s);
//execute each query separately
for(int i=0; i<queries.size(); i++){
result.add(db.get(queries.get(i)));
}
return result;
}
public static void main(String[] args) {
String s = "babab";
List<Integer> queries = new ArrayList<Integer>();
queries.add(2);
List<Integer> result = closest(s,queries);
for(Integer res: result){
System.out.println(res);
}
}
}
如果我了解问题,则可以在O(n)时间内完成。
算法:input(String s,int idx)
创建一个列表,该列表存储该特定字符出现的所有索引,但idx本身除外。
初始化min_difference = Integer.MAX_VALUE且最近索引= -1。
遍历列表并使用idx计算列表中索引的mod差异,同时保持min_difference和最近索引。
例如。 对于字符串“ babab”和idx = 2,则:
执行第一步后,我们创建的列表为{0,4}
在步骤3中,我们| 2 -0 | = 2(更新min_difference = 2,最近索引= 0),并且| 2-4-| = 2(这时取决于您的要求是是否需要最接近的索引。是否更新是您的选择)。
字符串API实际上可以帮助您简化整个过程。
您可以使用indexOf(int,int)来查找char的下一个用法。 您可以使用substring(int,int)仅查看String的一部分。 并且您可以使用lastIndexOf(int)查找最后一个出现的char。
使用这些方法,每个字符串的搜索方法将类似于以下内容
public static int closest(String s, int index) {
char target = s.charAt(index);
int next = s.indexOf(target, index+1);
int previous = s.substring(0, index).lastIndexOf(target);
//The below code probably needs so work to handle not found case (ie -1)
if (index-previous <= next-index) {
return previous;
} else {
return next;
}
}
然后,您可以在上一个函数中使用它:
public static List<Integer> closest(String s, List<Integer> queries) {
queries.stream().mapToInt(I -> closets(s,i)).collect(Collectors.toList());
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.