1. 程式人生 > >民生銀行IT類技術筆試題解析

民生銀行IT類技術筆試題解析

時間: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、黑盒白盒測試的功能

第一次聽說,這是關於軟體測試方面的內容,可參考這篇文章

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 xxx
from my_table
where 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;
}