为什么我超出了时间限制?

时间:2019-07-13 07:48:05

标签: java

我正在超过时间限制?

类似字符 问题描述 塔希尔(Tahir)和玛姆塔(Mamta)正在TCS的一个项目中工作。 Tahir作为一个问题解决者,为他的朋友Mamta提出了一个有趣的问题。

问题由长度为N的字符串组成,并且仅包含小写字母。

它将跟随Q查询,其中每个查询将包含一个整数P(1 <= P <= N),该整数表示字符串中的位置。

Mamta的任务是找到该位置存在的字母,并确定在给定位置P之前相同字母的出现次数。

Mamta忙于她的办公室工作。因此,她请您帮助她。

约束 1 <= N <= 500000

由小写字母组成的

1 <= Q <= 10000

1 <= P <= N

输入格式 第一行包含一个整数N,表示字符串的长度。

第二行包含字符串S本身仅由小写字母组成('a'-'z')。

第三行包含一个整数Q,表示将要查询的查询数。

接下来的Q行包含一个整数P(1 <= P <= N),您需要为它找到在P之前的Pth位置出现的字符的数量。

输出 对于每个查询,在单行上打印一个整数,表示答案。

测试用例

说明 示例1

输入

9

abacsddaa

2

9

3

输出

3

1

说明

这里Q = 2

对于P = 9,第9个位置的字符为“ a”。在P(即9)之前出现“ a”的次数为三。

类似地,对于P = 3,第三个字符为'a'。 P之前出现“ a”的次数(即3)是1。

import java.io.*;

public class simchar
{
    public static void main(String gg[]) throws Exception
    {
        BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
        int n=Integer.parseInt(reader.readLine());
        String s=reader.readLine();
        if(s.length()!=n) return;
        int q=Integer.parseInt(reader.readLine());
        int qq;
        int []count=new int[q];
        char someChar;
        for(int j=0;j<q;j++)
        {
            qq=Integer.parseInt(reader.readLine());
            someChar=s.charAt(qq-1);
            for(int k=0;k<s.substring(0,qq-1).length();k++){
                if((s.substring(0,(qq-1)).charAt(k)==someChar)) count[j]++;
            }
            System.out.println(count[j]);
        }

        reader.close();
    }
}

2 个答案:

答案 0 :(得分:1)

对于长字符串(最多500000个字母)和许多查询(最多10000个)的有效解决方案,您需要以某种方式预处理字符串数据,以便在此之后可以快速处理每个查询。我建议对于26个可能的小写字母(问题明确表示为'a'-'z')中的每个字母,找到第1个,第2个,第3个出现的位置,等等,并将其填充到数组或列表中。然后对于每个查询,在数组中进行二进制搜索以找到您作为输入的位置。然后找到的数组索引将告诉您答案。这会将您的时间复杂度从 O(s ^ 2 * q)减少到 O(s + q * log(s) )

如果您不知道二进制搜索,请查找它。或使用Map<Integer, Integer>代替数组或列表。

仍然更有效,构建一个与字符串长度相同的数组,并在每个索引中存储有关该索引的查询的答案。我相信可以用 O(s + q)来实现。

快乐的编码。

链接:Original question on brainly.in

答案 1 :(得分:1)

除了Ole的答案,您还需要考虑一些“微”优化:

我怀疑大部分时间都将花在执行此循环上

for(int k=0;k<s.substring(0,qq-1).length();k++){
  if((s.substring(0,(qq-1)).charAt(k)==someChar)) count[j]++;
}

让我们看一下两个方面:

  • k<s.substring(0,qq-1).length()创建一个子字符串只是为了确定其长度。但是我们知道长度是多少:qq!因此,您没有充分的理由就创建了一个新字符串并复制了qq个字符。效率低下。毫无意义。

  • s.substring(0,(qq-1)).charAt(k)==someChar创建另一个字符串,然后获取其第k个字符。但是,子字符串的第k个字符也是原始字符串k的第s个字符。 (考虑一下!)因此,再次创建子字符串是没有意义的。

  • 这些不必要的计算均重复qq次。进行了2 x qq次相同的(不必要的)计算。

注意:此分析不考虑您的代码是正确的还是算法是最佳的。这纯粹是关于微效率。由于不必要的子字符串创建,您所做的就是将O(N^2)算法转换为O(N^3)算法...