一定时间内控制登录次数的算法

面试经历

面试一家游戏公司,问到一个关于算法的问题,被卡住了,回去研究了下发现,其实思路只差了一部
直接上代码

/**
* 一定时间内登录次数的控制
* 实现方案:将每次的登录次数和登录时间以键值对的形式放在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:该算法仅仅是解决了基本的登录控制,其实在实际应用场景中还有其它问题。
    比如随着登录次数的不断增加,两个索引值会不断增大。但是数据都是有一个最大值的,是否需要考虑在某个时机去重置该索引以及登录数据?或者有更好的方式去避开这种无限增长的方式?

当时通过分别通过次数控制和时间控制单方面的去分析,总是被面试官推翻,就没有想到把它们结合起来去分析,真是太遗憾了。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值