阿里雲數據庫內核面經(已拿offer)

座標polarDB,阿里雲數據庫內核組。
自己在過年後光速寫了個小的數據庫當項目,也算是彌補了項目經驗上的不足。

簡歷面

  1. 編譯器是怎麼優化的
  2. 手擼內存分配器
    通過一個數組來管理資源,需要使用時從數組中分配一個成員,使用完畢後從數組中釋放該成員,釋放後的成員可以被再次分配使用;請實現一個結構用來快速的對資源進行分配和釋放。
  3. 聊項目

一面

  1. 說說 const char *ptr 和 char const *ptr的區別
  2. 寫出一個包含以下元素的結構體的大小
	char a;
	char b;
	double c; 
	int d; 
  1. static的作用
  2. 宏和inline區別
  3. 說說純虛函數和虛函數
  4. new和malloc區別
  5. 說出以下代碼每行的作用和運行結果
char *p = (char *) malloc(10); 
sizeof(p)= 4
free(p+1)
  1. 手擼算法:最大子矩陣和,我是用 O(n3)O(n^3) 的做法寫出來的
  2. 口述算法:N個數,有一個數出現超過N/2,尋找這個數
  3. 口述算法:鏈表倒數第K數
  4. 靜態鏈接庫和動態鏈接庫的區別
  5. epoll和select的作用
  6. 手擼多線程編程題:隊列取數和放數交替操作(具體的記不太清了)
  7. 聊項目,因爲自己的項目是實現了一個小的關係型數據庫,正好這是數據庫內核組,於是就…被花式吊打

二面

  1. 聊大一時候的圖像檢索的項目
  2. 聊數據庫這個項目
  3. 手擼算法題:
    按段(段內的元素不翻轉)翻轉鏈表:如鏈表 1->2->3->4->5->6->7->8->9,如果段大小爲3,翻轉後爲7->8->9->4->5->6->1->2->3。
    注意段大小作爲參數傳入。要求編寫可以運行的測試用例(有main函數和足夠的測試集),注意代碼規範。

三面

  1. Linux系統怎麼看cache的相關信息
  2. 什麼情況下內容會存進cache,怎麼看cache的內容
  3. 聊項目。。。
  4. 算法題1:找二叉樹最深的節點
  5. 算法題2:遍歷二叉樹最底層的節點
  6. 算法題3:在一個無向圖中,如何判斷兩點是否聯通
  7. 算法題4:在一個有向圖中,如何判斷兩點是否聯通

這一面還是比較簡單的,幾個算法題就是dfs、bfs來回考,判聯通可以用並查集操作一下。

四面

  1. 聊項目
  2. 進程和線程區別
  3. 進程間的通信方式
  4. 如何調試C++多線程程序
  5. 聊人生

五面(hr面)

  1. 自我介紹
  2. 自己擅長什麼不擅長什麼
  3. 聊聊ACM經歷
  4. 說說自己的學校怎麼樣
  5. 自己成績怎麼樣
  6. 人生最大的挫折是什麼

個人代碼

因爲阿里伯樂寫代碼是有存檔的,所以就貼一下方便大家指教。

內存分配器

//通過一個數組來管理資源,
//需要使用時從數組中分配一個成員;
//使用完畢後從數組中釋放該成員,釋放後的成員可以被再次分配使用;請實現一個結構用來快速的對資源進行分配和釋放。

// 10000這種數字是跟面試官溝通以後隨便寫的
class memory_manage {
public:
	obj* m_malloc() {
		obj* p = nullptr;
		if(l.size()) {
			p = l.front();
			l.erase(l.begin());
		} else if(cur<10000) {
			p = &arr[cur++];
		}
		return p;

	}

	void m_free(obj* p) {
		l.push_back(p);
	}

private:
	obj arr[10000];
	int cur = 0;
	list<obj*> l;
};

最大子矩陣和

N * N

-10 1 2 3
2 3 4 -100
1 2 3 5
0 0 0 0

K*M
和最大的子矩陣

O(N^2)
第一步:矩陣前綴和O(n^2)
第二步:遍歷子矩陣O(n^4)

int a[N+2][N+2];
int sum[N+2][N+2];

void FindMax(int n) {
	int cur = 0,ans = 0;
	memset(sum,0,sizeof(sum));
	for(int i=1; i<=n; i++) {
		for(int j=1; j<=n; j++) {
			sum[i][j] = sum[i-1][j] + a[i][j];
		}
	}
	for(int i=1; i<=n; i++) {
		for(int j=1; j<=n; j++) {
			cur = 0;
			for(int k=1; k<=n; k++) {
				cur = cur + (sum[j][k]-sum[i-1][k]);
				if(cur<0) cur = 0;
				else ans = cur;
			}
		}
	}
	return ans;
}

多線程題

mutex g_mutex;
condition_variable cv;
queue<int> q;
bool flag = 0; // 0放,1取

int get() {
	lock_guard<mutex> mtx(g_mutex);
	cv.wait(mtx,[] {return flag==1;});
	int val = q.front();
	q.pop();
	flag = 0;
	cv.notify_one();
	return val;
}

void put(int val) {
	lock_guard<mutex> mtx(g_mutex);
	cv.wait(mtx,[] {return flag==0;});
	q.push(val);
	flag = 1;
	cv.notify_one();
	return;
}

花式翻轉鏈表

// 評測題目: 按段(段內的元素不翻轉)翻轉鏈表:如鏈表 1->2->3->4->5->6->7->8->9,
// 如果段大小爲3,翻轉後爲7->8->9->4->5->6->1->2->3。注意段大小作爲參數傳入。
// 要求編寫可以運行的測試用例(有main函數和足夠的測試集),注意代碼規範。

#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;

struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x):val(x),next(NULL){}
};

struct BlockList {
    ListNode *LeftPre,*LeftNow,*RightNow;
    BlockList(ListNode* a,ListNode* b){
        LeftPre = a;
        LeftNow = b;
        RightNow = nullptr;
    }
};

void PrintList(ListNode* head) {
    head = head->next;
    while(head!=nullptr) {
        cout << head->val << ' ';
        head=head->next;
    }
    cout << endl;
}

ListNode* ReverseList(ListNode* head,int block_size) {
    vector<BlockList> Block;
    ListNode* p = head;
    ListNode* pre = nullptr;
    int now_size = -1;
    while(p!=nullptr) { //Record each block head
        if(now_size>=0 && now_size % block_size==0) {
            Block.push_back(BlockList(pre,p));
        }
        if(now_size>=0 && now_size % block_size==block_size-1 || p->next==nullptr) {
            Block.back().RightNow = p;
        }
        pre = p;
        p = p->next;
        now_size++;
    } 

    int block_num = Block.size();

    for(int i=0;i<block_num/2;i++) {
        BlockList left = Block[i];
        BlockList right = Block[block_num-i-1];
        left.LeftPre->next = right.LeftNow;
        ListNode* temp =  right.RightNow->next;
        right.RightNow->next = left.RightNow->next;
        right.LeftPre->next = left.LeftNow;
        left.RightNow->next = temp;
    }
    
    return head;
}

int main() {
    int ListSize,ReverseSize;
    cin >> ListSize >> ReverseSize;

    if(ListSize==0) {
        cout << "Empty List!" << endl;
        return 0;
    }

    ListNode* p = new ListNode(-1);
    ListNode* root = p;
    for(int i=0,val;i<ListSize;i++) {
        cin >> val;
        ListNode* q = new ListNode(val);
        p->next = q;
        p = p->next;
    }
    ReverseList(root,ReverseSize);
    PrintList(root);
    return 0;
}

/* 測試用例
9 3
1 2 3 4 5 6 7 8 9

3 1
1 2 3

0 0

2 2
1 2

3 4
1 2 3 

5 2
1 2 3 4 5
*/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章