繁体   English   中英

努力寻找字符串中最接近的字符出现

[英]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)

  1. 创建一个列表,该列表存储该特定字符出现的所有索引,但idx本身除外。

  2. 初始化min_difference = Integer.MAX_VALUE且最近索引= -1。

  3. 遍历列表并使用idx计算列表中索引的mod差异,同时保持min_difference和最近索引。

例如。 对于字符串“ babab”和idx = 2,则:

执行第一步后,我们创建的列表为{0,4}

在步骤3中,我们| 2 -0 | = 2(更新min_difference = 2,最近索引= 0),并且| 2-4-| = 2(这时取决于您的要求是是否需要最接近的索引。是否更新是您的选择)。

字符串API隔离

字符串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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM