欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

劍指Offer66題C++面試題+答案總結(jié)

  發(fā)布時(shí)間:2019-08-14 15:58:14   作者:zj19941113   我要評(píng)論
這篇文章主要介紹了劍指Offer66題C++面試+答案總結(jié),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

1、二維數(shù)組中的查找

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

/* 
 3 4 5
 4 5 6
 6 7 8
 從左下角開始查找,當(dāng)target比左下角數(shù)字大時(shí),右移;小時(shí),上移
*/
class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
        int rows = array.size(), cols = array[0].size();
        int i = rows - 1, j = 0;
        while(i>=0&&j<cols){
            if(array[i][j] == target) return true;
            else if(array[i][j] > target) i--;
            else j++;
        }
        return false;
    }
};

2、替換空格

請(qǐng)實(shí)現(xiàn)一個(gè)函數(shù),將一個(gè)字符串中的每個(gè)空格替換成“%20”。例如,當(dāng)字符串為We Are Happy.則經(jīng)過替換之后的字符串為We%20Are%20Happy。

/*
 從前往后替換,后面的字符要多次移動(dòng),效率低下
 從后往前,先計(jì)算需要多少空間,每個(gè)字符只移動(dòng)一次,效率更高
 例如:a b c
 從后往前,當(dāng)前第i位為'c'(非空格),前有n個(gè)空格,則i+2*n位為c
 當(dāng)前第i位為' '(空格),前有n個(gè)空格,則i+2*n位為%,i+2*n+1位為2,i+2*n+2位為0
*/
class Solution {
public:
 void replaceSpace(char *str,int length) {
        int sum = 0;
        for(int i=0;i<length;i++){
            if(str[i] == ' ') sum++;
        }
        for(int i=length-1;i>=0;i--){
            if(str[i] != ' ') str[i + 2*sum] = str[i];
            else{
                sum--;
                str[i + 2*sum] = '%';
                str[i + 2*sum + 1] = '2';
                str[i + 2*sum + 2] = '0';
            }
        }
    }
};

3、從尾到頭打印鏈表

輸入一個(gè)鏈表,按鏈表值從尾到頭的順序返回一個(gè)ArrayList。

/**
*  struct ListNode {
*        int val;
*        struct ListNode *next;
*        ListNode(int x) :
*              val(x), next(NULL) {
*        }
*  };
*/
class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
        vector<int> res;
        stack<int> stack;
        while(head){
            stack.push(head->val);
            head = head->next;
        }
        while(!stack.empty()){
            res.push_back(stack.top());
            stack.pop();
        }
        return res;
    }
};

4、重建二叉樹

輸入某二叉樹的前序遍歷和中序遍歷的結(jié)果,請(qǐng)重建出該二叉樹。假設(shè)輸入的前序遍歷和中序遍歷的結(jié)果中都不含重復(fù)的數(shù)字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹并返回。

/*
 前序遍歷序列{1,2,4,7,3,5,6,8} 1是根元素
 中序遍歷序列{4,7,2,1,5,3,8,6} 1之前4,7,2是左子樹中序,之后5,3,8,6是右子樹中序
 前序中1后的3個(gè)是左子樹前序,之后是右子樹前序
 問題轉(zhuǎn)換為根元素已知,求左子樹和右子樹的重建二叉樹,進(jìn)行遞歸
*/
/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
        return buildtree(pre,vin,0,pre.size()-1,0,vin.size()-1);
    }
    
    TreeNode* buildtree(vector<int> pre,vector<int> vin,int pl,int pr,int vl,int vr) {
        if(pl > pr || vl > vr) return NULL;
        TreeNode* root = new TreeNode(pre[pl]);
        int i;
        for(i=vl;i<=vr;i++){
            if(vin[i] == pre[pl]) break;
        }
        int num = i - vl; //左子樹個(gè)數(shù)
        root->left =  buildtree(pre,vin,pl+1,pl+num,vl,vl+num-1);
        root->right =  buildtree(pre,vin,pl+num+1,pr,vl+num+1,vr);
        return root;
    }
};

5、用兩個(gè)棧實(shí)現(xiàn)隊(duì)列

用兩個(gè)棧來實(shí)現(xiàn)一個(gè)隊(duì)列,完成隊(duì)列的Push和Pop操作。 隊(duì)列中的元素為int類型。

/*
 用兩個(gè)棧實(shí)現(xiàn)一個(gè)隊(duì)列的功能
 入隊(duì):將元素進(jìn)棧A
 出隊(duì):判斷棧B是否為空,如果為空,則將棧A中所有元素pop,并push進(jìn)棧B,棧B出棧;
 如果不為空,棧B直接出棧。
 
 用兩個(gè)隊(duì)列實(shí)現(xiàn)一個(gè)棧的功能
 入棧:將元素進(jìn)隊(duì)列A
 出棧:判斷隊(duì)列A中元素的個(gè)數(shù)是否為1,如果等于1,則出隊(duì)列,否則將隊(duì)列A中的元素依次出隊(duì)列并放入隊(duì)列B,直到隊(duì)列A中的元素留下一個(gè),然后隊(duì)列A出隊(duì)列,再把隊(duì)列B中的元素出隊(duì)列以此放入隊(duì)列A中。
*/
class Solution
{
public:
    void push(int node) {
        stack1.push(node);
    }

    int pop() {
        while(!stack1.empty()){
            stack2.push(stack1.top());
            stack1.pop();
        }
        int res = stack2.top();
        stack2.pop();
        while(!stack2.empty()){
            stack1.push(stack2.top());
            stack2.pop();
        }
        return res;
    }
private:
    stack<int> stack1;
    stack<int> stack2;
};

6、旋轉(zhuǎn)數(shù)組的最小數(shù)字

把一個(gè)數(shù)組最開始的若干個(gè)元素搬到數(shù)組的末尾,我們稱之為數(shù)組的旋轉(zhuǎn)。 輸入一個(gè)非減排序的數(shù)組的一個(gè)旋轉(zhuǎn),輸出旋轉(zhuǎn)數(shù)組的最小元素。 例如數(shù)組{3,4,5,1,2}為{1,2,3,4,5}的一個(gè)旋轉(zhuǎn),該數(shù)組的最小值為1。 NOTE:給出的所有元素都大于0,若數(shù)組大小為0,請(qǐng)返回0。

class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray) {
        if(rotateArray.size() == 0) return 0;
        int i = 0, j = rotateArray.size()-1;
        while(i < j){
            int mid = (i + j)/2;
            if(rotateArray[mid] > rotateArray[j]){ 
                i = mid + 1; //3 4 7 8 1 2  旋轉(zhuǎn)點(diǎn)在右,左順序
            }
            else if(rotateArray[mid] < rotateArray[j]){ 
                j = mid; //7 8 1 2 3 4  旋轉(zhuǎn)點(diǎn)在左,右順序
            }
            else{ //1 0 1 1 1  或  1 1 1 0 1 順序部分為常數(shù)
                i ++; //或 j --;
            }
        }
        return rotateArray[i];
    }
};

7、斐波那契數(shù)列

大家都知道斐波那契數(shù)列,現(xiàn)在要求輸入一個(gè)整數(shù)n,請(qǐng)你輸出斐波那契數(shù)列的第n項(xiàng)(從0開始,第0項(xiàng)為0)。
n<=39

class Solution {
public:
    int Fibonacci(int n) { //0 1 1 2 3 5 …,使用動(dòng)態(tài)規(guī)劃
        int i = 0, j = 1;
        while(n>0){
            int tmp = j;
            j = i+j;
            i = tmp;
            n--;
        }
        return i;
    }
};

8、跳臺(tái)階

一只青蛙一次可以跳上1級(jí)臺(tái)階,也可以跳上2級(jí)。求該青蛙跳上一個(gè)n級(jí)的臺(tái)階總共有多少種跳法(先后次序不同算不同的結(jié)果)。

/*
 最后一步跳1,有f(n-1)種情況
 最后一步跳2,有f(n-2)種情況
 共f(n)=f(n-1)+f(n-2),1 1 2 3 5(斐波那契數(shù)列)使用動(dòng)態(tài)規(guī)劃
*/
class Solution {
public:
    int jumpFloor(int number) {
        int i = 1, j = 1;
        while(number>0){
            int tmp = j;
            j = i + j;
            i = tmp;
            number--;
        }
        return i;
    }
};

9、變態(tài)跳臺(tái)階

一只青蛙一次可以跳上1級(jí)臺(tái)階,也可以跳上2級(jí)……它也可以跳上n級(jí)。求該青蛙跳上一個(gè)n級(jí)的臺(tái)階總共有多少種跳法。

//f(n) = f(1) + f(2) + f(3) +...+ f(n-1) + 1
//1 2 4 8 ...
class Solution {
public:
    int jumpFloorII(int number) {
        vector<int> step;
        while(number>0){
            int sum = 0;
            for(int i=0;i<step.size();i++){
                sum += step[i];
            }
            step.push_back(sum+1); 
            number--;
        }
        return step.back();
    }
};
/*
class Solution {
public:
    int jumpFloorII(int number) {
        int res = 1;
        for(int i=1;i<number;i++){
            res += jumpFloorII(i);
        }
        return res;
    }
};
*/

10、矩形覆蓋

我們可以用2*1的小矩形橫著或者豎著去覆蓋更大的矩形。請(qǐng)問用n個(gè)2*1的小矩形無重疊地覆蓋一個(gè)2*n的大矩形,總共有多少種方法?

/*
|    | | |   f(n-1)
|    | | |
 
— —    | |   f(n-2)
— —    | |
f(n) = f(n-1) + f(n-2),1 2 3 5 8…,動(dòng)態(tài)規(guī)劃
*/
class Solution {
public:
    int rectCover(int number) {
        if(number == 0) return 0;
        int i = 1, j = 1;
        while(number>0){
            int tmp = j;
            j = i + j;
            i = tmp;
            number--;
        }
        return i;
    }
};

11、二進(jìn)制中1的個(gè)數(shù)

輸入一個(gè)整數(shù),輸出該數(shù)二進(jìn)制表示中1的個(gè)數(shù)。其中負(fù)數(shù)用補(bǔ)碼表示。

/*
 將n與n-1相與會(huì)把n的最右邊的1變?yōu)?,比如
 1100&1011 = 1000
*/
class Solution {
public:
     int  NumberOf1(int n) {
         int res=0;
         while(n!=0){
             res++;
             n = n&(n-1);
         }
         return res;
     }
};

/*
 #include <bitset>
*/
class Solution {
public:
     int  NumberOf1(int n) {
         bitset<32>a(n); //32位的2進(jìn)制
         return a.count(); //返回1的個(gè)數(shù)
     }
};

12、數(shù)值的整數(shù)次方

給定一個(gè)double類型的浮點(diǎn)數(shù)base和int類型的整數(shù)exponent。求base的exponent次方。

/*
 10^1101 = 10^0001*10^0100*10^1000,即base*1 * base^2 * base^4 * …
 通過&1和>>1來逐位讀取1101
*/
class Solution {
public:
    double Power(double base, int exponent) {
        double res = 1;
        int e = abs(exponent);
        while(e!=0){
            if(e&1 == 1){
                res *= base;
            }
            base *= base;
            e = e>>1;
        }
        return exponent>0?res:1/res;
    }
};

13、調(diào)整數(shù)組順序使奇數(shù)位于偶數(shù)前面

輸入一個(gè)整數(shù)數(shù)組,實(shí)現(xiàn)一個(gè)函數(shù)來調(diào)整該數(shù)組中數(shù)字的順序,使得所有的奇數(shù)位于數(shù)組的前半部分,所有的偶數(shù)位于數(shù)組的后半部分,并保證奇數(shù)和奇數(shù),偶數(shù)和偶數(shù)之間的相對(duì)位置不變。

/*
 要想保證原有次序,則只能順次移動(dòng)或相鄰交換。
 1.i從左向右遍歷,找到第一個(gè)偶數(shù)。
 2.j從i+1開始向后找,找到第一個(gè)奇數(shù)。
 3.將[i,...,j-1]的元素整體后移一位,將找到的奇數(shù)放入i位置
*/
class Solution {
public:
    void reOrderArray(vector<int> &array) {
        for(int i=0;i<array.size();i++){
            if(array[i]%2 == 0){
                for(int j=i+1;j<array.size();j++){
                    if(array[j]%2 == 1){
                        int tmp = array[j];
                        for(int k=j-1;k>=i;k--){
                            array[k+1] = array[k];
                        }
                        array[i] = tmp;
                        break;
                    }
                }
            }
        }
    }
};

14、鏈表中倒數(shù)第k個(gè)結(jié)點(diǎn)

輸入一個(gè)鏈表,輸出該鏈表中倒數(shù)第k個(gè)結(jié)點(diǎn)。

/*
struct ListNode {
 int val;
 struct ListNode *next;
 ListNode(int x) :
   val(x), next(NULL) {
 }
};*/
/*
 兩指針指向頭結(jié)點(diǎn),
 第一個(gè)指針走(k-1)步,到k節(jié)點(diǎn)
 兩個(gè)指針同時(shí)往后移動(dòng),當(dāng)?shù)谝粋€(gè)結(jié)點(diǎn)到達(dá)末尾的時(shí)候,第二個(gè)結(jié)點(diǎn)所在位置就是倒數(shù)第k個(gè)節(jié)點(diǎn)
*/
class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        if(!pListHead || k==0) return NULL;
        ListNode* node1 = pListHead;
        ListNode* node2 = pListHead;
        int i = 0;
        while(node1){
            if(i>=k){
                node2 = node2 -> next;
            }
            node1 = node1 -> next;
            i++;
        }
        return i<k ? NULL : node2;
    }
};

15、反轉(zhuǎn)鏈表

輸入一個(gè)鏈表,反轉(zhuǎn)鏈表后,輸出新鏈表的表頭。

/*
struct ListNode {
 int val;
 struct ListNode *next;
 ListNode(int x) :
   val(x), next(NULL) {
 }
};*/
/*
1 2 3 4 5
遍歷鏈表,當(dāng)前值為4時(shí),相當(dāng)于新建值為4的鏈表node,node->next = 前面鏈表反轉(zhuǎn),node即為所求
當(dāng)前值為5時(shí),相當(dāng)于新建值為5的鏈表node,node->next = 上一步的值
*/
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        ListNode* res = NULL;
        while(pHead){
            ListNode* tmp = new ListNode(pHead->val);
            tmp -> next = res;
            res = tmp;
            pHead = pHead -> next;
        }
        return res;
    }
};



16、合并兩個(gè)排序的鏈表

輸入兩個(gè)單調(diào)遞增的鏈表,輸出兩個(gè)鏈表合成后的鏈表,當(dāng)然我們需要合成后的鏈表滿足單調(diào)不減規(guī)則。

/*
struct ListNode {
 int val;
 struct ListNode *next;
 ListNode(int x) :
   val(x), next(NULL) {
 }
};*/
class Solution {
public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
    {
        ListNode* res = new ListNode(0);//初始化,取幾不重要
        ListNode* here = res; //標(biāo)記位置
        while(pHead1 && pHead2){
            if(pHead1->val < pHead2->val){
                res -> next = pHead1;
                pHead1 = pHead1 -> next;
            }
            else{
                res -> next = pHead2;
                pHead2 = pHead2 -> next;
            }
            res = res -> next;
        }
        res -> next = pHead1 ? pHead1:pHead2;
        return here->next;
    }
};

17、樹的子結(jié)構(gòu)

輸入兩棵二叉樹A,B,判斷B是不是A的子結(jié)構(gòu)。(ps:我們約定空樹不是任意一個(gè)樹的子結(jié)構(gòu))

/*
/*
struct TreeNode {
 int val;
 struct TreeNode *left;
 struct TreeNode *right;
 TreeNode(int x) :
   val(x), left(NULL), right(NULL) {
 }
};*/
class Solution {
public:
    bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2) {
        if(pRoot1 && pRoot2){
            return issub(pRoot1,pRoot2)|| 
                HasSubtree(pRoot1->left,pRoot2)|| 
                HasSubtree(pRoot1->right,pRoot2);
        }
        return false;
    }
    
    bool issub(TreeNode* l1, TreeNode* l2) {
        if(l2){
            return l1&& l1->val==l2->val&& 
                issub(l1->left,l2->left)&& 
                issub(l1->right,l2->right);
        }
        return true;
    }
};

18、二叉樹的鏡像

操作給定的二叉樹,將其變換為源二叉樹的鏡像。

二叉樹的鏡像定義:        源二叉樹         8       /  \      6   10     / \  / \    5  7 9 11    鏡像二叉樹        8       /  \      10   6     / \  / \    11 9 7  5

/*
struct TreeNode {
 int val;
 struct TreeNode *left;
 struct TreeNode *right;
 TreeNode(int x) :
   val(x), left(NULL), right(NULL) {
 }
};*/
class Solution {
public:
    void Mirror(TreeNode *pRoot) {
        if(!pRoot) return;
        TreeNode *tmp = pRoot->left;
        pRoot->left = pRoot->right;
        pRoot->right = tmp;
        Mirror(pRoot->left);
        Mirror(pRoot->right);
    }
};

19、順時(shí)針打印矩陣

輸入一個(gè)矩陣,按照從外向里以順時(shí)針的順序依次打印出每一個(gè)數(shù)字,例如,如果輸入如下4 X 4矩陣: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 則依次打印出數(shù)字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.

/*
   m   n
 i 1 2 3
   4 5 6
 j 7 8 9
*/
class Solution {
public:
    vector<int> printMatrix(vector<vector<int> > matrix) {
        vector<int> res;
        int i = 0,j = matrix.size()-1,m = 0,n = matrix[0].size()-1;
        while(i<=j && m<=n){
            for(int k=m;k<=n;k++) res.push_back(matrix[i][k]);
            i++;//削首行
            if(i>j) break;
            for(int k=i;k<=j;k++) res.push_back(matrix[k][n]);
            n--;//削尾列
            if(m>n) break;
            for(int k=n;k>=m;k--) res.push_back(matrix[j][k]); 
            j--;//削尾行
            if(i>j) break;
            for(int k=j;k>=i;k--){
                res.push_back(matrix[k][m]);
            }
            m++;//削首列
        }
        return res;
    }
};

20、包含min函數(shù)的棧

定義棧的數(shù)據(jù)結(jié)構(gòu),請(qǐng)?jiān)谠擃愋椭袑?shí)現(xiàn)一個(gè)能夠得到棧中所含最小元素的min函數(shù)(時(shí)間復(fù)雜度應(yīng)為O(1))。

/*
 用stack1保存數(shù)據(jù),用stack2做輔助棧保存依次入棧最小的數(shù)
 stack1:5, 4, 3, 8, 10, 11, 12, 1
 stack2:5, 4, 3,no, no, no, no, 1
 no代表此次不入棧
 入棧,如果stack1的壓入比stack2壓入大,stack2不壓;小于等于,兩棧同時(shí)壓入
 出棧,如果兩棧頂元素不等,stack1出,stack2不出;相等,都出
*/
class Solution {
public:
    stack<int> stack1,stack2;
    void push(int value) {
        stack1.push(value);
        if(stack2.empty()) stack2.push(value);
        else{
            if(value <= stack2.top()) stack2.push(value);
        }
    }
    void pop() {
        if(stack1.top() == stack2.top()) stack2.pop();
        stack1.pop();
    }
    int top() {
        return stack1.top();
    }
    int min() {
        return stack2.top();
    }
};

21、棧的壓入、彈出序列

輸入兩個(gè)整數(shù)序列,第一個(gè)序列表示棧的壓入順序,請(qǐng)判斷第二個(gè)序列是否可能為該棧的彈出順序。假設(shè)壓入棧的所有數(shù)字均不相等。例如序列1,2,3,4,5是某棧的壓入順序,序列4,5,3,2,1是該壓棧序列對(duì)應(yīng)的一個(gè)彈出序列,但4,3,5,1,2就不可能是該壓棧序列的彈出序列。(注意:這兩個(gè)序列的長度是相等的)

class Solution {
public:
    bool IsPopOrder(vector<int> pushV,vector<int> popV) {
        stack<int> s;
        int k = 0,len = pushV.size();
        for(int i=0;i<len;i++){
            s.push(pushV[i]);
            while(k<len && popV[k] == s.top()){
                s.pop();
                k++;
            }
        }
        return s.empty();
    }
};

22、從上往下打印二叉樹

從上往下打印出二叉樹的每個(gè)節(jié)點(diǎn),同層節(jié)點(diǎn)從左至右打印。

/*
struct TreeNode {
 int val;
 struct TreeNode *left;
 struct TreeNode *right;
 TreeNode(int x) :
   val(x), left(NULL), right(NULL) {
 }
};*/
class Solution {
public:
    vector<int> PrintFromTopToBottom(TreeNode* root) {
        vector<int> res;
        queue<TreeNode* > q;
        if(root) q.push(root);
        while(!q.empty()){
            if(q.front()->left) q.push(q.front()->left);
            if(q.front()->right) q.push(q.front()->right);
            res.push_back(q.front()->val);
            q.pop();
        }
        return res;
    }
};

23、二叉搜索樹的后序遍歷序列

輸入一個(gè)整數(shù)數(shù)組,判斷該數(shù)組是不是某二叉搜索樹的后序遍歷的結(jié)果。如果是則輸出Yes,否則輸出No。假設(shè)輸入的數(shù)組的任意兩個(gè)數(shù)字都互不相同。

/*
 二叉搜索樹BST 左子樹值都比root小,右子樹值都比root大。
 去掉最后一個(gè)元素root,其他分成兩段:
 前一段(左子樹)小于x,后一段(右子樹)大于x,且這兩段(子樹)都是BST的后序遍歷
*/
class Solution {
public:
    bool VerifySquenceOfBST(vector<int> sequence) {
        if(sequence.size()==0) return false;
        return isok(sequence,0,sequence.size()-1);
    }
    bool isok(vector<int> arr,int l,int r) {
        if(l >= r) return true;
        int i=l;
        while(i<r && arr[i]<arr[r]) i++; //找到滿足BST的右子樹開頭
        for(int j=i;j<r;j++) if(arr[j] < arr[r]) return false; //判斷剩下是否為右子樹
        return isok(arr,l,i-1)&& isok(arr,i,r-1);
    } 
};

24、二叉樹中和為某一值的路徑

輸入一顆二叉樹的根節(jié)點(diǎn)和一個(gè)整數(shù),打印出二叉樹中結(jié)點(diǎn)值的和為輸入整數(shù)的所有路徑。路徑定義為從樹的根結(jié)點(diǎn)開始往下一直到葉結(jié)點(diǎn)所經(jīng)過的結(jié)點(diǎn)形成一條路徑。(注意: 在返回值的list中,數(shù)組長度大的數(shù)組靠前)

/*
struct TreeNode {
 int val;
 struct TreeNode *left;
 struct TreeNode *right;
 TreeNode(int x) :
   val(x), left(NULL), right(NULL) {
 }
};*/
class Solution {
public:
    vector<vector<int> > res;
    vector<int> tmp;
    vector<vector<int> > FindPath(TreeNode* root,int expectNumber) {
        if(root) helper(root,expectNumber);
        return res;
    }
    void helper(TreeNode* root,int n) {
        tmp.push_back(root->val);
        if(root->val == n && !root->left && !root->right) res.push_back(tmp);
        else{
            if(root->left) helper(root->left,n-root->val);
            if(root->right) helper(root->right,n-root->val);
        }
        tmp.pop_back();
    }
};

25、復(fù)雜鏈表的復(fù)制

輸入一個(gè)復(fù)雜鏈表(每個(gè)節(jié)點(diǎn)中有節(jié)點(diǎn)值,以及兩個(gè)指針,一個(gè)指向下一個(gè)節(jié)點(diǎn),另一個(gè)特殊指針指向任意一個(gè)節(jié)點(diǎn)),返回結(jié)果為復(fù)制后復(fù)雜鏈表的head。(注意,輸出結(jié)果中請(qǐng)不要返回參數(shù)中的節(jié)點(diǎn)引用,否則判題程序會(huì)直接返回空)

/*
struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};
*/
/*
 復(fù)制節(jié)點(diǎn),如:復(fù)制節(jié)點(diǎn)A得到A1,將A1插入節(jié)點(diǎn)A后面
 復(fù)制random,遍歷鏈表,A1->random = A->random->next;
 將鏈表拆分成原鏈表和復(fù)制后的鏈表
*/
class Solution {
public:
    RandomListNode* Clone(RandomListNode* pHead)
    {
        if(!pHead) return NULL;
        
        RandomListNode* cur = pHead;//從頭復(fù)制節(jié)點(diǎn) A->B->C 變成A->A'->B->B'->C->C'
        while(cur){
            RandomListNode* copynode = new RandomListNode(cur->label);
            copynode -> next = cur -> next;
            cur->next = copynode;
            cur = cur -> next -> next;
        }
        
        cur = pHead;//從頭復(fù)制random,A1->random = A->random->next;
        while(cur){
            if(cur -> random) cur -> next -> random = cur -> random -> next;
            cur = cur -> next -> next;
        }
        
        cur = pHead;//從頭將鏈表拆分成原鏈表和復(fù)制后的鏈表
        RandomListNode* res = cur -> next; //復(fù)制后的鏈表,標(biāo)記位置
        RandomListNode* tmp;
        while(cur -> next){
            tmp = cur -> next;
            cur -> next = tmp -> next;
            cur = tmp;
        }
        return res;
    }
};

26、二叉搜索樹與雙向鏈表

輸入一棵二叉搜索樹,將該二叉搜索樹轉(zhuǎn)換成一個(gè)排序的雙向鏈表。要求不能創(chuàng)建任何新的結(jié)點(diǎn),只能調(diào)整樹中結(jié)點(diǎn)指針的指向。

/*
struct TreeNode {
 int val;
 struct TreeNode *left;
 struct TreeNode *right;
 TreeNode(int x) :
   val(x), left(NULL), right(NULL) {
 }
};*/
class Solution {
public:
 //樹的線索化,利用了二叉樹結(jié)點(diǎn)中的空指針,讓它們分別指向本結(jié)點(diǎn)的前驅(qū)或者后繼
    TreeNode* head = NULL;
    TreeNode* res = NULL;
    TreeNode* Convert(TreeNode* pRootOfTree) {
        if(!pRootOfTree) return NULL;
        helper(pRootOfTree);
        return res;
    }
    void helper(TreeNode* root) {
        if(!root) return;
        helper(root->left);
        if(!head){ //中序遍歷第一個(gè),即樹的左下角
            head = root;
            res = root;
        }
        else{
            head -> right = root;
            root -> left = head;
            head = root;
        }
        helper(root->right);
    } 
};

27、字符串的排列

輸入一個(gè)字符串,按字典序打印出該字符串中字符的所有排列。例如輸入字符串a(chǎn)bc,則打印出由字符a,b,c所能排列出來的所有字符串a(chǎn)bc,acb,bac,bca,cab和cba。

輸入一個(gè)字符串,長度不超過9(可能有字符重復(fù)),字符只包括大小寫字母。

/*
 問題轉(zhuǎn)換為先固定第一個(gè)字符,求剩余字符的排列
 再把第一個(gè)字符與后面每一個(gè)字符交換,并同樣遞歸獲得首位后面的字符串組合
 a b b c:
 a+f(bbc),b+f(abc),c+f(cbba); 遍歷出所有可能出現(xiàn)在第一個(gè)位置的字符
 f(bbc)=b+f(bc),c+f(bb);
 f(bc)=b+f(c),c+f(b);
 f(c)=c;
*/
class Solution {
public:
    vector<string> res;
    vector<string> Permutation(string str) {
        helper(str,0);
        sort(res.begin(),res.end());
        return res;
    }
    void helper(string s,int n) {
        if(n == s.size()-1){ //終止條件
            if(find(res.begin(),res.end(),s) == res.end()) res.push_back(s);
        }
        else{
            for(int i=n;i<s.size();i++){
                swap(s,i,n);
                helper(s,n+1);
                swap(s,i,n);
            }
        }
    }
    void swap(string &str,int i,int j) {
        char tmp = str[i];
        str[i] = str[j];
        str[j] = tmp;
    }
};

28、數(shù)組中出現(xiàn)次數(shù)超過一半的數(shù)字

數(shù)組中有一個(gè)數(shù)字出現(xiàn)的次數(shù)超過數(shù)組長度的一半,請(qǐng)找出這個(gè)數(shù)字。例如輸入一個(gè)長度為9的數(shù)組{1,2,3,2,2,2,5,4,2}。由于數(shù)字2在數(shù)組中出現(xiàn)了5次,超過數(shù)組長度的一半,因此輸出2。如果不存在則輸出0。

/*
 如果重復(fù)的次數(shù)超過一半的話,一定有相鄰的數(shù)字相同這種情況的
 對(duì)數(shù)組同時(shí)去掉兩個(gè)不同的數(shù)字,到最后剩下的一個(gè)數(shù)就是該數(shù)字
*/
class Solution {
public:
    int MoreThanHalfNum_Solution(vector<int> numbers) {
        if(numbers.empty()) return 0;
        int res = numbers[0];
        int times = 0;
        for(int i=0;i<numbers.size();i++){
            if(numbers[i] == res) times++;
            else{
                times--;
                if(times == 0){
                    res = numbers[i];
                    times = 1;
                }
            }
        }
        //check
        times = 0;
        for(int i=0;i<numbers.size();i++){
            if(numbers[i] == res) times++;
        }
        return times>numbers.size()/2?res:0;
    }
};
/* 涉及到快排sort,其時(shí)間復(fù)雜度為O(NlogN)并非最優(yōu)
class Solution {
public:
    int MoreThanHalfNum_Solution(vector<int> numbers)
    {
        // 因?yàn)橛玫搅藄ort,時(shí)間復(fù)雜度O(NlogN),并非最優(yōu)
        if(numbers.empty()) return 0;
         
        sort(numbers.begin(),numbers.end());
        int middle = numbers[numbers.size()/2];//假設(shè)存在眾數(shù)may
        
        //check
        int count=0; // 出現(xiàn)次數(shù)
        for(int i=0;i<numbers.size();++i)
        {
            if(numbers[i]==middle) ++count;
        }
         
        return (count>numbers.size()/2) ? middle :  0;
    }
};
*/

29、最小的k個(gè)數(shù)

輸入n個(gè)整數(shù),找出其中最小的K個(gè)數(shù)。例如輸入4,5,1,6,2,7,3,8這8個(gè)數(shù)字,則最小的4個(gè)數(shù)字是1,2,3,4,。

/*
 基于堆排序算法,構(gòu)建最大堆。時(shí)間復(fù)雜度為O(nlogk)
 用最大堆保存這k個(gè)數(shù),每次只和堆頂比,如果比堆頂小,刪除堆頂,新數(shù)入堆
 如果用快速排序,時(shí)間復(fù)雜度為O(nlogn);
*/
class Solution {
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        vector<int> res;
        priority_queue<int> q; 
        //priority_queue<int,vector<int>,greater<int>> q;最小堆
        if(input.empty() || k>input.size() || k==0) return res;
        for(int i=0;i<input.size();i++){
            if(i<k) q.push(input[i]);
            else{
                if(input[i] < q.top()){
                    q.pop();
                    q.push(input[i]);
                }
            }
        }
        while(!q.empty()){
            res.push_back(q.top());
            q.pop();
        }
        return res;
    }
};

30、連續(xù)子數(shù)組的最大和

HZ偶爾會(huì)拿些專業(yè)問題來忽悠那些非計(jì)算機(jī)專業(yè)的同學(xué)。今天測試組開完會(huì)后,他又發(fā)話了:在古老的一維模式識(shí)別中,常常需要計(jì)算連續(xù)子向量的最大和,當(dāng)向量全為正數(shù)的時(shí)候,問題很好解決。但是,如果向量中包含負(fù)數(shù),是否應(yīng)該包含某個(gè)負(fù)數(shù),并期望旁邊的正數(shù)會(huì)彌補(bǔ)它呢?例如:{6,-3,-2,7,-15,1,2,2},連續(xù)子向量的最大和為8(從第0個(gè)開始,到第3個(gè)為止)。給一個(gè)數(shù)組,返回它的最大連續(xù)子序列的和,你會(huì)不會(huì)被他忽悠???(子向量的長度至少是1)

class Solution {
public:
    int FindGreatestSumOfSubArray(vector<int> array) {
        int res = array[0];
        int max = 0;
        for(int i=0;i<array.size();i++){
            max += array[i];
            if(max > res) res = max;
            if(max < 0) max = 0;
        }
        return res;
    }
};

31、整數(shù)中1出現(xiàn)的次數(shù)

求出113的整數(shù)中1出現(xiàn)的次數(shù),并算出1001300的整數(shù)中1出現(xiàn)的次數(shù)?為此他特別數(shù)了一下1~13中包含1的數(shù)字有1、10、11、12、13因此共出現(xiàn)6次,但是對(duì)于后面問題他就沒轍了。ACMer希望你們幫幫他,并把問題更加普遍化,可以很快的求出任意非負(fù)整數(shù)區(qū)間中1出現(xiàn)的次數(shù)(從1 到 n 中1出現(xiàn)的次數(shù))。

/*
 n=10917 1~10917
 所有數(shù)里在個(gè)位的1的數(shù)量:
 前面為0~1090,個(gè)位后無,排列組合共1*1091種情況;前面為1091時(shí),個(gè)位后為1。總共:1*1091+1(m=1,情況3)
 所有數(shù)里在十位的1的數(shù)量:
 前面為0~108,十位后為0~9,排列組合共10*109種情況;前面為109時(shí),十位后為0~7??偣玻?0*109+8(m=8,情況2)
 所有數(shù)里在百位的1的數(shù)量:
 前面為0~9,百位后為0~99,排列組合共100*10種情況;前面為10時(shí),百位后為0~99??偣玻?00*10+100(m=100,情況3)
 所有數(shù)里在千位的1的數(shù)量:
 前面為0~0,千位后為0~999,排列組合共1000*1種情況;前面為1時(shí),千位后沒有滿足的。總共:1000*1+0(m=0,情況1)
 所有數(shù)里在萬位的1的數(shù)量:
 前面為無,萬位后為0~917??偣玻?000*0+918(m=918,情況2)
 
 精髓在于后面部分m值分三種情況:
 ①當(dāng)前位為0時(shí),m=0;②當(dāng)前位為1時(shí),m=后面值+1;③當(dāng)前位為2~9時(shí),m=10^(后面的位數(shù))
*/
class Solution {
public:
    int NumberOf1Between1AndN_Solution(int n) {
        if(n == 0) return 0;
        int res = 0;
        int base = 1,t = n,m;
        while(t!=0){
            if(t%10 == 0) m = 0;
            else if(t%10 == 1) m = n-t*base+1;
            else m = base;
            t/=10; res+=base*t+m; base*=10; 
        }
        return res;
    }
};

32、把數(shù)組排成最小的數(shù)

輸入一個(gè)正整數(shù)數(shù)組,把數(shù)組里所有數(shù)字拼接起來排成一個(gè)數(shù),打印能拼接出的所有數(shù)字中最小的一個(gè)。例如輸入數(shù)組{3,32,321},則打印出這三個(gè)數(shù)字能排成的最小數(shù)字為321323。

class Solution {
public:
    //sort中的比較函數(shù)compare要聲明為靜態(tài)成員函數(shù)或全局函數(shù),不能作為普通成員函數(shù)
    string PrintMinNumber(vector<int> numbers) {
        string res = "";
        sort(numbers.begin(),numbers.end(),cmp);
        for(int i=0;i<numbers.size();i++){
            res += to_string(numbers[i]); 
        }
        return res;
    }
    static bool cmp(int &i,int &j) {
        string si = to_string(i);
        string sj = to_string(j);
        return si+sj<sj+si; // 2 23和23 2
    }
};

33、丑數(shù)

把只包含質(zhì)因子2、3和5的數(shù)稱作丑數(shù)(Ugly Number)。例如6、8都是丑數(shù),但14不是,因?yàn)樗|(zhì)因子7。 習(xí)慣上我們把1當(dāng)做是第一個(gè)丑數(shù)。求按從小到大的順序的第N個(gè)丑數(shù)。

/*
 如果p是丑數(shù),那么p=2^x * 3^y * 5^z, 且x,y,z需滿足是前面的丑數(shù)
 初始x=y=z=1, 2^x、3^y、5^z最小的數(shù)2^x加進(jìn)結(jié)果,x在結(jié)果中位置后移一位
*/
class Solution {
public:
    int GetUglyNumber_Solution(int index) {
        if(index < 7) return index;
        vector<int> res(index);
        res[0] = 1;
        int x=0, y=0, z=0;
        for(int i=1;i<index;i++){
            res[i] = min(min(res[x]*2,res[y]*3),res[z]*5);
            if(res[i] == res[x]*2) x++;
            if(res[i] == res[y]*3) y++;
            if(res[i] == res[z]*5) z++;
        }
        return res[index-1];
    }
};

34、第一個(gè)只出現(xiàn)一次的字符

在一個(gè)字符串(0<=字符串長度<=10000,全部由字母組成)中找到第一個(gè)只出現(xiàn)一次的字符,并返回它的位置, 如果沒有則返回 -1(需要區(qū)分大小寫).

class Solution {
public:
    int FirstNotRepeatingChar(string str) {
        //字符在計(jì)算機(jī)中以ASCII碼的形式存儲(chǔ),當(dāng)字符作為數(shù)組下標(biāo)時(shí),其表示的下標(biāo)值為該字符的ASCII碼的十進(jìn)制值
        //0-9:  48-57, A-Z:  65-90, a-z:  97-122
        map<char,int> map; //map支持int,char,string
        for(int i=0;i<str.size();i++){
            map[str[i]]++;
        }
        for(int i=0;i<str.size();i++){
            if(map[str[i]] == 1) return i;
        }
        return -1;
    }
};

35、數(shù)組中的逆序?qū)?/p>

在數(shù)組中的兩個(gè)數(shù)字,如果前面一個(gè)數(shù)字大于后面的數(shù)字,則這兩個(gè)數(shù)字組成一個(gè)逆序?qū)Α]斎胍粋€(gè)數(shù)組,求出這個(gè)數(shù)組中的逆序?qū)Φ目倲?shù)P。并將P對(duì)1000000007取模的結(jié)果輸出。 即輸出P%1000000007

輸入描述:
題目保證輸入的數(shù)組中沒有的相同的數(shù)字
數(shù)據(jù)范圍:對(duì)于%50的數(shù)據(jù),size<=10^4對(duì)于%75的數(shù)據(jù),size<=10^5對(duì)于%100的數(shù)據(jù),size<=2*10^5

示例:
輸入   1,2,3,4,5,6,7,0
輸出   7

/*
 先把數(shù)組分割成子數(shù)組,先統(tǒng)計(jì)出子數(shù)組內(nèi)部的逆序?qū)Φ臄?shù)目,然后再統(tǒng)計(jì)出兩個(gè)相鄰子數(shù)組之間的逆序?qū)Φ臄?shù)目
 在統(tǒng)計(jì)逆序?qū)Φ倪^程中,還需要對(duì)數(shù)組進(jìn)行排序,每一次比較的時(shí)候
 都把較大的數(shù)字從后面往前復(fù)制到一個(gè)輔助數(shù)組中,確保輔助數(shù)組copy中的數(shù)字是遞增排序的
 交換copy和data:在每次的操作中,當(dāng)前傳入函數(shù)中第一項(xiàng),比較的結(jié)果都存放到第二項(xiàng)中,需要交叉保證下一次是排序的
 輸入[7,5,6,4], 最后的結(jié)果copy[4,5,6,7], data[5,7,4,6]
*/
class Solution {
public:
    int InversePairs(vector<int> data) {
        if(data.size()==0) return 0;
        vector<int>copy(data); //使用data初始化copy
        long long P = InversePairsCore(data,copy,0,data.size()-1);
        return P%1000000007;
    }
    long long InversePairsCore(vector<int> &data,vector<int> &copy,int l,int r) {
        if(l == r){
            copy[l] = data[l]; return 0;
        }
        int mid = (l+r)/2;
        long long left = InversePairsCore(copy,data,l,mid);
        long long right = InversePairsCore(copy,data,mid+1,r);
        int i = mid,j = r;
        long long count = 0; //需要long long,int的話最后一個(gè)例子會(huì)溢出測試不通過
        int cur = r;
        while(i>=l && j>=mid+1){
            if(data[i]>data[j]){ //3 8,4 6  8>6
                count += j-mid;
                copy[cur--] = data[i]; i--;
            }
            else{
                copy[cur--] = data[j]; j--;
            }
        }
        while(i>=l){
            copy[cur--] = data[i]; i--;
        }
        while(j>=mid+1){
            copy[cur--] = data[j]; j--;
        }
        return left+right+count;
    }
};

36、兩個(gè)鏈表的第一個(gè)公共節(jié)點(diǎn)
輸入兩個(gè)鏈表,找出它們的第一個(gè)公共結(jié)點(diǎn)。

/*
struct ListNode {
 int val;
 struct ListNode *next;
 ListNode(int x) :
   val(x), next(NULL) {
 }
};*/
class Solution {
public:
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
        //找出2個(gè)鏈表的長度,然后讓長的先走兩個(gè)鏈表的長度差,然后再一起走
        int len1 = getlen(pHead1);
        int len2 = getlen(pHead2);
        int dis = len1-len2>0?len1-len2:len2-len1;
        while(dis!=0){
            if(len1>len2) pHead1 = pHead1->next;
            else pHead2 = pHead2->next;
            dis--;
        }
        while(pHead1){
            if(pHead1 == pHead2) return pHead1;
            pHead1 = pHead1->next;
            pHead2 = pHead2->next;
        }
        return NULL;
    }
    
    int getlen(ListNode* p) {
        int res = 0;
        ListNode* root = p;
        while(root){
            res++;
            root = root->next;
        }
       return res;
    }
};

37、數(shù)字在排序數(shù)組中出現(xiàn)的次數(shù)
統(tǒng)計(jì)一個(gè)數(shù)字在排序數(shù)組中出現(xiàn)的次數(shù)。

class Solution {
public:
    int GetNumberOfK(vector<int> data ,int k) {
        if(data.empty()) return 0;
        return findk(data,k,0,data.size()-1);
    }
    int findk(vector<int> data ,int k, int l, int r){
        if(l>r) return -1;
        int mid = (l+r)/2;
        if(data[mid] == k){ //找到了一個(gè)k,往data兩邊擴(kuò)展,統(tǒng)計(jì)k的個(gè)數(shù)
            int i = mid-1; //往左找
            while(i >= l){
                if(data[i] == k) i--;
                else break;
            }
            int j = mid+1; //往右找
            while(j <= r){
                if(data[j] == k) j++;
                else break;
            }
            return j-i-1;
        }
        if(findk(data,k,l,mid-1)>0) return findk(data,k,l,mid-1);
        if(findk(data,k,mid+1,r)>0) return findk(data,k,mid+1,r);
        return 0;
    }
};

38、二叉樹的深度
輸入一棵二叉樹,求該樹的深度。從根結(jié)點(diǎn)到葉結(jié)點(diǎn)依次經(jīng)過的結(jié)點(diǎn)(含根、葉結(jié)點(diǎn))形成樹的一條路徑,最長路徑的長度為樹的深度。

/*
struct TreeNode {
 int val;
 struct TreeNode *left;
 struct TreeNode *right;
 TreeNode(int x) :
   val(x), left(NULL), right(NULL) {
 }
};*/
class Solution {
public:
    int TreeDepth(TreeNode* pRoot) {
        if(!pRoot) return 0;
        return max(TreeDepth(pRoot->left),TreeDepth(pRoot->right))+1;
    }
};

39、平衡二叉樹
輸入一棵二叉樹,判斷該二叉樹是否是平衡二叉樹。

class Solution {
public:
    //左右子樹均為平衡二叉樹,且左右子樹層高不超過1
    bool IsBalanced_Solution(TreeNode* pRoot) {
        if(!pRoot) return true;
        return IsBalanced_Solution(pRoot->left)
            && IsBalanced_Solution(pRoot->right)
            && abs(getlen(pRoot->left)-getlen(pRoot->right))<=1;
    }
    int getlen(TreeNode* p){
        if(!p) return 0;
        return max(getlen(p->left),getlen(p->right))+1;
    }
};

40、數(shù)組中只出現(xiàn)一次的數(shù)字
一個(gè)整型數(shù)組里除了兩個(gè)數(shù)字之外,其他的數(shù)字都出現(xiàn)了兩次。請(qǐng)寫程序找出這兩個(gè)只出現(xiàn)一次的數(shù)字。

/*
 異或性質(zhì):
 交換律:a ^ b ^ c  <=> a ^ c ^ b,倆兩相同的移到一起
 相同的數(shù)異或?yàn)?: n ^ n => 0
 任何數(shù)于0異或?yàn)槿魏螖?shù) 0 ^ n => n
 
 遍歷異或后,只剩下兩單個(gè)的異或了,結(jié)果res的二進(jìn)制至少有一位為1
 取第一個(gè)1所在的位數(shù)index,原數(shù)組分成第index位為1和為0
 相同的數(shù)肯定在一個(gè)組,兩個(gè)單的在不同的組
*/
class Solution {
public:
    void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
        int res = 0;
        for(int i=0;i<data.size();i++){
            res ^= data[i];
        }
        int index = findbit1(res);
        for(int i=0;i<data.size();i++){
            if((data[i] >> index & 1)== 1) num1[0]^=data[i];
            else num2[0]^=data[i];
        }
    }
    
    int findbit1(int n) {
        int index = 0;
        while((n&1) == 0 && index<32){ //當(dāng)前位為0且未溢出
            index++; n >>= 1;
        }
        return index;
    }
};

41、和為S的連續(xù)正數(shù)序列
小明很喜歡數(shù)學(xué),有一天他在做數(shù)學(xué)作業(yè)時(shí),要求計(jì)算出9~16的和,他馬上就寫出了正確答案是100。但是他并不滿足于此,他在想究竟有多少種連續(xù)的正數(shù)序列的和為100(至少包括兩個(gè)數(shù))。沒多久,他就得到另一組連續(xù)正數(shù)和為100的序列:18,19,20,21,22。現(xiàn)在把問題交給你,你能不能也很快的找出所有和為S的連續(xù)正數(shù)序列? Good Luck!
輸出描述:
輸出所有和為S的連續(xù)正數(shù)序列。序列內(nèi)按照從小至大的順序,序列間按照開始數(shù)字從小到大的順序

class Solution {
public:
    vector<vector<int> > FindContinuousSequence(int sum) {
        vector<vector<int> > res;
        vector<int> part;
        int i = 1,j = 2;
        while(i < j){
            int count = (i+j)*(j-i+1)/2; //i~j的和
            if(count == sum){ //將i~j插入res
                part.clear();
                for(int k=i;k<=j;k++){
                    part.push_back(k);
                }
                res.push_back(part);
                i++;
            }
            else if(count < sum) j++; //右窗口右移
            else i++; //左窗口右移
            
        }
        return res;
    }
};

42、和為S的兩個(gè)數(shù)字
輸入一個(gè)遞增排序的數(shù)組和一個(gè)數(shù)字S,在數(shù)組中查找兩個(gè)數(shù),使得他們的和正好是S,如果有多對(duì)數(shù)字的和等于S,輸出兩個(gè)數(shù)的乘積最小的。
輸出描述:
對(duì)應(yīng)每個(gè)測試案例,輸出兩個(gè)數(shù),小的先輸出。

class Solution {
public:
    vector<int> FindNumbersWithSum(vector<int> array,int sum) {
        vector<int> res;
        int i = 0, j = array.size()-1;
        while(i<j){
            if(array[i]+array[j] == sum){ //1 3 4 6,1*6<3*4,越邊邊乘積越小
                res.push_back(array[i]);
                res.push_back(array[j]);
                break;
            }
            else if(array[i]+array[j] > sum) j--;
            else i++;
        }
        return res;
    }
};

43、左旋轉(zhuǎn)字符串
匯編語言中有一種移位指令叫做循環(huán)左移(ROL),現(xiàn)在有個(gè)簡單的任務(wù),就是用字符串模擬這個(gè)指令的運(yùn)算結(jié)果。對(duì)于一個(gè)給定的字符序列S,請(qǐng)你把其循環(huán)左移K位后的序列輸出。例如,字符序列S=”abcXYZdef”,要求輸出循環(huán)左移3位后的結(jié)果,即“XYZdefabc”。是不是很簡單?OK,搞定它!

class Solution {
public:
    string LeftRotateString(string str, int n) {
        int len = str.size();
        if(len == 0) return "";
        n = n%len; //str = ”abcXYZ”, n = 1
        str += str; //str = ”abcXYZabcXYZ”
        return str.substr(n, len); //從下標(biāo)n開始的len個(gè)字符
    }
};

44、翻轉(zhuǎn)單詞順序列
??妥罱鼇砹艘粋€(gè)新員工Fish,每天早晨總是會(huì)拿著一本英文雜志,寫些句子在本子上。同事Cat對(duì)Fish寫的內(nèi)容頗感興趣,有一天他向Fish借來翻看,但卻讀不懂它的意思。例如,“student. a am I”。后來才意識(shí)到,這家伙原來把句子單詞的順序翻轉(zhuǎn)了,正確的句子應(yīng)該是“I am a student.”。Cat對(duì)一一的翻轉(zhuǎn)這些單詞順序可不在行,你能幫助他么?

class Solution {
public:
    string ReverseSentence(string str) {
        string res;
        stack<string> stack;
        string tmp;
        for(int i=0;i<str.size();i++){
            if(str[i] == ' '){
                stack.push(tmp);
                tmp.clear();
            }
            else tmp.push_back(str[i]);
        }
        stack.push(tmp);
        while(!stack.empty()){
            res += ' ' + stack.top();
            stack.pop();
        }
        return res.erase(0,1);
    }
};

45、撲克牌順子
LL今天心情特別好,因?yàn)樗ベI了一副撲克牌,發(fā)現(xiàn)里面居然有2個(gè)大王,2個(gè)小王(一副牌原本是54張_)…他隨機(jī)從中抽出了5張牌,想測測自己的手氣,看看能不能抽到順子,如果抽到的話,他決定去買體育彩票,嘿嘿?。?ldquo;紅心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是順子…LL不高興了,他想了想,決定大\小 王可以看成任何數(shù)字,并且A看作1,J為11,Q為12,K為13。上面的5張牌就可以變成“1,2,3,4,5”(大小王分別看作2和4),“So Lucky!”。LL決定去買體育彩票啦。 現(xiàn)在,要求你使用這幅牌模擬上面的過程,然后告訴我們LL的運(yùn)氣如何, 如果牌能組成順子就輸出true,否則就輸出false。為了方便起見,你可以認(rèn)為大小王是0。

/*
 max 記錄 最大值,min 記錄  最小值,min ,max 都不記0
 滿足條件 max - min <5;除0外沒有重復(fù)的數(shù)字(牌);數(shù)組長度 為5
*/
class Solution {
public:
    bool IsContinuous( vector<int> numbers ) { // 5張牌
        if(numbers.size()!=5) return false;
        int max = -1, min = 14;
        int* flag = new int[14](); //初始化數(shù)組全為 0
        for(int i=0;i<numbers.size();i++){
            if(numbers[i] == 0) continue;
            int tmp = numbers[i];
            if(flag[tmp] == 1) return false; //重復(fù)
            else{
                if(tmp < min) min = tmp;
                if(tmp > max) max = tmp;
                flag[tmp] = 1;
            }
        }
        delete[] flag;
        return max-min<5;
    }
};

46、孩子們的游戲(圓圈中最后剩下的數(shù))
每年六一兒童節(jié),??投紩?huì)準(zhǔn)備一些小禮物去看望孤兒院的小朋友,今年亦是如此。HF作為牛客的資深元老,自然也準(zhǔn)備了一些小游戲。其中,有個(gè)游戲是這樣的:首先,讓小朋友們圍成一個(gè)大圈。然后,他隨機(jī)指定一個(gè)數(shù)m,讓編號(hào)為0的小朋友開始報(bào)數(shù)。每次喊到m-1的那個(gè)小朋友要出列唱首歌,然后可以在禮品箱中任意的挑選禮物,并且不再回到圈中,從他的下一個(gè)小朋友開始,繼續(xù)0…m-1報(bào)數(shù)…這樣下去…直到剩下最后一個(gè)小朋友,可以不用表演,并且拿到??兔F的“名偵探柯南”典藏版(名額有限哦!!_)。請(qǐng)你試著想下,哪個(gè)小朋友會(huì)得到這份禮品呢?(注:小朋友的編號(hào)是從0到n-1)

class Solution {
public:
    int LastRemaining_Solution(int n, int m) {
        if (m == 0 || n == 0) return -1;
        int* flag = new int[n]();//初始化數(shù)組全為 0
        int i = -1,left = n,step = 0;
        while(left>0){
            i++; //0
            if(i == n) i = 0; //模擬環(huán)
            if(flag[i] == 1) continue; //跳過被刪除的對(duì)象
            step++;
            if(step == m){
                step = 0;
                flag[i] = 1;
                left--;
            }
        }
        return i;
    }
};

47、求1+2+3+…+n
求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等關(guān)鍵字及條件判斷語句(A?B:C)。

/*
 int Sum_Solution(int n) {
     if(n == 0) return 0;
     return n+Sum_Solution(n-1);
 }
 將此段代碼改寫成不使用for、while、if、else、switch、case等關(guān)鍵字及條件判斷語句
*/
class Solution {
public:
    int Sum_Solution(int n) {
        int res = n;
        res && (res+=Sum_Solution(n-1));
        //當(dāng)n==0時(shí),只執(zhí)行前面的判斷,為false,然后直接返回0;
        //當(dāng)n>0時(shí),執(zhí)行sum+=Sum_Solution(n-1),實(shí)現(xiàn)遞歸計(jì)算Sum_Solution(n)
        return res;
    }
};

48、不用加減乘除做加法
寫一個(gè)函數(shù),求兩個(gè)整數(shù)之和,要求在函數(shù)體內(nèi)不得使用+、-、*、/四則運(yùn)算符號(hào)。

/*
 兩數(shù)相與再左移一位,表示相加進(jìn)位的值 101&111=101 左移1,1010
 兩數(shù)異或,表示相加不算進(jìn)位的值 101^111=010
 兩者相加為和,(101&111)<<1 + 101^111 = 1100,即調(diào)用函數(shù)本身,直到進(jìn)位為0
*/
class Solution {
public:
    int Add(int num1, int num2) {
        while(num2!=0){
            int tmp = num1^num2; //相加不算進(jìn)位的值
            num2 = (num1&num2)<<1; //相加進(jìn)位的值
            num1 = tmp;
        }
        return num1;
    }
};

49、把字符串轉(zhuǎn)換成整數(shù)

將一個(gè)字符串轉(zhuǎn)換成一個(gè)整數(shù)(實(shí)現(xiàn)Integer.valueOf(string)的功能,但是string不符合數(shù)字要求時(shí)返回0),要求不能使用字符串轉(zhuǎn)換整數(shù)的庫函數(shù)。 數(shù)值為0或者字符串不是一個(gè)合法的數(shù)值則返回0。
輸入描述:
輸入一個(gè)字符串,包括數(shù)字字母符號(hào),可以為空
輸出描述:
如果是合法的數(shù)值表達(dá)則返回該數(shù)字,否則返回0

輸入: +2147483647 , 1a33
輸出: 2147483647 , 0

/*
字符"0123456789"的值是連續(xù)的,如果c"0123456789"范圍內(nèi)
int a = c - '0'就是對(duì)應(yīng)整數(shù)值
從后往前,最后判斷符號(hào)位
*/
class Solution {
public:
   int StrToInt(string str) {
       if(str.empty()) return 0;
       int res = 0,base = 1;
       for(int i = str.size()-1;i>=0;i--){
           if(str[i]>='0' && str[i]<='9'){
               res += base*(int)(str[i]-'0');
               base *= 10;
           }
           else if(str[i] == '-'){
               if(i == 0) return -res; //-123
           }
           else if(str[i] == '+'){
               if(i == 0) return res; //+123
           }
           else return 0; //1a3
       }
       return res; //123
   }
};

50、數(shù)組中重復(fù)的數(shù)字
在一個(gè)長度為n的數(shù)組里的所有數(shù)字都在0到n-1的范圍內(nèi)。 數(shù)組中某些數(shù)字是重復(fù)的,但不知道有幾個(gè)數(shù)字是重復(fù)的。也不知道每個(gè)數(shù)字重復(fù)幾次。請(qǐng)找出數(shù)組中任意一個(gè)重復(fù)的數(shù)字。 例如,如果輸入長度為7的數(shù)組{2,3,1,0,2,5,3},那么對(duì)應(yīng)的輸出是第一個(gè)重復(fù)的數(shù)字2。

/*
 數(shù)字的范圍保證在0 ~ n-1 之間,所以可以利用現(xiàn)有數(shù)組設(shè)置標(biāo)志
 當(dāng)一個(gè)數(shù)字i被訪問過后,可以設(shè)置對(duì)應(yīng)位上的數(shù)numbers[i] += n
 再次訪問i時(shí),發(fā)現(xiàn)numbers[i] >=n,直接返回i
*/
class Solution {
public:
    // Parameters:
    //        numbers:     an array of integers
    //        length:      the length of array numbers
    //        duplication: (Output) the duplicated number in the array number
    // Return value:       true if the input is valid, and there are some duplications in the array number
    //                     otherwise false
    bool duplicate(int numbers[], int length, int* duplication) {
        for(int i=0;i<length;i++){ //2,3,1,0,2,5,3
            int cur = numbers[i];
            if(cur >= length) cur = cur-length;
            if(numbers[cur] >= length){
                *duplication = cur;
                return true;
            }
            numbers[cur] += length;
        }
        return false;
    }
};

51、構(gòu)建乘積數(shù)組
給定一個(gè)數(shù)組A[0,1,…,n-1],請(qǐng)構(gòu)建一個(gè)數(shù)組B[0,1,…,n-1],其中B中的元素B[i]=A[0]A[1]…*A[i-1]A[i+1]…*A[n-1]。不能使用除法。

/*
 1                             第一項(xiàng)左側(cè)
 a[0]                          第二項(xiàng)左側(cè)
 a[0]*a[1]
 a[0]*a[1]*a[2]
 a[0]*a[1]*a[2]...*a[n-2]      第n項(xiàng)左側(cè)
 
 1                             第n項(xiàng)右側(cè)
 a[n-1]
 a[n-1]*a[n-2]
 a[n-1]*a[n-2]*a[n-3]...*a[2]  第二項(xiàng)左側(cè)
 a[n-1]*a[n-2]*a[n-3]...*a[1]  第一項(xiàng)右側(cè)
*/
class Solution {
public:
    vector<int> multiply(const vector<int>& A) {
        vector<int> res;
        if(A.empty()) return res;
        int tmp = 1;
        for(int i=0;i<A.size();i++){ //左邊乘
            res.push_back(tmp);
            tmp *= A[i];
        } 
        tmp = 1;
        for(int i=A.size()-1;i>=0;i--){ //右邊乘
            res[i] *= tmp;
            tmp *= A[i];
        }
        return res;
    }
};

52、正則表達(dá)式匹配
請(qǐng)實(shí)現(xiàn)一個(gè)函數(shù)用來匹配包括’.‘和’‘的正則表達(dá)式。模式中的字符’.‘表示任意一個(gè)字符,而’'表示它前面的字符可以出現(xiàn)任意次(包含0次)。 在本題中,匹配是指字符串的所有字符匹配整個(gè)模式。例如,字符串"aaa"與模式"a.a"和"abaca"匹配,但是與"aa.a"和"ab*a"均不匹配

/*
 當(dāng)?shù)诙€(gè)字符不是“*”時(shí):
 1、第一個(gè)字符匹配,字符串和模式后移1個(gè)字符,繼續(xù)匹配 
 2、第一個(gè)字符不匹配,返回false
 當(dāng)?shù)诙€(gè)字符是“*”時(shí):
 1、第一個(gè)字符不匹配,模式后移2個(gè)字符,繼續(xù)匹配
 2、第一個(gè)字符匹配,可以有3種情況:
    (1)模式后移2字符,相當(dāng)于x*被忽略,x出現(xiàn)0次;
    (2)字符串后移1字符,模式后移2字符,相當(dāng)于x出現(xiàn)一次;
    (3)字符串后移1字符,模式不變,相當(dāng)于x出現(xiàn)多次次;
 注:匹配指值相同,或pattern為'.',字符串未到尾
*/
class Solution {
public:
    bool match(char* str, char* pattern)
    {
        if(*str == '\0' && *pattern == '\0') return true;
        if(*str != '\0' && *pattern == '\0') return false;
        if(*(pattern+1) != '*'){
            if(*str==*pattern || *pattern=='.'&&*str!='\0'){
                return match(str+1,pattern+1);
            }
            else return false;
        }
        else{
            if(*str==*pattern || *pattern=='.'&&*str!='\0'){
                return match(str,pattern+2)|| match(str+1,pattern+2)|| match(str+1,pattern);
            }
            else return match(str,pattern+2);
        }
    }
};

53、表示數(shù)值的字符串
請(qǐng)實(shí)現(xiàn)一個(gè)函數(shù)用來判斷字符串是否表示數(shù)值(包括整數(shù)和小數(shù))。例如,字符串"+100",“5e2”,"-123",“3.1416"和”-1E-16"都表示數(shù)值。 但是"12e",“1a3.14”,“1.2.3”,"±5"和"12e+4.3"都不是。

/*
 1、+、-
  第一次出現(xiàn)+-符號(hào),且不在首位,必須緊接在e之后
  第二次出現(xiàn)+-符號(hào),必須緊接在e之后
 2、e、E
  e后不為空
  不能雙e
 3、.
  .前不能有.或e
 4、其他
  return false
*/
class Solution {
public:
    bool isNumeric(char* string) {
        // 標(biāo)記符號(hào)、小數(shù)點(diǎn)、e是否出現(xiàn)過
        bool hasSign = false, hasPoint = false, hasE = false; 
        for(int i=0;string[i];i++){
            if(string[i] == '+' || string[i] == '-'){
                if(!hasSign && i>0 && string[i-1]!='e' && string[i-1]!='E') return false;
                if(hasSign && string[i-1]!='e' && string[i-1]!='E') return false;
                hasSign = true;
            }
            else if(string[i] == 'e' || string[i] == 'E'){
                if(string[i+1] == '\0' || hasE) return false;
                hasE = true;
            }
            else if(string[i] == '.'){
                if(hasPoint || hasE) return false;
                hasPoint = true;
            }
            else if(string[i] < '0' || string[i] > '9') return false;
        }
        return true;
    }
};
 

54、字符流中第一個(gè)不重復(fù)的字符
請(qǐng)實(shí)現(xiàn)一個(gè)函數(shù)用來找出字符流中第一個(gè)只出現(xiàn)一次的字符。例如,當(dāng)從字符流中只讀出前兩個(gè)字符"go"時(shí),第一個(gè)只出現(xiàn)一次的字符是"g"。當(dāng)從該字符流中讀出前六個(gè)字符“google"時(shí),第一個(gè)只出現(xiàn)一次的字符是"l"。
輸出描述:
如果當(dāng)前字符流沒有存在出現(xiàn)一次的字符,返回#字符。

/*
 字符在計(jì)算機(jī)中以ASCII碼的形式存儲(chǔ),當(dāng)字符作為數(shù)組下標(biāo)時(shí),其表示的下標(biāo)值為該字符的ASCII碼的十進(jìn)制值
 0-9:  48-57  ,A-Z:  65-90  ,a-z:  97-122   ASCII碼:0~127
*/
class Solution
{
public:
    string s;
    char flag[128] = {0}; 
    void Insert(char ch) {
        s += ch;
        flag[ch]++;
    }
    
    char FirstAppearingOnce() {
        for(int i=0;i<s.size();i++){
            if(flag[s[i]] == 1) return s[i];
        }
        return '#';
    }
};

55、鏈表中環(huán)的入口結(jié)點(diǎn)
給一個(gè)鏈表,若其中包含環(huán),請(qǐng)找出該鏈表的環(huán)的入口結(jié)點(diǎn),否則,輸出null。

/*
 如果有環(huán),快慢指針總會(huì)相遇
 1——2——3——4——5——6
          |     |
          9——8——7
 假設(shè)快慢指針相遇在6,有1~6走的=6~6走的
 1~6走的 = 1~入環(huán)點(diǎn)+入環(huán)點(diǎn)~6
 6~6走的 = 6~入環(huán)點(diǎn)+入環(huán)點(diǎn)~6
 則當(dāng)快指針從1重新開始,兩指針?biāo)俣认嗤俅蜗嘤黾礊槿肟诠?jié)點(diǎn)
*/
/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead) {
        //快慢指針,判斷是否有環(huán)
        bool hasLoop = false;
        ListNode* fast = pHead;
        ListNode* slow = pHead;
        while(fast && fast->next){
            fast = fast->next->next;
            slow = slow->next;
            if(fast == slow){
                hasLoop = true;
                break;
            }
        }
        //尋找環(huán)的入口節(jié)點(diǎn)
        if(hasLoop){
            fast = pHead;
            while(fast != slow){
                fast = fast->next;
                slow = slow->next;
            }
            return slow;
        }
        return NULL;
    }
};
 

56、刪除鏈表中重復(fù)的結(jié)點(diǎn)
在一個(gè)排序的鏈表中,存在重復(fù)的結(jié)點(diǎn),請(qǐng)刪除該鏈表中重復(fù)的結(jié)點(diǎn),重復(fù)的結(jié)點(diǎn)不保留,返回鏈表頭指針。 例如,鏈表1->2->3->3->4->4->5 處理后為 1->2->5

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead) {
        ListNode* root = new ListNode(0);//設(shè)為幾無所謂
        ListNode* h = root; //標(biāo)記當(dāng)前位置
        h->next = pHead;
        while(h->next && h->next->next){//至少兩個(gè)節(jié)點(diǎn)
            ListNode* tmp = h->next->next;
            if(h->next->val == tmp->val){//兩節(jié)點(diǎn)相同
                while(tmp && h->next->val == tmp->val){
                    tmp = tmp->next;
                }
                h->next = tmp; //刪除操作
            }
            else h = h->next;
        }
        return root->next;
    }
};

57、二叉樹的下一個(gè)結(jié)點(diǎn)
給定一個(gè)二叉樹和其中的一個(gè)結(jié)點(diǎn),請(qǐng)找出中序遍歷順序的下一個(gè)結(jié)點(diǎn)并且返回。注意,樹中的結(jié)點(diǎn)不僅包含左右子結(jié)點(diǎn),同時(shí)包含指向父結(jié)點(diǎn)的指針。

/*
 3種情況:
       1              1              1
      / \            / \            / \
     2   3          2   4          2   5
        / \        /              / \
       4   5      3              3   4
  cur=1,next=4   cur=2,next=1   cur=4,next=1
 情況1,有右子樹,返回右子樹的左下角
 情況2,無右子樹,且是父結(jié)點(diǎn)的左子樹,返回父結(jié)點(diǎn)
 情況3,無右子樹,且是父結(jié)點(diǎn)的右子樹,返回父結(jié)點(diǎn)的左上角的父結(jié)點(diǎn)
*/
/*
struct TreeLinkNode {
    int val;
    struct TreeLinkNode *left;
    struct TreeLinkNode *right;
    struct TreeLinkNode *next;
    TreeLinkNode(int x) :val(x), left(NULL), right(NULL), next(NULL) {
        
    }
};
*/
class Solution {   
public:
    TreeLinkNode* GetNext(TreeLinkNode* pNode) {
        if(pNode->right){
            TreeLinkNode* res = pNode->right;
            while(res->left){
                res = res->left;
            }
            return res;
        }
        else{  
            while(pNode->next && pNode->next->right == pNode){
                pNode = pNode->next;
            }
            return pNode->next;
        }
        
    }
};

58、對(duì)稱的二叉樹
請(qǐng)實(shí)現(xiàn)一個(gè)函數(shù),用來判斷一顆二叉樹是不是對(duì)稱的。注意,如果一個(gè)二叉樹同此二叉樹的鏡像是同樣的,定義其為對(duì)稱的。

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NUL L) {
    }
};
*/
class Solution {
public:
    bool isSymmetrical(TreeNode* pRoot){
        if(!pRoot) return true;
        return ismoir(pRoot->left,pRoot->right);
    }
    bool ismoir(TreeNode* l,TreeNode* r){//是鏡像的
        if(!l && !r) return true;//都不存在
        if(l && r) return l->val==r->val && ismoir(l->left,r->right) && ismoir(r->left,l->right);
        return false;// 有且僅有1個(gè)存在
    }
};

59、按之字形順序打印二叉樹
請(qǐng)實(shí)現(xiàn)一個(gè)函數(shù)按照之字形打印二叉樹,即第一行按照從左到右的順序打印,第二層按照從右至左的順序打印,第三行按照從左到右的順序打印,其他行以此類推。

/*
        1         ——> stack1 存奇數(shù)層,順序
       / \
      2   3       <—— stack2 存偶數(shù)層,逆序,先left后right
     / \  / \
    4  5 6   7    ——> stack1 存奇數(shù)層,順序,先right后left
*/
/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
    vector<vector<int> > Print(TreeNode* pRoot) {
        vector<vector<int> > res;
        if(!pRoot) return res;
        stack<TreeNode*> stack1,stack2;
        stack1.push(pRoot);
        while(!stack1.empty() || !stack2.empty()){
            if(!stack1.empty()){
                vector<int> tmp;
                while(!stack1.empty()){
                    if(stack1.top()->left) stack2.push(stack1.top()->left);
                    if(stack1.top()->right) stack2.push(stack1.top()->right);
                    tmp.push_back(stack1.top()->val);
                    stack1.pop();
                }
                res.push_back(tmp);
            }
            if(!stack2.empty()){
                vector<int> tmp;
                while(!stack2.empty()){
                    if(stack2.top()->right) stack1.push(stack2.top()->right);
                    if(stack2.top()->left) stack1.push(stack2.top()->left);
                    tmp.push_back(stack2.top()->val);
                    stack2.pop();
                }
                res.push_back(tmp);
            }
        }
        return res;
    }
};

60、把二叉樹打印成多行
從上到下按層打印二叉樹,同一層結(jié)點(diǎn)從左至右輸出。每一層輸出一行。

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
        vector<vector<int> > Print(TreeNode* pRoot) {
            vector<vector<int> > res;
            if(!pRoot) return res;
            queue<TreeNode*> queue;
            queue.push(pRoot);
            while(!queue.empty()){
                int num = queue.size();
                vector<int> tmp;
                while(num!=0){
                    if(queue.front()->left) queue.push(queue.front()->left);
                    if(queue.front()->right) queue.push(queue.front()->right);
                    tmp.push_back(queue.front()->val);
                    queue.pop();
                    num--;
                }
                res.push_back(tmp);
            }
            return res;
        }
    
};

61、序列化二叉樹
請(qǐng)實(shí)現(xiàn)兩個(gè)函數(shù),分別用來序列化和反序列化二叉樹

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
    char* Serialize(TreeNode *root) {
        if(!root) return NULL;
        string s;
        queue<TreeNode*> queue;
        queue.push(root);
        while(!queue.empty()){
            if(queue.front()){
                queue.push(queue.front()->left);
                queue.push(queue.front()->right);
                s += to_string(queue.front()->val)+",";
            }
            else s += "#,";
            queue.pop();
        }
        char* res = strdup(s.c_str());
        /* 另一種寫法,不用strdup()
        char* res = new char[s.size() + 1];
        int i;
        for(i=0;i<s.size();i++) res[i]=s[i];
        res[i] = '\0';
        */
        return res;
    }
    TreeNode* Deserialize(char *str) {
        if(!str) return NULL;
        int i = 0;
        auto head = getnode(str,i);
        queue<TreeNode*> queue;
        queue.push(head);
        while(!queue.empty()){
            queue.front()->left = getnode(str,i);
            queue.front()->right = getnode(str,i);
            if(queue.front()->left) queue.push(queue.front()->left);
            if(queue.front()->right) queue.push(queue.front()->right);
            queue.pop();
        }
        return head;
    }
    TreeNode* getnode(char *str,int &i){
        if(str[i] == ',') i++;
        if(str[i] == '#'){
            i += 2;
            return NULL;
        }
        string s;
        while(str[i] != ',' && str[i] != '\0'){
            s += str[i];
            i++;
        }
        if(!s.empty()) return new TreeNode(stoi(s));
        return NULL;
    }
};
 

62、二叉搜索樹的第k個(gè)結(jié)點(diǎn)
給定一棵二叉搜索樹,請(qǐng)找出其中的第k小的結(jié)點(diǎn)。例如, (5,3,7,2,4,6,8) 中,按結(jié)點(diǎn)數(shù)值大小順序第三小結(jié)點(diǎn)的值為4。

/*
 二叉搜索樹:左子樹上所有結(jié)點(diǎn)的值均小于它的根結(jié)點(diǎn)的值,右子樹上所有結(jié)點(diǎn)的值均大于它的根結(jié)點(diǎn)的值
 二叉搜索樹按照中序遍歷得到遞增的順序,壓入棧,第k個(gè)結(jié)點(diǎn)就是結(jié)果
*/
/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/

class Solution {
public:
    stack<TreeNode*> stack;
    TreeNode* KthNode(TreeNode* pRoot, int k){
        if(k <= 0) return NULL;
        sortmid(pRoot,k);
        if(stack.size() < k) return NULL; //k大于節(jié)點(diǎn)數(shù)
        return stack.top();
    }
    
    void sortmid(TreeNode* pRoot, int k) {
        if(!pRoot) return;
        if(stack.size()!=k) sortmid(pRoot->left,k);
        if(stack.size()!=k) stack.push(pRoot);
        if(stack.size()!=k) sortmid(pRoot->right,k);
    }
};
 

63、數(shù)據(jù)流中的中位數(shù)
如何得到一個(gè)數(shù)據(jù)流中的中位數(shù)?如果從數(shù)據(jù)流中讀出奇數(shù)個(gè)數(shù)值,那么中位數(shù)就是所有數(shù)值排序之后位于中間的數(shù)值。如果從數(shù)據(jù)流中讀出偶數(shù)個(gè)數(shù)值,那么中位數(shù)就是所有數(shù)值排序之后中間兩個(gè)數(shù)的平均值。我們使用Insert()方法讀取數(shù)據(jù)流,使用GetMedian()方法獲取當(dāng)前讀取數(shù)據(jù)的中位數(shù)。

/*
 使用大小頂堆,中位數(shù)是大頂堆的根節(jié)點(diǎn)與小頂堆的根節(jié)點(diǎn)和的平均數(shù)
 大頂堆,由大到小,存較小的數(shù) 7 6 5
 小頂堆,由小到大,存較大的數(shù) 8 9 10
 步驟:
 第一個(gè)插入的元素裝大頂堆
 1、每來一個(gè)插入的元素,比大頂堆堆頂元素小的裝大頂堆,否則裝小頂堆(保證大頂堆的數(shù)都比小頂堆的數(shù)小)
 2、判斷是否大頂堆裝多了,大頂堆最多比小頂堆多一個(gè),如果是,將大頂堆堆頂元素插入小頂堆
 3、判斷是否小頂堆裝多了,小頂堆小于等于大頂堆,如果是,將小頂堆堆頂元素插入大頂堆
*/
class Solution {
public:
    priority_queue<int,vector<int>,less<int> > big_heap;
    priority_queue<int,vector<int>,greater<int> > small_heap;
    void Insert(int num) {
        if(big_heap.empty() || num < big_heap.top()) big_heap.push(num);
        else small_heap.push(num);
        if(big_heap.size() == small_heap.size()+2){
            small_heap.push(big_heap.top());
            big_heap.pop();
        }
        if(big_heap.size() == small_heap.size()-1){
            big_heap.push(small_heap.top());
            small_heap.pop();
        }
    }

    double GetMedian() { 
        return small_heap.size()==big_heap.size()?(small_heap.top()+big_heap.top())/2.0:big_heap.top();
    }
};
 

64、滑動(dòng)窗口的最大值
給定一個(gè)數(shù)組和滑動(dòng)窗口的大小,找出所有滑動(dòng)窗口里數(shù)值的最大值。例如,如果輸入數(shù)組{2,3,4,2,6,2,5,1}及滑動(dòng)窗口的大小3,那么一共存在6個(gè)滑動(dòng)窗口,他們的最大值分別為{4,4,6,6,6,5}; 針對(duì)數(shù)組{2,3,4,2,6,2,5,1}的滑動(dòng)窗口有以下6個(gè): {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。

class Solution {
public:
    vector<int> maxInWindows(const vector<int>& num, unsigned int size)
    {
        vector<int> res;
        deque<int> q;//隊(duì)首為當(dāng)前窗口下最大值下標(biāo)
        for(unsigned int i=0;i<num.size();i++){
            while(!q.empty() && num[i]>num[q.back()]){//q刪掉所有比當(dāng)前元素小的,保證q降序
                q.pop_back();
            }
            if(!q.empty() && q.front()+size == i){ //若隊(duì)首超過窗口位置,刪掉
                q.pop_front();
            }
            q.push_back(i);
            if(size && i+1>=size) res.push_back(num[q.front()]); //防止size=0
        }
        return res;
    }
};

65、矩陣中的路徑
請(qǐng)?jiān)O(shè)計(jì)一個(gè)函數(shù),用來判斷在一個(gè)矩陣中是否存在一條包含某字符串所有字符的路徑。路徑可以從矩陣中的任意一個(gè)格子開始,每一步可以在矩陣中向左,向右,向上,向下移動(dòng)一個(gè)格子。如果一條路徑經(jīng)過了矩陣中的某一個(gè)格子,則之后不能再次進(jìn)入這個(gè)格子。 例如 a b c e s f c s a d e e 這樣的3 X 4 矩陣中包含一條字符串"bcced"的路徑,但是矩陣中不包含"abcb"路徑,因?yàn)樽址牡谝粋€(gè)字符b占據(jù)了矩陣中的第一行第二個(gè)格子之后,路徑不能再次進(jìn)入該格子。

class Solution {
public:
    //用一個(gè)狀態(tài)數(shù)組保存之前訪問過的字符,然后再分別按上,下,左,右遞歸
    bool hasPath(char* matrix, int rows, int cols, char* str) {
        if(!matrix || rows<=0 || cols<=0 || !str) return false;
        bool* flag = new bool[rows*cols];
        //bool* flag=(bool*)malloc(rows*cols*sizeof(bool));
        memset(flag,false,rows*cols);
        for(int i=0;i<rows;i++){
            for(int j=0;j<cols;j++){
                if(helper(matrix,rows,cols,i,j,0,str,flag)) return true;
            }
        }
        delete[] flag;
        //free(flag);
        return false;
    }
    
    bool helper(char* matrix, int rows, int cols, int i, int j, int k, char* str, bool* flag) {
        int index = i*cols+j;
        if(i<0||i>=rows||j<0||j>=cols||flag[index]||matrix[index]!=str[k]) return false;
        if(str[k+1] =='\0') return true;
        flag[index] = true;
        if( helper(matrix,rows,cols,i-1,j,k+1,str,flag)
            || helper(matrix,rows,cols,i+1,j,k+1,str,flag)
            || helper(matrix,rows,cols,i,j-1,k+1,str,flag)
            || helper(matrix,rows,cols,i,j+1,k+1,str,flag)){
            return true;
        }
        flag[index] = false;
        return false;
    }
};
 

66、機(jī)器人的運(yùn)動(dòng)范圍
地上有一個(gè)m行和n列的方格。一個(gè)機(jī)器人從坐標(biāo)0,0的格子開始移動(dòng),每一次只能向左,右,上,下四個(gè)方向移動(dòng)一格,但是不能進(jìn)入行坐標(biāo)和列坐標(biāo)的數(shù)位之和大于k的格子。 例如,當(dāng)k為18時(shí),機(jī)器人能夠進(jìn)入方格(35,37),因?yàn)?+5+3+7 = 18。但是,它不能進(jìn)入方格(35,38),因?yàn)?+5+3+8 = 19。請(qǐng)問該機(jī)器人能夠達(dá)到多少個(gè)格子?

class Solution {
public:
    int movingCount(int threshold, int rows, int cols) {
        if(rows<=0 || cols<=0 || threshold<0) return 0;
        bool* flag = new bool[rows*cols];
        memset(flag,false,rows*cols);
        return helper(threshold,rows,cols,0,0,flag);
    }
    int helper(int threshold, int rows, int cols,int i, int j, bool* flag) {
        int index = i*cols+j;
        if(i<0||i>=rows||j<0||j>=cols||flag[index]||count(i)+count(j)>threshold) return 0;
        flag[index] = true;
        return helper(threshold,rows,cols,i-1,j,flag)+
               helper(threshold,rows,cols,i+1,j,flag)+
               helper(threshold,rows,cols,i,j-1,flag)+
               helper(threshold,rows,cols,i,j+1,flag)+1;
    }
    int count(int n) {
        int res = 0;
        while(n!=0){
            res += n%10;
            n /= 10;
        }
        return res;
    }
};

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 騰訊公司c++面試小結(jié)

    這篇文章主要介紹了騰訊公司c++面試小結(jié),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2020-03-02
  • C++ 面試題目(整理自??途W(wǎng))

    這篇文章主要介紹了 C++ 面試題目(整理自??途W(wǎng)),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2020-02-13
  • 華為校招 C++崗面試經(jīng)歷總結(jié)【筆試+一面+二面+Offer】

    這篇文章主要介紹了華為校招 C++崗面試經(jīng)歷,總結(jié)分析了華為校招C++崗位的筆試題,以及一面、二面到最終拿到Offer的經(jīng)歷與相關(guān)經(jīng)驗(yàn)感想,需要的朋友可以參考下
    2019-11-28
  • C++面試常見算法題與參考答案總結(jié)

    這篇文章主要介紹了C++面試常見算法題與參考答案,總結(jié)分析了C++面試中遇到的常見算法題與相應(yīng)的參考答案,需要的朋友可以參考下
    2019-11-20
  • C++必備面試題與參考答案經(jīng)典總結(jié)

    這篇文章主要介紹了C++必備面試題與參考答案,結(jié)合大量經(jīng)典實(shí)例總結(jié)分析了C++面試過程中經(jīng)常遇到的各種概念、原理、算法相關(guān)問題及參考答案,需要的朋友可以參考下
    2019-10-31
  • C/C++經(jīng)典面試題(附答案)

    這篇文章主要介紹了C/C++經(jīng)典面試題(附答案),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-10-23
  • C/C++求職者必備的20道面試題與參考答案解析

    這篇文章主要介紹了C/C++求職者必備的20道面試題與參考答案,總結(jié)分析了C/C++相關(guān)的常見概念、原理、知識(shí)點(diǎn)與注意事項(xiàng),需要的朋友可以參考下
    2019-10-10
  • 騰訊的外包c(diǎn)++面試經(jīng)歷總結(jié)

    這篇文章主要介紹了騰訊的外包c(diǎn)++面試經(jīng)歷,總結(jié)記錄了一次騰訊C++面試的經(jīng)歷,包括面試的流程、面試題目與相應(yīng)的參考答案,需要的朋友可以參考下
    2019-09-29
  • 阿里面試必會(huì)的20道C++面試題與參考答案解析

    這篇文章主要介紹了阿里面試必會(huì)的20道C++面試題與參考答案,涉及C++指針、面向?qū)ο?、函?shù)等相關(guān)特性與使用技巧,需要的朋友可以參考下
    2019-09-26
  • 經(jīng)典C++筆試面試題目與參考答案100例

    這篇文章主要介紹了經(jīng)典C++筆試題目與參考答案,總結(jié)分析了C++常見的各種面試題目,包含C++常見知識(shí)點(diǎn)、技術(shù)難點(diǎn)、算法等,需要的朋友可以參考下
    2019-09-10

最新評(píng)論