1. 程式人生 > >程式設計師面試題(C++ 實現)

程式設計師面試題(C++ 實現)

說明

  • 以下題目均來自於牛客網
  • 以下程式碼用 C++11 編寫
  • 以下程式碼均已編譯通過(Compile by MINGW)
  • 以下程式碼均有測試案例(Main function)
  • 以下程式碼均已進行優化或部分優化(Optimize)
  • 以下程式碼均有註釋(Comment)
  • 部分題目附有解析(Analysis)
  • 如有錯誤或侵權,請聯絡博主

題目一覽

  1. 二維陣列中的查詢
  2. 替換空格
  3. 從尾到頭列印連結串列
  4. 重建二叉樹
  5. 用兩個棧實現佇列

1. 二維陣列中的查詢

問題描述:

在一個二維陣列中(每個一維陣列的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函式,輸入這樣的一個二維陣列和一個整數,判斷陣列中是否含有該整數。

解析:

先與每行的第一個數字作比較,一旦大於等於該數字,再與該行的在最後一個數字比較,如果小於該數字,則選定該行,然後在該行依次進行比較查詢;否則不存在該整數

實現:

/*
在一個二維陣列中(每個一維陣列的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。
請完成一個函式,輸入這樣的一個二維陣列和一個整數,判斷陣列中是否含有該整數。
*/

#include <iostream>
#include <vector>

using namespace std;

bool Find(int target, const vector<vector<
int> > &array) { if (array.empty()) return false; if (target < array[0][0]) return false; int _length = array.size(); for (int i = 0; i < _length; i++) { if (array[i].empty()) continue; else if(target >= array[i][0]) { // 選定該行
if (target <= array[i][array[i].size() - 1]) { // 是否小於該行的最後一個數字 for (int j = array[i].size() - 1; j >= 0; j--) { if (target == array[i][j]) return 1; else if (target > array[i][j]) break; } } else { continue; } } else return false; } return false; } int main(int argc, char const *argv[]) { // Test vector<vector<int> > vec; for(int i = 0; i < 10; i++) { vector<int> vecson; for(int j = 0; j < 7; j++) { vecson.push_back(i + j); cout << i + j << " "; } vec.push_back(vecson); cout << endl; } int target = 13; cout << "Is the target exist in array? " << ((Find(target, vec) == false) ? "False" : "True") << endl; return 0; }

輸出結果:

6  7  8  9  10  11  12  
7  8  9  10  11  12  13  
8  9  10  11  12  13  14  
9  10  11  12  13  14  15  
Is the target exist in array?  True

2. 替換空格

問題描述:

請實現一個函式,將一個字串中的每個空格替換成“%20”。例如,當字串為We Are Happy,則經過替換之後的字串為We%20Are%20Happy。

解析:

暫且沒有太好的演算法,目前只是通過指標來實現

實現:

/*
請實現一個函式,將一個字串中的每個空格替換成“%20”。
例如,當字串為We Are Happy.
則經過替換之後的字串為We%20Are%20Happy。
 */

#include <iostream>
#include <stdio.h>

using namespace std;

void replaceSpace(char *str, int length) {
    if(str == NULL)
        return ;

    int CountOfBlanks = 0;
    int Originallength = 0;
    for(int i = 0; str[i] != '\0'; i++) {
        Originallength++;
        if(str[i] == ' ')
            ++CountOfBlanks;
    }

    int len = Originallength + 2 * CountOfBlanks;  //因為 %20 比 空格 多兩個字元
    if(len + 1 > length)
        return ;

    char *pStr1 = str + Originallength; //複製結束符‘\0’
    char *pStr2 = str + len;
    while(pStr1 < pStr2) {
        if(*pStr1 == ' ') {
            *pStr2-- = '0';
            *pStr2-- = '2';
            *pStr2-- = '%';
        } else {
            *pStr2-- = *pStr1;
        }
        --pStr1;
    }
}

int main(int argc, char const *argv[]) {
    //Test
    char p[] = "AA BB CC ";
    printf("替換前:%s\n", p);
    replaceSpace(p, 50);
    printf("替換後:%s\n", p);

    return 0;
}

輸出結果:

替換前:AA BB CC 
替換後:AA%20BB%20CC%20

3. 從尾到頭列印連結串列

問題描述:

輸入一個連結串列,按連結串列值從尾到頭的順序返回一個ArrayList。

解析:

使用棧的 LIFO (Last in First out)性質來實現

如果有對連結串列的基本操作不熟悉的,請參考我的另一篇博文:

更多請參考我的另一篇部落格:連結串列大全

實現:

/*
輸入一個連結串列,按連結串列值從尾到頭的順序返回一個ArrayList。
 */

#include <vector>
#include <stack>
#include <iostream>
#include <stdlib.h>

using namespace std;

// 定義節點
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};

// 建立連結串列
struct ListNode *createList() {
    struct ListNode *head = new ListNode(0);
    struct ListNode *ret = head;
    for(int i = 1; i < 10; i++) {
        struct ListNode *p = new ListNode(i);
        ret->next = p;
        ret = ret->next;
    }
    return head;
}

 // 刪除連結串列
void deleteList(struct ListNode *list) {
    struct ListNode *p = list;
    while(p != NULL) {
        list = p->next;
        free(p);
        p = list;
    }
    free(p);
}

// 列印連結串列
void printList(ListNode *head) {
    while(head != NULL) {
        cout << head->val << " ";
        head = head->next;
    }
    cout << endl;
}

// 從尾部列印連結串列
vector<int> printListFromTailToHead(struct ListNode *const head) {
    vector <int> result;
    stack<int> arr;
    struct ListNode *p = head;
    while(p != NULL) {
        arr.push(p->val);
        p = p->next;
    }
    int len = arr.size();
    for(int i = 0; i < len; i++) {
        result.push_back(arr.top());
        arr.pop();
    }
    return  result;
}

int main(int argc, char const *argv[]) {
    //Test
    struct ListNode *head = createList();
    cout << "原始列表:\n";
    printList(head);

    cout << "逆序列印列表:\n";
    vector<int> v(printListFromTailToHead(head));
    for(int i = 0; i < v.size(); i++)
        cout << v[i] << " ";

    deleteList(head);

    return 0;
}

輸出結果:

原始列表:
0 1 2 3 4 5 6 7 8 9 
逆序列印列表:
9 8 7 6 5 4 3 2 1 0

4. 重建二叉樹

問題描述:

輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。 假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。 例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。

解析:

主要利以下內容:

  • 根節點肯定是前序遍歷的第一個數
  • 分治思想

如果有對二叉樹的基本操作不熟悉的,請參考我的另一篇博文:

更多請參考我的另一篇部落格:樹結構大全

實現:

/*
輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。
假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。
例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。
 */

#include <vector>
#include <queue>
#include <iostream>

using namespace std;

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

// 重建二叉樹
struct TreeNode *reConstructBinaryTree(vector<int> pre, vector<int> in) {
    int inlen = in.size();
    if(inlen == 0)
        return NULL;

    vector<int> left_pre, right_pre, left_in, right_in;
    //建立根節點,根節點肯定是前序遍歷的第一個數
    TreeNode *head = new TreeNode(pre[0]);
    //找到中序遍歷根節點所在位置,存放於變數gen中
    int gen = 0;
    for(int i = 0; i < inlen; i++) {
        if (in[i] == pre[0]) {
            gen = i;
            break;
        }
    }
    //對於中序遍歷,根節點左邊的節點位於二叉樹的左邊,根節點右邊的節點位於二叉樹的右邊
    //利用上述這點,對二叉樹節點進行歸併
    for(int i = 0; i < gen; i++) {
        left_in.push_back(in[i]);
        left_pre.push_back(pre[i + 1]); //前序第一個為根節點
    }

    for(int i = gen + 1; i < inlen; i++) {
        right_in.push_back(in[i]);
        right_pre.push_back(pre[i]);
    }

    //和shell排序的思想類似,取出前序和中序遍歷根節點左邊和右邊的子樹
    //遞迴,再對其進行上述所有步驟,即再區分子樹的左、右子子數,直到葉節點
    head->left = reConstructBinaryTree(left_pre, left_in);
    head->right = reConstructBinaryTree(right_pre, right_in);

    return head;
}


// 列印二叉樹
vector<vector<int> > Print(TreeNode *pRoot) {
    vector<vector<int> > Value;
    if (pRoot == NULL)
        return Value;
    queue<TreeNode * > queNode;
    queNode.push(pRoot);
    vector<int> subValue;                               //輔助陣列,儲存當前層所有的結點值
    int nextLevels = 0;                                 //用來統計下一層的結點數
    int currentLevels = 1;                              //用來標記當前層剩餘的沒有列印的結點數
    while (!queNode.empty()) {
        TreeNode *pNode = queNode.front();
        queNode.pop();
        subValue.push_back(pNode->val);
        if (pNode->left != NULL) {
            queNode.push(pNode->left);
            ++nextLevels;
        }

        if (pNode->right != NULL) {
            queNode.push(pNode->right);
            ++nextLevels;
        }
        --currentLevels;
        if (currentLevels == 0) {                           //如果當前層結點已全部列印完畢
            Value.push_back(subValue);
            subValue.clear();                           //清空,開始存下一層結點
            currentLevels = nextLevels;                 //下一層要列印的結點數
            nextLevels = 0;                             //置0,開始統計下一層結點數
        }
    }
    return Value;
}

void plr(TreeNode *pRoot) {
    if(pRoot != NULL) {
        cout << pRoot->val << endl;
        if(pRoot->left != NULL)
            cout << "left  " << pRoot->left->val << endl;
        if(pRoot->right != NULL)
            cout << "right  " << pRoot->right->val << endl;
    }
}

int main(int argc, char const *argv[]) {
    // Test
    // 建立 vec_pre vec_in
    int arr_pre[8] = {1, 2, 4, 7, 3, 5, 6, 8};
    vector<int> vec_pre(arr_pre, arr_pre + 8);
    int arr_in[8] = {4, 7, 2, 1, 5, 3, 8, 6};
    vector<int> vec_in(arr_in, arr_in + 8);

    struct TreeNode *head = reConstructBinaryTree(vec_pre, vec_in);

    vector<vector<int> > list(Print(head));
    for(int i = 0; i < list.size(); i++) {
        for(int j = 0; j < list[i].size(); j++) {
            cout << list[i][j] << " ";
        }
        cout << endl;
    }

    return 0;
}


輸出結果:

1 
2 3 
4 5 6 
7 8 

5. 用兩個棧實現佇列

問題描述:

用兩個棧來實現一個佇列,完成佇列的Push和Pop操作。 佇列中的元素為int型別。

解析:

利用棧的 LIFO性質(Last in First out)

實現

注:這個版本有很多細節沒有注意起來,參考第二個完美版本,但是比較複雜

/*
用兩個棧來實現一個佇列,完成佇列的Push和Pop操作。 佇列中的元素為int型別。
 */

#include <iostream>
#include <stack>

using namespace std;

class Queue {
public:

    void push(int node) {
        stack1.push(node);
    }

    int pop() {
        int res;
        if (stack2.size() > 0) {
            res = stack2.top();
            stack2.pop();
        } else if(stack1.size() > 0) {
            while (stack1.size() > 0) {
                int ele = stack1.top()
            
           

相關推薦

程式設計師試題(C++ 實現) - Day1

文章目錄 說明 題目一覽 1. 二維陣列中的查詢 2. 替換空格 3. 從尾到頭列印連結串列 4. 重建二叉樹 5. 用兩個棧實現佇列 聯絡博主

程式設計師試題(C++ 實現) - Day2

文章目錄 說明 今日題目一覽 1. 旋轉陣列中的最小數字 2. 斐波那契數列 3. 跳臺階(變態跳臺階) 4. 矩形覆蓋 5. 二進位制中 1 的個數 聯絡博主

程式設計師試題(C++ 實現)

說明 以下題目均來自於牛客網 以下程式碼用 C++11 編寫 以下程式碼均已編譯通過(Compile by MINGW) 以下程式碼均有測試案例(Main function) 以下程式碼均已進行優化或部分優化(Optimize) 以下程式碼均有註釋(Com

[程式設計師試題]C/C++中static的作用

面試題:static有什麼作用? 答:在C語言中,static主要定義全域性靜態變數,定義區域性靜態變數,定義靜態函式  一、       定義全域性靜態變數 :在全域性變數前面加上關鍵字static,該全域性變數變成了全域性靜態變數。全域性靜態變數有以下特點: (

“刷一波” 程式設計師試題,掌握八成便可BATJ一試~

最近看見了很多程式設計師成功入的BAT,小編這裡在網上搜集了一些國內一線網際網路公司的面試題和麵試技巧,特此整理分享給需要的技術人員,看你和BAT之間差了多少!    阿里巴巴   根據部分網友的反饋,阿里的面試共分為五輪,前兩輪均為電面(電話和視訊),四輪技術一

Java程式設計師試題集(151-180)

分享一下我的偶像大神的人工智慧教程!http://blog.csdn.net/jiangjunshow Java面試題集(151-180) 摘要:這部分包含了Spring、Spring MVC以及Spring和其他框架整合以及測試相關的內容,除此之外還包含了大型網站技術架構

拉手網Python程式設計師試題

拉手網Python程式設計師面試題 拉手網Python程式設計師面試題,有用人用10行程式碼解決,有人用了一行程式碼解決是多麼牛的趕腳。有種被秒殺的趕腳,題目在此https://www.jinshuju.net/f/EGQL3D dic={} def num(aa,bb,cc):

java常見面試題:Java程式設計師試題(六)

不知不覺中,已經將面試題更新到第六篇了,龐大的java面試題庫,想要刷完似乎不大可能,需要一點一點的積累。 1、java 中會存在記憶體洩漏嗎,請簡單描述。   答:會;存在無用但可達的物件,這些物件不能被GC 回收,導致耗費記憶體資源。 2、靜態變數和例項變數的區別?

Java高階程式設計師試題(個人建議收藏+分享)

1.你認為專案中最重要的過程是那些? 分析、設計階段 儘量找出進度的優先順序 2.如果給你一個4-6人的team,怎麼分配? 挑選一技術過硬的人作為我的替補。其它人平均分配任務,每週進行全面的任務分配,每個人領取一週的工作量 ,每天彙報進度。 3.簡述軟體開發文件

java常見面試題:Java程式設計師試題(五)

本期的java面試題是偏向資料庫方面的,對相關技術知識匱乏的,或者對這方面不大自信的同學,面試之前可以參考一下這套題,這只是節選,試運營一下,如果不能滿足你們的需求,可以直接評論留言! 1、檢視的優缺點 答:優點: 1)對資料庫的訪問,因為檢視可以有選擇性的選取資料庫

java常見面試題:Java程式設計師試題(四)

上一次更新的java面試題,很多小夥伴反應很簡單,其實上一期更新的就是更偏基礎的面試題,但這並不意味著,面試就這麼簡單,在java的學習中,有從Java基礎、框架、設計模式等等都是重點學習的點。在本文的面試題分享中,我們循序漸進,儘量挑一些重點的內容來分享! 1、當一個物件

初級程式設計師試題總結(一):

本人將這幾天面試的題目總結一些,如果出現錯誤請指正,謝謝。 1,談一談spring。 答:spring是為java程式開發提供的綜合性的基礎java開發平臺,它提供了從表現層SpringMVC到業務層Spring再到持久層springData的一套完整的解決

【.NET程式設計師試題----初級】第一卷

//1.遞迴演算法求30位數字        public static int MyFoun_04(int n)        {            //一組數值排序如下1、1、2、3、5、8、13、21、34....用遞迴求30位數字            if (n

程式設計師試題:快速找出一個數組中的兩個數字,讓這兩個數字之和等於一個給定的值

能否快速找出一個數組中的兩個數字,讓這兩個數字之和等於一個給定的值,為了簡化起見,我們假設這個陣列中肯定存在至少一組符合要求的解。 假如有如下的兩個陣列,如圖所示: 5,6,1,4,7,9,8 給定Sum= 10 1,5,6,7,8,9 給定Sum=

程式設計師試題2016】騰訊企鵝

1、已知一棵二叉樹,如果先序遍歷的節點順序是: ADCEFGHB ,中序遍歷是: CDFEGHAB ,則後序遍歷結果為:( ) A. CFHGEBDA B. CDFEGHBA C. FGHCDEBA D. CFHGEDBA 知識點 對於二叉樹的遍歷方式一般分為三

2018最新JAVA程式設計師試題

應用伺服器有那些?【基礎】答:BEAWebLogic Server, IBM WebSphere Application Server, Oracle9i   Application Server, JBoss, Tomcat。146、Servlet執行時一般實現哪幾個方法?

第一次只出現一次的字元(程式設計師試題精選100題)

題目:在一個字串中找到第一個只出現一次的字元。如輸入abaccdeff,則輸出b。 分析:這道題是2006年google的一道筆試題。 方法一:         最直觀的想法是從頭開始掃描這個字串中的每個字元。當訪問到某字元時拿這個字元和後面的每個字元相比較,如果在後面沒

黑馬程式設計師------試題------交通燈管理系統

------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">

Java程式設計師試題及解答(三)

二、Web篇 這部分主要是與Java Web和Web Service相關的面試題。 96、闡述Servlet和CGI的區別?  答:Servlet與CGI的區別在於Servlet處於伺服器程序中,它通過多執行緒方式執行其service()方法,一個例項可

程式設計師試題精選100題(40)-撲克牌的順子[演算法]

題目:從撲克牌中隨機抽5張牌,判斷是不是一個順子,即這5張牌是不是連續的。2-10為數字本身,A為1,J為11,Q為12,K為13,而大小王可以看成任意數字。 分析:這題目很有意思,是一個典型的寓教於樂的題目。 我們需要把撲克牌的背景抽象成計算機語言。不難想象,我們可以把5