这是一个面试问题。假设我们将工人的工作历史表示为字符串。每个字符串由N
个字符组成;每个字符都是{A
- “缺席”,L
- “迟到”和O
- “确定”之一。如果有两个“缺席”或三个随后的“迟到”,系统会发出警报。例如:AOOAO
- 引发警报,ALLOL
- 没有。
编写一个函数(用Java编写)来生成所有大小为N
的字符串,这会引发警报。
我建议循环遍历所有可能的“工作历史”字符串(很明显如何生成它们)并使用正则表达式过滤所需的字符串。
你会如何解决这个问题?
答案 0 :(得分:4)
这将是一种智能方法,不会检查任何内容,但只能直接生成正确的案例:
使用N-2天(即3 ^(N-2)组合)进行所有可能的变化。对于如此获得的每个变体,通过在每个可能的位置拼接“AA”来制作N-1个最终字符串(加上简单地附加在最后,这就是为什么它是N-1)。
重复N-3天并拼接“LLL”。
你们已经完成了。
现在我看到缺席不需要连续。这稍微改变了解决方案:在第一种情况下,你将独立地拼接两个“A”,首先拼接一个,然后将另一个拼接成结果字符串。
有一个非常对称的附加检查,可以在拼接时避免重复。在这两个步骤中,检查插入点左侧的字符。在步骤1中,如果它是A,则停止当前的拼接迭代(这也控制第二个A的拼接)。在步骤2中,如果它是L,则转到下一个插入点(跳过当前插入点)。
答案 1 :(得分:1)
这是一个类似于蛮力的解决方案,除了一些优化。我们的想法是创建所有可能序列的组合(由于必须返回警报字符串,因此无需额外费用)。然后跟踪报警条件(绝对没有正则表达式),以便只需要检查当前字符(参见#2)。一旦子字符串引发了警报,让我们说位置i,该函数可以继续为n-i字符创建组合而不检查警报条件。
3^N
)。numLate
,它将跟踪到目前为止系列中的连续'L'和变量numAbsences
,它将跟踪系列中的'A'数量,以便远。match == true
),请继续。numAbsences
。如果numAbsences > 1
,请设置match = true
。继续。numLate
,则设置为numLate = 0
。如果numLate > 2
,请设置match = true
。继续。在组合期间,当设置第N个字符时,如果match==true
返回当前字符串。否则,跳过,它不匹配。如果您在最后一个角色上并且到目前为止已经有0个缺席,则可以通过不检查缺席来进行额外(次要)优化。或者在组合的最后2个字符中,已经有0个晚了。
编辑:我发布了一个递归(groovy)解决方案。例如,Test.combination(0, new char[10], false, 0, 0);
会返回55513个组合,但不确定它是否正确。
class Test{
public static final char[] rep = ['O', 'A', 'L'];
public static void combination(int index, char[] arr, boolean match, int numLate, int numAbsence){
if(index==arr.length){
if(match)
println arr;
return;
}
for(int i=0;i<rep.length;i++){
arr[index] = rep[i];
if(!match){
boolean tempMatch = match;
int tempNumLate = numLate;
int tempNumAbsence = numAbsence;
switch(arr[index]){
case 'L': tempNumLate++; break;
case 'A': tempNumAbsence++; tempNumLate=0; break;
default: tempNumLate = 0; break;
}
if(tempNumLate > 2)
tempMatch = true;
if(tempNumAbsence > 1)
tempMatch = true;
combination(index+1, arr, tempMatch, tempNumLate, tempNumAbsence);
}else{
combination(index+1, arr, match, numLate, numAbsence);
}
}
}
}
答案 2 :(得分:1)
对于完全不同的东西,这里有一种方法可以生成所需的字符串,而不是其他任何东西。将其视为状态机,并使每个状态成为一个函数。非常冗长但直截了当。 (如果你做了很多这样的事情,你可以很容易地安排自动生成这段代码。)
因为我们被要求使用Java,所以这里是Java。 (我也在Perl中编写了相同的代码。我只是为.=
和chop
编写了一个字符串而不是StringBuilder
,它的运行速度比Java版快3倍。奇怪。)
import java.io.*;
public class ListAllAlarmedStrings {
static StringBuilder builder;
static int length;
public static void main(String[] args) throws IOException {
length = 5;
if (args.length > 0) {
try {
length = Integer.parseInt(args[0]);
} catch (NumberFormatException e) {
System.err.println("Argument" + " must be an integer");
System.exit(1);
}
}
builder = new StringBuilder(length);
for (int i = 0; i < length; i++)
builder.append("O");
stateA(0, 'A');
stateL(0, 'L');
stateNone(0, 'O');
}
static void stateNone (int pos, char chr) {
if (length < pos + 3)
return;
builder.setCharAt(pos, chr);
//System.out.println("stateNone " + pos + " " +builder.toString());
stateA(pos + 1, 'A');
stateL(pos + 1, 'L');
stateNone(pos + 1, 'O');
}
static void stateL (int pos, char chr) {
if (length < pos + 3)
return;
builder.setCharAt(pos, chr);
//System.out.println("stateL " + pos + " " +builder.toString());
stateA(pos + 1, 'A');
stateLL(pos + 1, 'L');
stateNone(pos + 1, 'O');
}
static void stateLL (int pos, char chr) {
if (length < pos + 2)
return;
builder.setCharAt(pos, chr);
//System.out.println("stateLL " + pos + " " +builder.toString());
stateA(pos + 1, 'A');
stateAlarmed(pos + 1, 'L');
stateNone(pos + 1, 'O');
}
static void stateA (int pos, char chr) {
if (length < pos + 2)
return;
builder.setCharAt(pos, chr);
//System.out.println("stateA " + pos + " " +builder.toString());
stateAlarmed(pos + 1, 'A');
stateAL(pos + 1, 'L');
stateA(pos + 1, 'O');
}
static void stateAL (int pos, char chr) {
if (length < pos + 2)
return;
builder.setCharAt(pos, chr);
//System.out.println("stateAL " + pos + " " +builder.toString());
stateAlarmed(pos + 1, 'A');
stateALL(pos + 1, 'L');
stateA(pos + 1, 'O');
}
static void stateALL (int pos, char chr) {
if (length < pos + 2)
return;
builder.setCharAt(pos, chr);
//System.out.println("stateALL " + pos + " " +builder.toString());
stateAlarmed(pos + 1, 'A');
stateAlarmed(pos + 1, 'L');
stateA(pos + 1, 'O');
}
static void stateAlarmed (int pos, char chr) {
if (length <= pos)
return;
if (length == pos + 1) {
builder.setCharAt(pos, chr);
System.out.println(builder.toString());
return;
}
builder.setCharAt(pos, chr);
stateAlarmed(pos + 1, 'A');
stateAlarmed(pos + 1, 'L');
stateAlarmed(pos + 1, 'O');
}
}