剑指offer刷题记录1

剑指offer是比较经典的面试题目,我决定在牛客网上做一下,把没做好的题记录下来。

1.请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

class Solution {
public:
    void replaceSpace(char *str,int length) {
        if(length<=0||str==NULL) return;
        char* temp=str;
        int lenori=0;int num=0;
        while(*temp!='\0'){
            lenori++;
            if(*temp==' ') num++;
            temp++;
        }
        int lennew=num*2+lenori;
        if(lennew>length) return;
        int indexnew=lennew;
        int indexold=lenori;
        while(indexold>=0){
            if(str[indexold]==' '){
                str[indexnew--]='0';
                str[indexnew--]='2';
                str[indexnew--]='%';
            }
            else {
                str[indexnew--]=str[indexold];
            }
            indexold--;
        }

    }
};

2.输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

/**
 * 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);
    }
    TreeNode* buildtree(vector<int>& pre,vector<int>& vin,int first,int end){
        if(pre.empty()||first>end) return NULL;
        int val=pre.front();
        auto mid=pre.begin();
        pre.erase(mid);
        auto it=vin.begin()+first;
        for(;it!=vin.begin()+end+1;it++){
            if(*it==val) break;
        }        
        TreeNode* root=new TreeNode(val);
        root->left=buildtree(pre,vin,first,it-vin.begin()-1);
        root->right=buildtree(pre,vin,it-vin.begin()+1,end);
        return root;

    }
};

3.输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

虽然这道题我ac了,但是还是值得分享一下,主要是竟然连负数也可以不断地去掉最后一个1,这个算法还是挺牛逼的。

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

     }
};

4.我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

class Solution {
public:
    int rectCover(int number) {
        if(number<3) return number;
        int first=1,second=2,val=0;//斐波那契数列
        for(int i=3;i<=number;i++){
            val=first+second;
            first=second;
            second=val;
        }        
        return val;




    }
};

4.输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
发现这种题还是不怎么会做

class Solution {
public:
    vector<int> printMatrix(vector<vector<int> > matrix) {

        vector<int > res;
        if(matrix.empty()||matrix[0].empty()) return res;
        int m=matrix.size();
        int n=matrix[0].size();
        int c=m>n?(n+1)/2:(m+1)/2;
        int p=m,q=n;
        for(int i=0;i<c;i++,q-=2,p-=2)
        {
            for(int col=i;col<i+q;col++)
                res.push_back(matrix[i][col]);
            for(int row=i+1;row<i+p;row++)
                res.push_back(matrix[row][i+q-1]);
            if(p==1||q==1) break;
            for(int col=i+q-2;col>=i;col--)
                res.push_back(matrix[i+p-1][col]);
            for(int row=i+p-2;row>i;row--)
                res.push_back(matrix[row][i]);
        }
        return res;
    }
};

5.定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。
第二个栈存当前最小值,再次压进去

#include<algorithm>
class Solution {
public:
    void push(int value) {
        minvalue=std::min(value,minvalue);
        stack1.push(value);
        stack2.push(minvalue);
    }
    void pop() {
        stack1.pop();
        stack2.pop();        
    }
    int top() {
        return stack1.top();
    }
    int min() {
        return stack2.top();
    }
private:
    stack<int> stack1;
    stack<int> stack2;
    int minvalue=INT_MAX;
};

6.输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

这道题的陷阱是 一定要把原来的链表恢复原状,不能损坏原来的链表。

/*
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) return pHead;        

        RandomListNode* step=pHead;
        while(step){
            RandomListNode* node=new RandomListNode(step->label);
            RandomListNode* nextnode=step->next;
            step->next=node;
            node->next=nextnode;
            step=nextnode;            
        }

        step=pHead;
        while(step){
            if(step->random)step->next->random=step->random->next;
            else step->next->random=NULL;
            step=step->next->next;

        }

        step=pHead;
        RandomListNode* newhead=new RandomListNode(0);
        RandomListNode* now=newhead;
        while(step){            
            now->next=step->next;
            if(now->next)step->next=now->next->next;//千万注意,一定要把原来的链表恢复原状,不能损坏原来的链表。
            now=now->next;
            step=step->next;
        }

        return newhead->next;




    }
};

7.输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
这道题就是要调,维护一个vector 存最小的k个数,然后按照顺序更新就行。

class Solution {
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        if(k>input.size()) return {};
        vector<int> res(k,0);
        int i=0;
        for(;i<k;i++){
            res[i]=input[i];
        }
        sort(res.begin(),res.end());
        for(;i<input.size();i++){
            int j=0;
            for(;j<k;j++){
                if(input[i]<=res[j])
                    break;
            }
            if(j<k){
                int m=0;
                for(m=k-1;m>j;m--){
                    res[m]=res[m-1];
                }
                res[j]=input[i];
            }
        }
        return res;



    }
};

8.请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。

这道题不难,核心是递归函数的输入时两个,是左右。左的左,右的右。右的左,左的右。

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
    bool isSymmetrical(TreeNode* pRoot)
    {
        if(!pRoot) return true;
        return solve(pRoot->left,pRoot->right);

    }
    bool solve(TreeNode* left,TreeNode* right){
        if((!left)&&(!right)) return true;
        if((left==NULL)||(right==NULL)) return false;
        if(left->val!=right->val) return false;
        return solve(left->left,right->right)&&solve(left->right,right->left);
    }

};

9.在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5

这道题最重要的是处理边界条件,比较消耗时间。经验就是凡是要考虑->next的属性,如->next->next或者->next->val的,都要考虑->next存不存在。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead)
    {
        ListNode* newhead=new ListNode(0);
        ListNode* first=pHead;
        ListNode* now=newhead;
        while(first){
            while(first&&first->next&&first->next->val==first->val){
                int mid=first->val;
                while(first&&mid==first->val)
                    first=first->next;
            }
            now->next=first;
            if(first)first=first->next;
            now=now->next;
        }
        return newhead->next;


    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值