民生银行IT类技术笔试题解析

来源:互联网 发布:网络运营的工作内容 编辑:程序博客网 时间:2024/04/19 04:45

时间:2014.04.30

地点:基地二楼

————————————————————————————

一、板块前言

  从今天起,我想去一有时间去做这件更有意义的事,一方面可以为之解析银行笔试中的所有问题,二是也还可以巩固自己,望能取互取彼此之长补彼此之短而共同进步。

————————————————————————————

二、关于银行IT技术类笔试

  大概了解了下,就银行IT技术类的笔试而言,考查范围包括编程语言、数据结构、数据库、网络协议、软件工程、操作系统,虽然内容也好多,但都还基础,慢慢看多了接触多了这些都不是问题,覆盖内容还是很多,所以也还是要尽早沉得下心和有信心去准备。

————————————————————————————

三、笔试题详解

1、TCP/IP协议通过什么方式判别不同的进程。

解答:这是一道考查网络协议的题,有一本书叫做《TCP/IP详解(卷1:协议)》,里面详细介绍了TCP/IP协议原理。

TCP/IP是一个互联网通信协议,所有互联网上的终端只有遵循这个协议才能交互数据,协议就像立下来的一个规则,大家各自按这套规则办事,才能有效进行信息交流。

进程,是一个应用程序实体,是程序运行所需资源分配的一个基本单位。首先程序不能在操作系统(OS)中独立运行,要想运行,首先得操作系统为之创建一个进程,进程中包含了程度段(程序代码)、相关的数据段和一个进程控制块。这个过程即把程序运行所需的资源都包装成一个进程,还为之创建一个管理和控制进程的模块。

答案:TCP/IP协议是分了四层,最顶层是应用层,这里是应用程序,比如我们的QQ,接下来是运输层,这里是TCP和UDP两个协议,负责将应用层要发送出去的信息进行分片,相当于是生产线上的好多产品,先做一次简单的包装,但是这里有一个问题是我们系统的程序那么多,到底是哪个程序的数据要做一个标志,TCP UDP规定使用一个16bit的端口号来表示应用程序,表示数据来自是来自你的QQ呢还是MSN,还要加上目的端口号,表示你是想将数据发给QQ呢还是MSN,即TCP/IP协议采用端口号的方式来判别不同的进程。在下一层是网络层,这里是IP协议,还有ICMP,IGMP,当然IP是最重要的,这一层是继续将上面的包装过后的数据再封装一次,加上源地址和目的地址,好比快件,在这层要填上寄件人收件人,最后一层是数据链路层,差不多就是把刚刚打包的快件放到车上,发出去。


2、URL可以对应于几个IP地址

解析:URL即网页地址,俗称网址,术语叫统一网络资源定位器,比如:IP是计算机在网络中的门牌号,并且是唯一的,域名是这个门牌号码的文字形式表达,比如域名:就是域名,对应的IP为:61.135.185.29,你可以在cmd命令下ping这个域名或IP,效果都是一样的。也就是说URL的域名是IP的文字化表现,与IP对应,一个域名只能对应一个IP,多个域名可以被解析到同一个域名,成多对一的姿态。但URL不只是IP,比如这里的http表示的是http协议,然后跟着是域名以及需要访问的路径参数等。这里的答案是:一个。



3、查询数据库的时候,在什么情况下可能会导致死锁。

  锁是一个操作系统、多线程编程都涉及的重要概念,主要是为了解决多任务对临界资源的争用问题。比如打印机在打印任务时,打印机这是一个临界资源,只有一台,但可能有多台计算机同时给这台打印机下达打印任务,这时就要讲究临界资源的分配问题了,不然,多个打印任务的数据同时来不就乱了吗,一般来说,先来的任务线占据这台打印机执行任务,并上锁处理,别的任务一看到打印机上锁了就只能排队等待,打印机的某个任务完成后应该及时解锁,让后面正在排队等待的任务可以获得锁而执行任务。

  以同样的态度,我们来看一个银行业务系统,你可能在某银行开了两张借记卡A和B,存款分别为100和200,某天你想从账户A上取出钱50块存入账户B中,我们记这个事件为任务TaskOne,当然理所当然的最终结果是账户A只有50块,B账户上有250块,若是我们还有一个任务TaskTwo,即某个终端显示账户A和账户B的总金额,当然,理想情况是不变的总是300,但事实并非如此,若是这两个任务顺序执行,先执行TaskOne和TaskTwo,那么是没有任何问题的,但显示中,这两个任务是并行执行的,便可能有这种情况发生:当系统从A账户上扣掉50块时,A账户还剩50块,但你要转的50块还没到账户B上,账户B还是200,这时TaskTwo已经进行了一次操作,将账户A和账户B的总金额计算显示,于是显示金额为,250。造成这种结果的原因是TaskOne和TaskTwo是两个互不相干的任务,各自执行各自的,但访问的资源却是共享的,于是中间就出现了问题。现在假设我们有一把锁,当TaskOne任务从账户A中扣款时,我们对账户A加锁,不准其他任务访问,直到账户A上的现金已经到达账户B上,TaskOne再解锁,未解锁时TaskTwo是不能访问账户A上有多少现金的,只能排队等待,通过这种锁的机制,于是就可解决这种不同步的问题。

  然而,现在问题又有了,假设TaskOne任务执行时先后需要对资源ResourceOne和资源ResourceTwo进行访问,并且当前正在对资源ResourceOne访问,按前面的意思,访问时对它上了锁,在释放锁之前别的任务不能访问ResourceOne,只能排队等待。类似的,有任务TaskTwo需要先后对资源ResourceTwo和资源ResourceOne访问,当前正访问ResourceOne,也对其上了锁防止其他任务访问,于是问题来了,到了某一时刻,TaskOne还需要访问ResourceTwo,但被TaskTwo上锁,只好排队等,而恰好TaskTwo又需要访问ResourceOne,却被TaskOne上锁,也需等待,于是各自占据资源各自等待对方解锁,哪个一个任务都不能正常执行,这就是死锁。一个解决死锁的方式就是事物回滚,使得某个事物占据的资源解锁,从而是任务继续。这就是在一条比较窄的马路上开车,两车相遇,都需要这一段路的空间,我等着你开过,你等着我开过,最后谁也开不过,只有某一方后退几步,各自都能顺利通过。


4、软件工程里面:软件开发阶段包括哪些内容

一般是需求分析 软件设计 编写代码 软件维护 四个阶段吧,各有各的说法,但基本一致。《代码大全》列细的列出了十来条。


5、黑盒白盒测试的功能

第一次听说,这是关于软件测试方面的内容,可参考这篇文章

http://blog.csdn.net/ningmeng2010/article/details/8114530


6、哈弗曼编码,求编码后的平均长度

离散数学里的问题,网上这个题目没给完整,应该是蛮简单的。


7、排序算法的稳定性归类

所谓的稳定性是指当两个数想等排序后的先后位置是否和排序前保持一致,比如有两个数,A1在A2前面,排序时,我们会进行大小比较,知道A1=A2,经过排序后A1还是放在A2前面,这样的排序就是稳定的。反之不稳定。

不稳定排序:选择、快排,堆排,希尔排序;

稳定的排序:归并、冒泡,插入,基数排序;

(一句话:选快堆希 归冒插基,还蛮押韵的,同时各类排序算法的时间复杂度也是很重要的,总结如下表)



8、链表的删除

  删除链表时,我们往往实现知道的是链表头结点指针head_ptr,于是顺着头结点,我们一边移动头结点一般往下面删除就好。C++的实现如下

void ListClear(node* &head_ptr){  while(head_ptr!=nullptr)   {        node* remove_ptr=head_ptr;        head_ptr=head_ptr->get_link();        delete remove_ptr;    }}

C的实现如下

void ListClear(node* *head_ptr){  while(head_ptr!=NULL)   {        node* remove_ptr=head_ptr;        head_ptr=head_ptr->link;        free(remove_ptr);    }}
  上述两种不同实现方式不管是C++版本的指针引用也好,还是C的指针的指针也好,主要目的是在删除过程中我们要修改头指针的值。拿C版本指针的指针来说,因为我们在删除过程中,删除都都是头结点head_ptr当前指向的节点,每删除一个节点,我们的头指针都要指向一个新的节点,把它当成链表的新的头节点。当我们需要修改指针的值的时候我们需要二级指针(是需要不是必要,但最好还是用二级指针),可以想象,比如我们需要修改一个常规变量的值时,我们可以通过一级指针去修改它,现在我们有一个一级指针类型的变量,我们也想修改这个变量的值,那么就需要通过一个指向该变量类型的指针,由于该变量是指针类型的,于是即需要指向指针的指针了,是吧~


9、TCP的三次握手
  TCP握手协议中计算机网络里很重要的一个知识点,具体可细看《TCP/IP详解,卷1:协议》一书。就像我们打电话,第一阶段:你首先要拨号,发出通话链接信号,第二阶段:对方看到有来电显示了,摘下电话,说“喂”,第三阶段你听到对方的“喂”,也说一个“喂”,于是通信就建立好了,可自由聊天说话了。TCP的三次握手很类似,它涉及客户端和服务端,服务端提供服务。

a.第一次握手是客户端发送请求(即我想和你进行通话),这个请求在报文里含有一个同步序号SYN段,同时指明想要打开的服务器端口,服务器上有好多端口。TCP是也是靠SYN标识对报文进行计数的,最后靠此序号来对数据报文重排序,同时该报文的SYN位会置1,表示这是一个发起握手的信号。

b.第二次握手服务端对客户端请求进行确认(即我知道你想和我通话了,我已经准备好了)。当服务端收到客户端发来数据包时,看到SYN位为1,知道有人申请服务,于是也发送一个类似的SYN段报文,并且还对刚刚收到的信息做出应答,即在报文中确认序号上填充刚刚收到的那个同步序号+1,并将syn位和ack位都置1,表示这是一个应答信号。

c.第三次握手客户端收对服务端的应答信号进行确认(服务端是说准备好了,但客户端准备好没好还没告诉服务端啊,所以这次握手是客户端告诉服务端,我知道你准备好了,现在我也准备好了,我们通话吧)。客户单收到服务端的回传的确认信息后,也还要再次确认,首先检查服务端发过来的确认序号是不是对的,以及位码ack是否为1,确认正确后,客户端也向服务端回复一个确认信息,即确认序列为刚刚服务端发来的同步序号+1,同时ack位置1。

这样三次握手完成,双方就可以顺利通信了。整个过程如下:


10、建数据库表,要求:有三个字段,c1,c2字符类型,c3,c4是整型,c5是日期类型,c2不能为空,c1 是主键

create table my_table( c1 varchar(10),  c2 varchar(10) not null,  c3 int,  c4 int,  c5 datetime,  primary key(c1));

11、查询满足条件的数据:这个属于很简单的查询操作 

用select语句,格式是:

select xxxfrom my_tablewhere xxx;

以上两个题都是考查的数据库查询语言SQL,作为银行软件开发,懂数据库知识我觉得还是很重要的。


12、输出字符串中第一个只出现一次的字符,用两种方案。

思路:我这里想了两种实现方式

版本1的思路是:设立了一个128大小的数组,用于对字符串中出现的字符进行计数,为什么用128的大小呢,因为我们知道有128个字符,于是我们把每一个可能出现的字符都对应一个计数器,字符出现几次,我们就对对应的计数器计数几次,没出现就计数为0,那么,我们只要对字符串遍历一次,就可对出现的每个字符都统计好,然后在遍历一次字符串,对于每个字符我们去查看对应的计数器,一旦碰到计数器为1则说明该字符是第一个在字符串中只出现一次的字符,这个算法时间复杂度为O(n)。

版本2的思路:我一般是对字符串中的每个字符进行遍历,针对每个字符,然后去看后面还有没有出现,没有出现则表明这是第一个在字符串中只出现一次的字符,这个算法的时间复杂度为O(n*n)。

两个版本的实现如下:

#include<iostream>#include<string>using namespace std;void PrintFirstOnceCharacter1(const string& str)//版本一{unsigned char_count[128] = { 0 };for (auto ch : str)++char_count[ch];for (auto ch : str){if (char_count[ch] == 1){cout << ch << endl;break;}}}void PrintFirstOnceCharacter2(const string& str)//版本二{for (size_t i = 0; i < str.length(); ++i){bool is_first_once_char = true;for (size_t j = i+1; j < str.length(); ++j){if (str[i] == str[j]){is_first_once_char = false;break;}}if (is_first_once_char){cout << str[i] << endl;break;}}}int main(){string str;cin >> str;PrintFirstOnceCharacter1(str);//调用第一个版本PrintFirstOnceCharacter2(str);//调用第二个版本return 0;}







0 0