九宫格----记网易游戏2015年研发类笔试题

最近一直在找工作,昨天参加了网易游戏的研发类笔试,题量比较大,大题有6个。

1.最小字典序字符串,

2.递归绘图函数转非递归

3.游戏编程中常用的数据结构4叉树,有三问,一问是写出如何判断点在矩形中和判断两矩形是否相交,第二问是写创建四叉树的实现,第三问是如何根据已知的矩形块,在四叉树中寻找包含的物体。

4.KD树,英文题,没怎么看,第一问问给出的一个算法的复杂度,并分析;第二问是自己实现算法(没怎么看)

5.求带权二叉树的最长路径,权值可以为负值

6.九宫格,就是手机手势密码。有三问,一问是如果只设置2位密码,有多少种满足的密码,密码不能穿越,比如1 3之间穿过2,这是不允许的;第二问,如果变成N*M格,判断一个2位密码是否是满足要求的密码(要求同1),第三问,如果设置密码位数为9位,有多少种合适的密码,给出算法思路,并给出伪代码。

当时最后一题写的有点仓促,写的用DFS实现,类似全排列实现,只不过递归过程中剔除不符合要求的即可(相当于剪枝吧),伪代码写的稀烂,今天周末自己在电脑上写出来了。跟大家分享一下。

分析一下九宫格如下图所示

1   2   3

4   5   6

7   8   9

不难看出,可以把所有点分成三类:

1 3 5 9为一类,2 4 6 8 为一类,5单独为1类。

第一类点,任意2点都不能互联,但是如果两点之间的已经用过,这时是可以互联的,这点一定要注意。

第二类点,2 8 是不能直接连的,4 6也是不行的,但是如果5已经用过,它们就变成可以连接的点了。

第三类点只有5一个,它与所有点之间都是可以直接连的。

求全排列的算法,网上有2中,一种是递归算法,另一种是非递归算法。不清楚的请百度之,博客园里也已经有很多大牛写过博客了,不再赘述。

我采用的是简单的递归算法,一是思路比较清晰,也好理解。并且此题深度不大,只有9,故DFS是可以的。

具体代码如下:

 1 int dfs(int* a,bool* flag,int k,int n)
 2 {
 3
 4     int sum = 0;
 5     if (k>=n)
 6     {
 7 #if 0
 8         for (int i=0;i<k;i++)
 9         {
10             cout<<a[i];
11         }
12         cout<<endl;
13 #endif
14         return 1;
15     }
16     else if (k<n)
17     {
18         for (int i=1;i<=9;i++)
19         {
20             if (!flag[i])
21             {    //检测是否合适
22                 if(check(a,flag,i,k))
23                 {
24                     flag[i]=true;
25                     a[k]=i;
26                     sum+=dfs(a,flag,k+1,n);
27                     flag[i]=false;
28                 }
29             }
30         }
31         return sum;
32     }
33 }

其中数组a保存已经确定了的密码序列,flag数组flag[i]表示数字i是否已经使用过,flag[0]未用。#if 0 …… #endif代码段用于打印出合适的密码序列。

k表示已经确定了前k-1个数,现在准备确定第k个满足要求的数。n表示密码长度,如果要求满足要求的2位,3位等等密码,可以直接设置成相应的值即可。

最重要的算法就是其中的check函数,也就是检测密码是否满足题意。

check算法的思路我上面已经做过分析,这里直接给出实现。需要注意的是,我们只需要判断即将确定位置的数a[k]和前一个数a[k-1]的组合的合法性即可,

为什么呢?因为这是一个递归的算法,也就是说前k-1个数构成的序列是一步步确定合法的序列,所以只需要判断从a[k-1]到a[k]是否合法即可。代码如下:

 1 bool check(int* a,bool* flag,int i,int k)
 2 {
 3     if (k==0)//确定第一个数字,任意数字都是合法的
 4     {
 5         return true;
 6     }
 7     if(i%2==1&&i!=5 && a[k-1]%2==1&&a[k-1]!=5)//a[k-]和i都属于1,3,7,9
 8     {
 9         return flag[(i+a[k-1])>>1];
10     }
11     else if (i%2==0 && a[k-1]%2==0)    //a[k-]和i都属于2,4,6,8
12     {
13         if (a[k-1]+i==10)
14         {
15             return flag[5];
16         }
17         return true;
18     }
19     else//其他情况
20     {
21         return true;
22     }
23 }

好了,这道题就这么解决了,22分的题目,难度倒不是很难,还是值得分析一下的。而且通过这个可以清楚得到我们的手势密码一共有多少种(九宫格)。如果是破解的话,真的很简单,这里给出整个测试的源码。

#include <iostream>
using namespace std;
bool check(int* a,bool* flag,int i,int k)
{
    if (k==0)//确定第一个数字,任意数字都是合法的
    {
        return true;
    }
    if(i%2==1&&i!=5 && a[k-1]%2==1&&a[k-1]!=5)//a[k-]和i都属于1,3,7,9
    {
        return flag[(i+a[k-1])>>1];
    }
    else if (i%2==0 && a[k-1]%2==0)    //a[k-]和i都属于2,4,6,8
    {
        if (a[k-1]+i==10)
        {
            return flag[5];
        }
        return true;
    }
    else//其他情况
    {
        return true;
    }
}

int dfs(int* a,bool* flag,int k,int n)
{

    int sum = 0;
    if (k>=n)
    {
#if 0
        for (int i=0;i<k;i++)
        {
            cout<<a[i];
        }
        cout<<endl;
#endif
        return 1;
    }
    else if (k<n)
    {
        for (int i=1;i<=9;i++)
        {
            if (!flag[i])
            {    //检测是否合适
                if(check(a,flag,i,k))
                {
                    flag[i]=true;
                    a[k]=i;
                    sum+=dfs(a,flag,k+1,n);
                    flag[i]=false;//此处注意恢复flag的标志
                }
            }
        }
        return sum;
    }
}

int main()
{
#if 0
    freopen("out.txt","w",stdout);
#endif

    int a[9]={0};
    bool flag[10]={false};
    int sum = 0;
    for(int i=4;i<=9;i++)
    {
        sum+=dfs(a,flag,0,i);
    }
    cout<<sum<<endl;
}

给出4位到9位手势密码总数389112,程序运行很快,有兴趣的可以运行看看,所以手势密码真的安全吗?留给大家去思考!

有兴趣的也可以做个GUI,然后看看所有的手势密码,肯定有一些比较霸气的!

时间: 2024-08-13 14:23:42

九宫格----记网易游戏2015年研发类笔试题的相关文章

阿里2016校招研发类笔试题php

一. 选择题 40分钟: 1.某操作系统采用分页存储管理方式,下图给出了进程A和进程B的页表结构.如果物理页的大小为512字节,那么进程A与进程B的物理内存总共使用了__字节. 进程A页表: 进程B页表: 逻辑页 物理页 逻辑页 物理页 0 9 0 1 1 2 1 3 2 4 2 4 3 6 3 7 4 4 2 5 5 4608 3584 4096 5120 2560 2048 2.以下函数中,和其他函数不属于一类的是__. fwrite putc pwrite putchar getline

公司真题-浩鲸科技2019校招普通研发类笔试题

感悟:好奇怪的题目,怎么还考察了css,难顶......不过数据库考察的挺详细,感觉挺不错的 资源的有序分配策略破坏(   )条件,是一种死锁预防策略. 正确答案: D 你的答案: B (错误) 互斥条件 保持和请求条件 不剥夺条件 环路等待条件 题解:互斥:一段时间只能一个人访问 请求和保持:就算有进程访问一个资源,原先占有进程也保持占有该资源不放. 不剥夺:资源不能被剥夺 环路等待:p0等待p1资源,p1等p2,p2等p0 在公司局域网上ping www.iwhalecloud.com没有涉

阿里2015在线研发工程师笔试题(部分)

今天lz去阿里的在线笔试打了一把酱油,由于lz的水平有限,时间太他么紧张了.下面把记下来的题给大家分享一下.选择题总共20道,前十题截了图,后面感觉太费时就没有再截了,凭记忆记下了两道.附加题都记录下来了. 选择题 第1题: 第2题: 第3题: 第4题 第5题: 第6题: 第7题: 第8题: 第9题: 第10题: 回忆起来的题(11-20中的某2道) 1.       一个博物馆,以每分钟20人的速度进入,平均每人待20分钟,问博物馆最少需要容纳多少人? A.100 B.200  C.300 

最长连续字母序列的长度(阿里2015在线研发工程师笔试题)

给定一个query和一个text,均由小写字母组成.要求在text中找出以同样的顺序连续出现在query中的最长连续字母序列的长度.例如, query为“acbac”,text为“acaccbabb”,那么text中的“cba”为最长的连续出现在query中的字母序列,因此,返回结果应该为其长度3.请注意程序效率. 直接暴力,时间复杂度:m*n*n int Solve(char qu[],int n,char te[],int m) { int i,j; int k,p; int Max; in

2015微软实习在线笔试题 - Professor Q&#39;s Software

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 Professor Q develops a new software. The software consists of N modules which are numbered from 1 to N. The i-th module will be started up by signal Si. If signal Si is generated multiple times, the i-th module

js+html+css实现简单页面交互功能(2015知乎前端笔试题)http://v.youku.com/v_show/id_XMTI0ODQ5NTAyOA==.html?from=y1.7-1.2

js+html+css实现简单页面交互功能(2015知乎前端笔试题) http://v.youku.com/v_show/id_XMTI0ODQ5NTAyOA==.html?from=y1.7-1.2 密码:hellozhihu

【新鲜出炉的,快到碗里来】2015腾讯实习产品类笔试题

昨晚做了2015腾讯实习产品类在线笔试题做题做到累觉不爱啊各种时间不够觉得智商捉急啊 为了攒rp,lz截屏截到手抽筋啊,统统发上来在线测试包含: 评估名称 您需要的全部时间 您需要什么 数字推理测试 45分钟 计算器,笔和纸,鼠标 语言推理测试 45分钟 鼠标 逻辑推理测试 45分钟 笔和纸,鼠标 性格问卷 25分钟 鼠标 邮件里时间这么长,其实不是啊~是25+19+25min(见附件~) 总结起来,其实题目不难我练习部分正确率挺高的8题错1-2题但是练习题时间没限制而且也比实际考试题简单我前面

2015年阿里巴巴校招笔试题

校招找工作的同学,可以看看,非常有帮助! 推荐: http://gointernetgo.com/textinterview/bishi-2015-alibba [产品经理]阿里巴巴2015校园招聘笔试题 [研发工程师]阿里巴巴2015校园招聘笔试题 [研发工程师]阿里巴巴2015校园招聘笔试题2 [国际安全运营专员]阿里巴巴2015校园招聘笔试题1 [产品运营]阿里巴巴2015校园招聘笔试题1 [前端开发工程师]阿里巴巴2015校园招聘笔试题1 [前端开发工程师]阿里巴巴2015校园招聘笔试题

2015阿里校招研发工程师笔试题

1.C++内存分配中说法错误的是() A 对于栈来说,生长方向是向上的,也就是向着内存地址增加的方向 //错,对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向:对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长. B 对于堆 ,大量的new/delete操作会造成内存空间不连续 //对,对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低.对于栈来讲,则不会存在这个问题,因为 //栈是先进后出的队列,他们是如此的一一对应,以至