(1)题目
(2) 分析
即,起点和终点都移动。
1. 假设数组w表示英文描述,数组q表示关键字,数组isfind表示记录数组q中的单词是否在w中出现
2.依次遍历数组w中的每一个单词(s表子数组第一个下标 e表子数组最后一个下标)
2.1 判断当前单词i是否在关键字数组q,如果在则标记为1;如果不在 继续向下遍历s++;
2.2 如果数组q中的单词全都在w中出现,则记录当前子数组长度
代码有问题
import java.util.Scanner;
public class Main {
/*
* 思路:
* len、begin、end分别表示当前包含所有关键字的子数组最短长度、起始下标
*
*
* 目的:求文字描述数组w中 包含关键字数组q中所有元素的 最短子数组(w中包含q元素的子数组可以与q中的顺序不同,包含即可)
*
* 代码问题:不能处理关键中有相同单词的情况。例如:wo wo ni
* */
public static void main(String[] args){
//1.输入相关数据
String[] q = {"ai","co","hu"}; //关键字数组
String[] w = {"o","ai","wo","co","pl","gj","hu","ai","u","ai","hu","co"}; //文字描述数组
//2.遍历数组w,寻找最短的子数组
int len=Integer.MAX_VALUE,begin=-1,end=-1;
int p2=-1;//标记上一个子数组的结束下标
for(int i=0;i<w.length;i++) {
int[] isfind = new int[q.length];//记录当前w中的单词是否在q中出现
//2.1 寻找当前子数组的第一个单词是否在q中出现过,i表示当前子数组的开始下标
String w1 = w[i];
int in = indexof(w1,q);//判断单词w1是否在关键字数组中,返回在数组q的下标
if(in==-1) {//不在,退出本次循环
continue;
}else {//在,在数组isfind中标记,此时i作为当前子数组的开始下标
isfind[in]=1;
}
//2.2 寻找剩余q中的单词在当前子数组中是否出现过
int j;//指向上一个子数组结束下标的位置
if(p2==-1) {
j=i+1;
}else {
j=p2;
}
for(;j<w.length;j++) {
String w2 = w[j];
int in2 = indexof(w2, q);//判断当前单词w2是否在q中出现
if(in2==-1 || isfind[in2]==1) {//未出现 或 之前已经出现
continue;
}else {//第一次出现
isfind[in2]=1;
if(sum(isfind)==q.length) {//所有的关键字都在当前子数组中出现过
p2=j;
if(j-i+1<len) {//小于当前最小长度
len = j-i+1;
begin=i;
end=j;
}
break;//在当前子数组中已找到所有的关键字,退出for
}
}
}//for
}//for
print(w,begin,end);
}
//打印数组w中下标在begin~end之间的单词
private static void print(String[] w, int begin, int end) {
for(int i=begin;i<=end;i++) {
System.out.print(w[i]+" ");
}
}
//计算数组的元素和
private static int sum(int[] isfind) {
int sum=0;
for(int i=0;i<isfind.length;i++) {
sum+=isfind[i];
}
return sum;
}
//判断元素w1在数组q中的下标
private static int indexof(String w1, String[] q) {
for(int i=0;i<q.length;i++) {
if(q[i].equals(w1)) {//出现相同单词
return i;
}
}
return -1;
}
}