我正在尝试查找字符串中某个字符的闭合重复出现,但是我被卡住了,不确定如何继续。
问题类似于示例:
字符串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;
}
}
}
}
答案 0 :(得分:0)
我不确定我是否正确理解了问题,但这是一个潜在的解决方案。请注意,此程序具有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);
}
}
}
答案 1 :(得分:0)
如果我理解了问题,则可以在O(n)时间内完成。
算法:input(String s,int idx)
创建一个列表,该列表存储该特定字符的所有出现索引,但idx本身除外。
将min_difference = Integer.MAX_VALUE初始化,并且ClosedIndex = -1。
遍历列表,并使用idx计算列表中索引的mod差异,同时保持min_difference和LeicesterIndex。
例如对于字符串“ babab”,idx = 2,则:
执行第一步后,我们创建的列表为{0,4}
在步骤3中,我们| 2 -0 | = 2(更新min_difference = 2,最近索引= 0),并且| 2-4-| = 2(这时取决于您的要求是是否需要最接近的索引。是否更新是您的选择)。
答案 2 :(得分:0)
字符串API实际上可以帮助您简化整个过程。
您可以使用indexOf(int, int)查找char的下一个用法。您可以使用substring(int,int)仅查看字符串的一部分。您可以使用lastIndexOf(int)查找最后一个出现的字符。
使用这些方法,每个字符串的搜索方法将如下所示
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());
}