面试经历
面试一家游戏公司,问到一个关于算法的问题,被卡住了,回去研究了下发现,其实思路只差了一部
直接上代码
/**
* 一定时间内登录次数的控制
* 实现方案:将每次的登录次数和登录时间以键值对的形式放在Map中,登录时通过与第一次的比较判断是否可以再次登录
* @author Administrator
*
*/
public class Demo2 {
//登录起点索引
private int loginStartIndex = 0;
//最后一次登录索引
private int loginEndIndex = 0;
//最大登录次数
private int maxTime = 6;
//最大登录间隔(ms)
private int maxLoginTime = 30000;
private Map<Integer, Long> loginTimeMap = new HashMap<Integer, Long>(maxTime);
public boolean login(){
long nowTime = System.currentTimeMillis();
if(0 == loginStartIndex){
//首次登录,直接放在Map变量中,并定位计算起点和终点
loginStartIndex ++;
loginTimeMap.put(++ loginEndIndex, nowTime);
System.out.println("登录成功!");
return true;
}else{
return this.controlLoginTimes(nowTime);
}
}
/**
* 控制登录次数
* @param nowTime
* @return
*/
private boolean controlLoginTimes(long nowTime) {
//把目前符合规则的已登录次数取出来
int times = loginTimeMap.size();
if(times < maxTime){
//登录次数符合规则,校验登录时间是否超出限制时间
if(!((nowTime - loginTimeMap.get(loginStartIndex)) <= maxLoginTime)){
loginTimeMap.remove(loginStartIndex ++);
}
loginTimeMap.put(++ loginEndIndex, nowTime);
System.out.println("登录成功!");
return true;
}else{
//之前的登录次数刚好符合规则,本次的登录时间必须大于周期内的第一次登录时间
if((nowTime - loginTimeMap.get(loginStartIndex)) > maxLoginTime){
//删除最早的记录,以它的下一个作为新的起点
loginTimeMap.remove(loginStartIndex ++);
//更新最新的登录时间
loginTimeMap.put(++ loginEndIndex, nowTime);
System.out.println("登录成功!");
return true;
}else{
System.out.println("登录失败,违反登录规则,请在" + ((maxLoginTime - (nowTime - loginTimeMap.get(loginStartIndex))))/1000 + "秒后重试");
return false;
}
}
}
}
public class Demo2Test {
public static String flag = "N";
/**
* @param args
*/
public static void main(String[] args) {
Demo2 d2 = new Demo2();
Scanner scanner = new Scanner(System.in);
System.out.println("是否登录?是:Y/否:N");
flag = scanner.next();
while("Y".equals(flag)){
d2.login();
scanner = new Scanner(System.in);
System.out.println("是否登录?是:Y/否:N");
flag = scanner.next();
};
scanner.close();
}
}
测试结果
是否登录?是:Y/否:N
Y
登录成功!
是否登录?是:Y/否:N
Y
登录成功!
是否登录?是:Y/否:N
Y
登录成功!
是否登录?是:Y/否:N
Y
登录成功!
是否登录?是:Y/否:N
Y
登录成功!
是否登录?是:Y/否::N
Y
登录成功!
是否登录?是:Y/否:N
Y
登录失败,违反登录规则,请在25秒后重试
是否登录?是:Y/否:N
Y
登录失败,违反登录规则,请在23秒后重试
是否登录?是:Y/否:N
Y
登录失败,违反登录规则,请在13秒后重试
是否登录?是:Y/否:N
Y
登录失败,违反登录规则,请在7秒后重试
是否登录?是:Y/否:N
Y
登录失败,违反登录规则,请在3秒后重试
是否登录?是:Y/否:N
Y
登录成功!
是否登录?是:Y/否:N
Y
登录成功!
是否登录?是:Y/否:N
N
PS:该算法仅仅是解决了基本的登录控制,其实在实际应用场景中还有其它问题。
比如随着登录次数的不断增加,两个索引值会不断增大。但是数据都是有一个最大值的,是否需要考虑在某个时机去重置该索引以及登录数据?或者有更好的方式去避开这种无限增长的方式?
当时通过分别通过次数控制和时间控制单方面的去分析,总是被面试官推翻,就没有想到把它们结合起来去分析,真是太遗憾了。。。