剑指offer习题集

1.重载赋值运算符函数:(具体见代码)

//普通做法
CMyString& CMyString::operator=(const CMyString& str)
{
    if (this == &str) 
        return *this;

    delete[] m_Pdata;
    m_Pdata = new char[strlen(str.m_Pdata)+1];
    strcpy(m_Pdata,str.m_Pdata);

    return *this;
}

//更加安全的做法,普通做法在new内存不足情况下,已经将原值delete
CMyString& CMyString::operator=(const CMyString& str)
{
    if (this != &str)
    {
        CMyString strTemp(str);

        char* temp = str.m_Pdata;
        //通过strTemp的析构函数delete掉原值
        strTemp.m_Pdata = m_Pdata; 
        m_Pdata = temp; 
    }

    return *this;
}

2.替换字符串中的空白字符

瞎了,做了一遍结果还是出错。。。确实要多练练

class Solution {
public:
    //length为数组容量
    void replaceSpace(char *str,int length) {
        
        if(length<=0||str==NULL) return;
        
        int i=0,n_blank=0,n_str=0,n_strlength=0;
        while(str[i]!=''){
            ++n_str;
           
            if(' '==str[i])
                ++n_blank;
            
            ++i;
        }
        
        n_strlength=n_str+n_blank*2;
        if(n_strlength>length) return;
        
        int n1=n_str,n2=n_strlength;
        while(n1>=0&&n2>n1){
            if(str[n1]==' '){
                str[n2--]='0';
                str[n2--]='2';
                str[n2--]='%';
            }else{
                str[n2--]=str[n1];
            }
            
            --n1;
        }  
    }
};

3.使用两个栈模仿队列

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

    int pop() {
        int temp;
        
        if(stack2.size()<=0){
            while(stack1.size()>0){
                temp=stack1.top();
                stack2.push(temp);
                stack1.pop();
            }
        }
        
        if(stack2.size()<=0) 
            return 0;
        
        temp=stack2.top();
        stack2.pop();
        return temp;
    }

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

4.改进的斐波那契数列

class Solution {
public:
    int Fibonacci(int n) {
        
        if(n<=0) return 0;
        
        if(1==n||2==n) return 1;
        
        long long n1=1,n2=1,n3=0;
        for(int i=2;i<n;i++){
            n3=n1+n2;
            n1=n2;
            n2=n3;
        } 
        return n3;
    }
};

5.实数的整数次方

class Solution {
public:
    double Power(double base, int exponent) {
        
        //防止0作为底数
        if(equal(base,0.0)){
            if(0==exponent) return 1.0;
            else return 0.0;
        } 
        
        //针对0次方做的特殊处理
        if(0==exponent) return 1.0;
        else if(1==exponent) return base;
        
        double res;
        bool sign=exponent<0?true:false;
        
        if(sign){
            return 1.0/PowerD(base,-1*exponent);
        }else{
            return PowerD(base,exponent);
        }
    }
    
    bool equal(const double &a,const double &b){
        if(fabs(a-b)<1e-6)
            return true;
        return false;
    }
    
    double PowerD(double base,int exponent){
        
        if(1==exponent) return base;
        else if(0==exponent) return 1.0;
       
        double res=PowerD(base,exponent/2);
        res*=res;
        if(exponent&0x01==1){ //判断是否是奇数次方
            res*=base;
        }
        return res;
    }
};

6.求链表的倒数第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(NULL==pListHead||k==0) return NULL;
        
        int i=k;
        ListNode *t1=pListHead,*t2=pListHead;
        
        while(i!=0&&t1!=NULL){
            --i;
            t1=t1->next;
        }
        
        if(i!=0) return NULL;
        
        while(t1!=NULL){
            t1=t1->next;
            t2=t2->next;
        }
        return t2;
    }
};

7.包含min函数的栈

class Solution {
public:
    void push(int value) {
        
        m_data.push(value);
        
        if(m_min.size()==0){
            m_min.push(value);
        }else{
            if(value<m_min.top())
                m_min.push(value);
            else m_min.push(m_min.top());
        }
    }
    void pop() {
        if(m_data.size()>0){
            m_data.pop();
            m_min.pop();
        }
    }
    int top() {
        if(m_data.size()>0)
            return m_data.top();
    }
    int min() {
        if(m_min.size()>0) 
            return m_min.top();
    }
    
private:
    stack<int> m_data;
    stack<int> m_min;
};

8.给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]。不能使用除法。

vector<int> multiply(const vector<int>& A) {
        
        int i,len=A.size(),temp=1;
        vector<int> res;
        if(len<=1) return res;
        
        res.push_back(1);
        for(i=1;i<len;i++){
            res.push_back(res[i-1]*A[i-1]);
        }
        
        for(i=len-2;i>=0;i--){
            temp*=A[i+1];
            res[i]*=temp;
        }
        
        return res;
    }

此题没怎么注意代码的鲁棒性,后续可以补充。

9.一个链表中包含环,请找出该链表的环的入口结点。

ListNode* EntryNodeOfLoop(ListNode* pHead)
    {
        if(pHead==NULL) return NULL;
         
        //找到环中节点
        ListNode *p1=MeetListNode(pHead),*p2;
        if(p1==NULL) return NULL;
         
        //计算链表中环的节点个数
        int i,n=1;
        p2=p1->next;
        while(p2!=p1){
            ++n;
            p2=p2->next;
        }
         
        //寻找链表中环的入口节点
        p1=pHead;p2=pHead;
        for(i=0;i<n;i++){
            p1=p1->next;
        }
        while(p1!=p2){
            p1=p1->next;
            p2=p2->next;
        }
        return p1;
    }
     
    ListNode* MeetListNode(ListNode* pHead){
         
        ListNode *p1=pHead->next,*p2=pHead;
        if(pHead==NULL||p1==NULL||p1->next==NULL) return NULL;
         
        p1=p1->next;
        while(p1!=p2){
             
            p2=p2->next;
             
            p1=p1->next;
            if(p1->next==NULL){
                return NULL;
            }else{
                p1=p1->next;
            }
        }
        return p1;
    }

这道题有更加快捷优化的做法,后续做更新。这里只是将书本上的思路进行阐述。

10.在一个长度为n的数组里的所有数字都在0到n-1的范围内。

数组中某些数字是重复的,但不知道有几个数字是重复的。

也不知道每个数字重复几次。请找出数组中任意一个重复的数字。

例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或者3。

bool duplicate(int numbers[], int length, int* duplication) {
        
        if(NULL==numbers||length<=1) return NULL;
        
        int i,temp;
        for(i=0;i<length;i++){ //对数据的正确性进行检测
            if(numbers[i]<0||numbers[i]>length-1)
                return NULL;
        }
        
        for(i=0;i<length;i++){
            while(numbers[i]!=i){
                if(numbers[i]==numbers[numbers[i]]){
                    *duplication=numbers[i];
                    return true;
                }
                
                //进行数值交换
                temp=numbers[i];
                numbers[i]=numbers[temp];
                numbers[temp]=temp;
            }  
        }
        
        return false;
    }

这道题还是比较绕,不能熟练掌握。

11.第一个只出现一次的字符

此题其实比较简单,但是要知道ASCII码共有256个。其实不知道也无妨,将hashtable设置较大即可。

期望于一个循环解决问题,是可以的,但是在面试的过程中,最重要的是解决题目,进而进行优化。

class Solution {
public:
    int FirstNotRepeatingChar(string str) {
        
        int len=str.length();
        if(0==len) 
            return -1;
        else if(1==len){
            return 0;
        }
        
        const int size=256;
        unsigned int i,hashtable[size]={0};
        
        for(i=0;i<len;++i){
            ++hashtable[str[i]];
        }
        
        for(i=0;i<len;++i){
            if(1==hashtable[str[i]])
                return i;
        }
        
        return -1;
    }
};

12.数组中只出现一次的数字

此题可以扩展范围,比如字符之类的,总之方法如果不是看书,蛮难想到的

class Solution {
public:
    void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
        
        int len=data.size();
        if(len<2) 
            return;
        else if(2==len&&data[0]!=data[1]){
            *num1=data[0];
            *num2=data[1];
            return;
        }
        
        int i,n=0,temp=data[0],res;
        for(i=1;i<len;i++){
            temp=temp^data[i];
        }
        
        //寻找二进制中初始为1数字
        while(!(temp&0x01)&&(n<8*sizeof(int))){
            ++n;
            temp=temp>>1;
        }
        
        *num1=0;*num2=0;
        for(i=0;i<len;++i){
            
            res=(data[i]>>n)&0x01;
            
            if(res){
                *num1^=data[i];
            }else{
                *num2^=data[i];
            }
        }
        
        return;
    }
};
原文地址:https://www.cnblogs.com/jason1990/p/4694821.html