剑指offer 编程题

1.二维数组的查找

根据大小行列查找

class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
        int n = array.size(),m = array[0].size();
        int i = n-1,j = 0;
        while(i >= 0 && j < m){
            if(array[i][j] > target)
                i--;
            else if(array[i][j] < target)
                j++;
            else
                return true;
        }
        return false;
    }
};

2.替换空格

计算长度替换

class Solution {
public:
    void replaceSpace(char *str,int length) {
        if(str == NULL || length == 0)
            return;
        int len = 0;
        for(int i = 0;str[i] != '\0';i++)
            if(str[i] == ' ')
                len++;
        len = length + len*2;
        for(;length >= 0 && len > length;length--){
            if(str[length] == ' '){
                str[len] = '0';str[--len] = '2';str[--len] = '%';
            }
            else
                str[len] = str[length];
            --len;
        }
    }
};

3.从尾到头打印链表

遍历

/**
*  struct ListNode {
*        int val;
*        struct ListNode *next;
*        ListNode(int x) :
*              val(x), next(NULL) {
*        }
*  };
*/
class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
        vector<int> v;
        while(head != NULL){
            v.insert(v.begin(),head->val);
            head = head->next;
        }
        return v;
    }
};

4.重建二叉树

每颗子树的根结点肯定是先序遍历的第一个结点,根据先序遍历和中序遍历得到子树的遍历结果,利用递归思想不断的处理左右子树

/**
 * 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> in) {
        if(in.size() == 0)
            return NULL;
        TreeNode* head = new TreeNode(pre[0]);
        vector<int> l_pre,l_in,r_pre,r_in;
        int pos = 0;
        for(int i = 0;i < in.size();i++)
            if(in[i] == pre[0]){
                pos = i;
                break;
            }

        for(int i = 0;i < pos;i++){
            l_pre.push_back(pre[i+1]);
            l_in.push_back(in[i]);
        }
        for(int i = pos+1;i < in.size();i++){
            r_pre.push_back(pre[i]);
            r_in.push_back(in[i]);
        }
        head->left = reConstructBinaryTree(l_pre,l_in);
        head->right = reConstructBinaryTree(r_pre,r_in);
        return head;
    }
};

5.用两个栈来实现队列

用栈1来存储,出队列的时候用栈2辅助

class Solution
{
public:
    void push(int node) {
        stack1.push(node);
    }

    int pop() {
        while(!stack1.empty()){
            stack2.push(stack1.top());
            stack1.pop();
        }
        int t = stack2.top();
        stack2.pop();
        while(!stack2.empty()){
            stack1.push(stack2.top());
            stack2.pop();
        }
        return t;
    }

private:
    stack<int> stack1;
    stack<int> stack2;
};

6.旋转数组的最小数字

根据其单调性

class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray) {
        if(rotateArray.size() == 0)
            return 0;

        int pos = 0;
        for(int i = 0;i < rotateArray.size();i++){
            if(rotateArray[i] < rotateArray[pos])
                return rotateArray[i];
            pos = i;
        }
        return pos+1 < rotateArray.size() ? rotateArray[pos+1] : rotateArray[pos];
    }
};

7.斐波那契数列

class Solution {
public:
    int f[40] = {0,1};
    int Fibonacci(int n) {
        for(int i = 2;i <= n;i++)
            f[i] = f[i-1] + f[i-2];
        return f[n];
    }
};

8.跳台阶

class Solution {
public:
    int f[40] = {1,1};
    int jumpFloor(int n) {
        for(int i = 2;i <= n;i++)
            f[i] = f[i-1] + f[i-2];
        return f[n];
    }
};

9.变态跳台阶

递推发现二倍规律

class Solution {
public:
    int jumpFloorII(int n) {
        if(n == 0 || n == 1) return 1;
        int sum = 1;
        while(--n)
            sum <<= 1;
        return sum;
    }
};

10.矩阵覆盖

int a[100005]={0,1,2};
class Solution {
public:
    int rectCover(int number) {
        for(int i = 3;i <= number;i++)
            a[i] = a[i-1] + a[i-2];
        return a[number];
    }
};

11.二进制中1的个数

class Solution {
public:
     int  NumberOf1(int n) {
         int sum = 0;
         while(n){
             sum++;
             n = n&(n-1);
         }
         return sum;
     }
};

12.数值的整数次方

class Solution {
public:
    double Power(double base, int exponent) {
        double ans = 1.0;
        int b = abs(exponent);
        while(b > 0){
            if(b&1)
                ans = ans*base;
            base = base*base;
            b >>= 1;
        }
        if(exponent < 0)
            return 1.0/ans;
        return ans;
    }
};

13.调整数组顺序使奇数位于偶数前面

先奇后偶

class Solution {
public:
    void reOrderArray(vector<int> &array) {
        int len = array.size();
        vector<int> d;
        for(int i = 0;i < len;i++)
            if(array[i]&1)
                d.push_back(array[i]);
        for(int i = 0;i < len;i++)
            if(array[i]%2 == 0)
                d.push_back(array[i]);
        array = d;
    }
};

14.链表中倒数第k个结点

两个指针,p1比p2早走k个结点,p1=null,p2恰好为倒数第k个

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};*/
class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        if(pListHead == NULL)
            return NULL;
        ListNode *pFirst = pListHead;
        for(int i = 0;i < k;i++){
            if(pFirst == NULL)
                return NULL;
            pFirst = pFirst->next;
        }

        ListNode *pResult = pListHead;
        while(pFirst != NULL){
            pFirst = pFirst->next;
            pResult = pResult->next;
        }
        return pResult;
    }
};

15.反转链表

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};*/
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if(pHead == NULL)
            return NULL;
        ListNode *pre = NULL,*cur = pHead,*nxt = NULL;
        while(cur != NULL){
            nxt = cur->next;
            cur->next = pre;
            pre = cur;
            cur = nxt;
        }
        return pre;
    }
};

16.合并两个排序的链表

还是递归更好写

递归:

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};*/
class Solution {
public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
    {
        if(pHead1 == NULL)
            return pHead2;
        if(pHead2 == NULL)
            return pHead1;


        ListNode *p = NULL;
        if(pHead1->val <= pHead2->val)
            p = pHead1,p->next = Merge(pHead1->next,pHead2);
        else
            p = pHead2,p->next = Merge(pHead1,pHead2->next);

        return p;
    }
};

非递归:

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};*/
class Solution {
public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
    {
        if(pHead1 == NULL)
            return pHead2;
        if(pHead2 == NULL)
            return pHead1;

        ListNode *p1 = pHead1,*p2 = pHead2;
        ListNode *head = new ListNode(-1);
        ListNode *p = NULL;
        if(p1->val <= p2->val)
            head = p = p1,p1 = p1->next;
        else
            head = p = p2,p2 = p2->next;

        while(p1 != NULL && p2 != NULL){
            if(p1->val <= p2->val)
                p->next = p1,p = p->next,p1 = p1->next;
            else
                p->next = p2,p = p->next,p2 = p2->next;
        }
        if(p1 == NULL)
            p->next = p2;
        else
            p->next = p1;
        return head;
    }
};

17.树的子结构

遍历A树的每个结点,判断从这个节点开始是否匹配B

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};*/
class Solution {
public:
    bool isSubtree(TreeNode* p1,TreeNode* p2)
    {
        if(p1 == NULL && p2 != NULL)//A
            return false;
        if(p2 == NULL)//B匹配完毕
            return true;
        if(p1->val == p2->val)//继续匹配
            return isSubtree(p1->left,p2->left) && isSubtree(p1->right,p2->right);
        else
            return false;
    }
    bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
    {
        if(pRoot1 == NULL || pRoot2 == NULL)
            return false;
        return isSubtree(pRoot1,pRoot2) || HasSubtree(pRoot1->left,pRoot2) || HasSubtree(pRoot1->right,pRoot2);
    }
};

18.二叉树的镜像

/*
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 == NULL)
            return;
        TreeNode *temp = pRoot->left;
        pRoot->left = pRoot->right;
        pRoot->right = temp;
        Mirror(pRoot->left);
        Mirror(pRoot->right);
    }
};

19.顺时针打印矩阵

打四个标记,注意避免重复打印

class Solution {
public:
    vector<int> printMatrix(vector<vector<int> > matrix) {
        vector<int> v;
        int m = matrix.size(),n = matrix[0].size();
        int left = 0,right = n-1,up = 0,down = m-1;
        while(left <= right && up <= down){
            for(int i = left;i <= right;i++)
                v.push_back(matrix[up][i]);
            for(int i = up+1;i <= down;i++)
                v.push_back(matrix[i][right]);
            if(up < down)
            for(int i = right-1;i >= left;i--)
                v.push_back(matrix[down][i]);
            if(left < right)
            for(int i = down-1;i > up;i--)
                v.push_back(matrix[i][left]);
            left++;
            right--;
            up++;
            down--;
        }
        return v;
    }
};

20.包含min函数的栈

多维护一个栈,保存当前栈内最小值

class Solution {
public:
    stack<int> s,minS;
    void push(int value) {
        s.push(value);
        if(minS.empty())
            minS.push(value);
        else{
            if(minS.top() > value)
                minS.push(value);
            else
                minS.push(minS.top());
        }
    }
    void pop() {
        if(!s.empty()){
            s.pop();
            minS.pop();
        }
    }
    int top() {
        if(!s.empty())
            return s.top();
        return 0;
    }
    int min() {
        if(!minS.empty())
            return minS.top();
        return 0;
    }
};

21.栈的压入、弹出序列

维护一个栈,不断将压入序列ai存入,如果和弹出序列bj相等,就pop(a[i]),j++,判断是否全部符合

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

22.从上往下打印二叉树

队列层次遍历

/*
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) {
        queue<TreeNode*> q;
        if(root != NULL)
            q.push(root);
        vector<int> v;
        while(!q.empty()){
            TreeNode* f = q.front();
            q.pop();
            v.push_back(f->val);
            if(f->left != NULL)
                q.push(f->left);
            if(f->right != NULL)
                q.push(f->right);
        }
        return v;
    }
};

23.二叉搜索树的后序遍历序列

递归:
根据二叉搜索树的特性,不断对左右子树和根比较

class Solution {
public:
    bool VerifySquenceOfBST(vector<int> sequence) {
        if(sequence.size() == 0)
            return false;
        int len = sequence.size();
        return judge(0,len-1,sequence);
    }
    bool judge(int l,int r,vector<int> a){
        if(l >= r)
            return true;
        int i = r-1;
        while(i >= l && a[i] > a[r])
            i--;
        for(int j = i;j >= l;j--)
            if(a[j] > a[r])
                return false;
        return judge(l,i,a) && judge(i+1,r-1,a);
    }
};

比较巧妙地方式,看和根比较完是否包括了所有子结点
非递归:

class Solution {
public:
    bool VerifySquenceOfBST(vector<int> sequence) {
        if(sequence.size() == 0)
            return false;
        int len = sequence.size();
        while(--len){
            int i = 0;
            while(sequence[i++] < sequence[len]);
            while(sequence[i++] > sequence[len]);
            if(i < len)
                return false;
        }
        return true;
    }
};

24.二叉搜索树的后序遍历序列

直接搜索

/*
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> > v;
    vector<int> vec;
    vector<vector<int> > FindPath(TreeNode* root,int expectNumber) {
        if(root == NULL)
            return v;
        vec.push_back(root->val);
        if(expectNumber - root->val == 0 && root->left == NULL && root->right == NULL)
            v.push_back(vec);
        FindPath(root->left,expectNumber-root->val);
        FindPath(root->right,expectNumber-root->val);
        if(vec.size() != 0)
            vec.pop_back();
        return v;
    }
};

25.复杂链表的复制

看懂这个图就会了,来源
这里写图片描述

/*
struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};
*/
class Solution {
public:
    RandomListNode* Clone(RandomListNode* pHead)
    {
        if(pHead == NULL)
            return NULL;
        //复制结点并且插入
        RandomListNode *cur = pHead;
        while(cur){
            RandomListNode *newnode = new RandomListNode(cur->label);
            newnode->next = cur->next;
            cur->next = newnode;
            cur = newnode->next;
        }
        //遍历链表,连接新表的random
        cur = pHead;
        while(cur){
            RandomListNode *newnode = cur->next;
            if(cur->random)//原结点有random
                newnode->random = cur->random->next;
            cur = newnode->next;
        }
        //拆链表得到新表
        RandomListNode *pnewHead = pHead->next;
        cur = pHead;
        while(cur->next){
            RandomListNode *temp = cur->next;
            cur->next = cur->next->next;
            cur = temp;
        }
        return pnewHead;
    }
};

用map的区别不大,可以参考here

26.二叉搜索树与双向链表

由于是排序的双向链表,所以可以用中序遍历的方式遍历二叉搜索树,然后左指针指向下一个节点

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};*/
class Solution {
public:
    TreeNode* Convert(TreeNode* pRootOfTree)
    {
        if(pRootOfTree == NULL)
            return NULL;
        TreeNode *pre = NULL;
        inorder(pRootOfTree,pre);
        TreeNode *res = pRootOfTree;
        while(res->left)
            res = res->left;
        return res;
    }
    void inorder(TreeNode* root,TreeNode*& pre)
    {
        if(root == NULL)
            return;
        inorder(root->left,pre);
        root->left = pre;
        if(pre)
            pre->right = root;
        pre = root;
        inorder(root->right,pre);
    }
};

27.字符串的排列

枚举所有的情况

class Solution {
public:
    vector<string> Permutation(string str) {
        vector<string> v;
        if(str == "")
            return v;
        solve(str,0,v);
        sort(v.begin(),v.end());
        return v;
    }
    void solve(string str,int pos,vector<string> &v){
        if(pos == str.length()){
            v.push_back(str);
            return;
        }
        for(int i = pos;str[i] != '\0';i++){
            if(i != pos && str[pos] == str[i])
                continue;
            swap(str[pos],str[i]);
            solve(str,pos+1,v);
            swap(str[pos],str[i]);
        }
    }
};

28.数组中出现次数超过一半的数字

哈希

class Solution {
public:
    int MoreThanHalfNum_Solution(vector<int> numbers) {
        unordered_map<int,int> mp;
        int n = numbers.size()/2;
        for(int i = 0;i < numbers.size();i++){
            mp[numbers[i]]++;
            if(mp[numbers[i]] > n)
                return numbers[i];
        }
        return 0;
    }
};

巧妙的解法,如果数字x在数组中出现次数超过一半,那么去掉两个不同的数字,数字x在数组中出现次数仍然超过一半

class Solution {
public:
    int MoreThanHalfNum_Solution(vector<int> numbers) {
        int count = 0,num = 0;
        for(int i = 0;i < numbers.size();i++){
            if(count == 0)
                num = numbers[i],count = 1;
            else{
                if(num == numbers[i])
                    count++;
                else
                    count--;
            }
        }
        count = 0;
        for(int i = 0;i < numbers.size();i++)
            if(numbers[i] == num)
                count++;
        if(count > numbers.size()/2)
            return num;
        else
            return 0;
    }
};

猜你喜欢

转载自blog.csdn.net/huatian5/article/details/79760358