剑指offer习题集1

1.打印二叉树

程序很简单,但是其中犯了一个小错误,死活找不到,写代码要注意啊

这里左右子树,要注意是node->left,结果写成root->left

vector<int> PrintFromTopToBottom(TreeNode *root) {

    vector<int> res;
    if (NULL == root)
        return res;

    TreeNode* node;
    deque<TreeNode*> tmp;
    tmp.push_back(root);

    while (tmp.size()) {

        node = tmp.front();
        res.push_back(node->val);
        tmp.pop_front();

        if (node->left)
            tmp.push_back(node->left);
        if (node->right)
            tmp.push_back(node->right);
    }
    return res;
}
View Code

 

2.求1+2+...+n

class A{
    public: 
    A(){     
        ++n;sum+=n; 
    }  
    static int getsum(){  
        return sum;
    }
    static void reset(){
        n=0;sum=0;
    }
    ~A(){}
         
private:        
    static int n; 
    static int sum;
};
     
int A::n=0;
int A::sum=0;
 
class Solution {
public:
     
    int Sum_Solution(int n) {
         
        A::reset(); //必不可少,测试集会重复运行
         
        A* tmp=new A[n];
        delete[] tmp;
         
        return A::getsum();   
    }
};
View Code

 

3.二叉树镜像

class Solution {
public:
    void Mirror(TreeNode *pRoot) {
        
        if(NULL==pRoot||(NULL==pRoot->left&&NULL==pRoot->right))
            return;
        
        mirrorset(pRoot);
    }
    
    void mirrorset(TreeNode* root){
        
        if(NULL==root||(NULL==root->left&&NULL==root->right))
            return;
        
        TreeNode *tmp=root->left;
        root->left=root->right;
        root->right=tmp;
        
        if(root->left)
            mirrorset(root->left);
        if(root->right)
            mirrorset(root->right);
    }
};
View Code

 

4.合并两个排序的链表

剑指offer书上用的是递归,感觉不必那么麻烦,用一个循环就可以解决。

ListNode1* Merge(ListNode1* pHead1, ListNode1* pHead2)
{
    //避免空指针
    if (NULL == pHead1 || NULL == pHead2)
        return NULL == pHead1 ? pHead2 : pHead1;

    //选取两个链表中的最小值作为链表头
    bool sign[2] = { false };
    ListNode1 *p1 = pHead1, *p2 = pHead2, *p3, *res;
    if (p1->val < p2->val) {
        res = p1;p3 = res;p1 = p1->next;sign[0] = true;
    }
    else {
        res = p2;p3 = res;p2 = p2->next;sign[1] = true;
    }

    while (p1&&p2) {
        if (p1->val < p2->val) {
            if (sign[0]) {
                p1 = p1->next;
                p3 = p3->next;
            }
            else {
                p3->next = p1;
                p1 = p1->next;
                p3 = p3->next;
            }
            sign[0] = true;sign[1] = false;
        }
        else {
            if (sign[1]) {
                p2 = p2->next;
                p3 = p3->next;
            }
            else {
                p3->next = p2;
                p2 = p2->next;
                p3 = p3->next;
            }
            sign[0] = false;sign[1] = true;
        }
    }

    if (p1) {
        p3->next = p1;
    }
    else if (p2) {
        p3->next = p2;
    }

    return res;
}
View Code

 

5.复杂链表的复制

/*
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(NULL==pHead)
            return NULL;
        
        //复制链表节点,并嵌入原链表
        RandomListNode *p1=pHead,*p2=pHead,*res;
        while(p1){
            RandomListNode *temp=new RandomListNode(p1->label);
            temp->next=p1->next;
            p1->next=temp;
            
            if(NULL==temp->next)
                break;
            else p1=temp->next;
        }
        
        //复制随机指针
        p1=pHead;
        while(p1){
            p2=p1->random;
            p1=p1->next;
            p1->random=p2;
            p1=p1->next;
        }
        
        //拆分链表
        p1=pHead;p2=p1->next;res=p2;
        while(p1&&NULL!=p2->next){
            p1->next=p2->next;
            p1=p1->next;
            p2->next=p1->next;
            p2=p2->next;
        }
        p1->next=NULL;
        
        return res;
    }
};
View Code

 

6.顺时针打印矩阵

void print(const vector<vector<int>>& matrix, const int& len1, const int& len2, const int& n, vector<int>& res) {

    int i, endx = len1 - 1 - n, endy = len2 - 1 - n;

    //从左至右存储
    for (i = n;i <= endy;++i) {
        res.push_back(matrix[n][i]);
    }

    //从上至下存储
    if (n < endx) {
        for (i = n + 1;i <= endx;++i)
            res.push_back(matrix[i][endy]);
    }

    //从右至左打印
    if (n < endx&&n < endy) {
        for (i = endy - 1;i >= n;--i)
            res.push_back(matrix[endx][i]);
    }

    //从下至上打印
    if (n < endx - 1 && n < endy) {
        for (i = endx - 1;i >= n + 1;--i)
            res.push_back(matrix[i][n]);
    }
}

vector<int> printMatrix(vector<vector<int>>& matrix) {

    vector<int> res;
    int len1 = matrix.size(), len2, n = 0;

    if (0 == len1) {
        return res;
    }
    else if (1 == len1) {
        return matrix[0];
    }
    else {
        len2 = matrix[0].size();
    }

    while (2 * n < len1 && 2 * n < len2) {
        print(matrix, len1, len2, n, res);
        ++n;
    }

    return res;
}
View Code

在VS上写程序真的是很简单,各种智能提示,在其他IDE上写程序,就得时刻注意。。。结果还是不容易找到错误

 

7.不能用加减乘除做加法

class Solution {
public:
    int Add(int num1, int num2)
    {
        int sum1,sum2;
        
        do{
            sum1=num1^num2;
            sum2=(num1&num2)<<1;
            
            num1=sum1;
            num2=sum2;
        }while(num2!=0);
            
        return sum1;
    }
};
View Code

日了够了,就不能一遍通过,左移右移竟然能犯错误。

 

8.翻转字符串

注意j值的变化,机试时不带调试,实在是无语啊

class Solution {
public:
    string ReverseSentence(string str) {
        
        int len=str.length();
        if(len<=1) return str;
        
        int i,j,left,right;
        
        //首先翻转整条语句
        reverse(str,0,len-1);
        
        //逐个翻转单词
        left=0;right=0;
        for(i=0;i<len;i++){            
            if(str[i]!=' '){
                left=i;
                for(j=i+1;j<=len;j++){                
                    if(str[j]==' '||str[j]=='\0'){                    
                        right=j-1;       
                        break;              
                    }
                }
                reverse(str,left,right);
                i=j; //从当前为空格字符运行
            }                        
        }      
        
        return str;
    }
    
private:   
    void reverse(string& str,int left,int right){
        
        if(left<0||right<0||(right-left)<=0)
            return;
        
        char temp;
        while(left<right){
            
            temp=str[left];
            str[left]=str[right];
            str[right]=temp;
            
            ++left;
            --right;
        }
    }
};
View Code

 

9.数组在排序数组中出现的次数

class Solution {
public:
    int GetNumberOfK(vector<int> data ,int k) {
        
        bool sign=false;
        int len=data.size();
        if(0==len) return 0;
        int left=0,right=len-1,mid; 
        
        //通过二分查找法先缩小搜索范围
        while(left<=right){ //注意二分查找法此处是等号,否则应对只有一个元素,岂不是呵呵了
            mid=(left+right)>>1;
            if(data[mid]==k){
                sign=true;break;
            }else if(data[mid]<k){
                left=mid+1;
            }else{
                right=mid-1;
            }
        }
        if(!sign) return 0; //确保数组中包含此数据   
        
        return getlastk(data,len,k,mid,right)-getfirstk(data,k,left,mid)+1;
    }
    
    int getfirstk(vector<int>& data,const int& k,int left,int right){
        
        int mid=(left+right)>>1;
        int midval=data[mid];
        
        if(midval==k){
            if((mid>0&&data[mid-1]!=k)||mid==0){
                return mid;
            }else
                right=mid-1;
        }else if(midval<k){
            left=mid+1;
        }else{
            right=mid-1;
        }
        
        return getfirstk(data,k,left,right);
    }
    
    int getlastk(vector<int>& data,const int& len,const int& k,int left,int right){
        
        int mid=(left+right)>>1;
        int midval=data[mid];
        
        if(midval==k){
            if((mid<len-1&&data[mid+1]!=k)||mid==len-1){
                return mid;
            }else{
                left=mid+1;
            }
        }else if(midval<k){
            left=mid+1;
        }else{
            right=mid-1;
        }
        
        return getlastk(data,len,k,left,right);
    }
    
};
View Code

 

10.二叉树的下一节点(看着答案做的,还需重新做)

class Solution {
public:
    TreeLinkNode* GetNext(TreeLinkNode* pNode)
    {
        if(NULL==pNode)
            return NULL;
        
        TreeLinkNode* pnext=NULL;
        
        if(pNode->right!=NULL){
            
            TreeLinkNode *right=pNode->right;
            while(right->left){
                right=right->left;
            }
            pnext=right;
        }else if(pNode->next){
            TreeLinkNode *curr=pNode;
            TreeLinkNode *parent=curr->next;
            while(parent!=NULL&&curr==parent->right){
                curr=parent;
                parent=parent->next;
            }
            pnext=parent;
        }else{
            //父节点无右子树
        }
        
        return pnext;
    }
};
View Code

 

11.按行打印二叉树

运行一直出错,还是找不到错误,后续才发现少了return res;

在线测试也不会提醒这个错误的,简直对自己无语了啊。

vector<vector<int> > Print_test(BinaryTreeNode* pRoot) {

    vector<vector<int>> res;
    if (NULL == pRoot)
        return res;

    int print = 1, nextlevel = 0;
    BinaryTreeNode* temp;
    std::queue<BinaryTreeNode*> nodes;
    std::vector<int> tval;
    nodes.push(pRoot);

    while (nodes.size()) {

        temp = nodes.front();
        tval.push_back(temp->m_nValue);
        if (temp->m_pLeft) {
            nodes.push(temp->m_pLeft); ++nextlevel;
        }
        if (temp->m_pRight) {
            nodes.push(temp->m_pRight); ++nextlevel;
        }
        nodes.pop();

        --print;
        if (!print) {

            //通过队列记录数值,并在读取完一层之后进行清空
            vector<int> val;
            for (int i = 0;i<tval.size();++i) {
                val.push_back(tval[i]);
            }
            tval.clear();
            res.push_back(val);

            print = nextlevel;
            nextlevel = 0;
        }
    }

    return res;
}
View Code

以后一定先写return res;

还有就是声明指针的时候一定记住初始化为NULL。

 

12.找最小的k个数

class Solution {
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
         
        int len=input.size();
        if(len<k){
            vector<int> res;return res;
        }else if(len==k){
            return input;
        }
         
        QuickSort(input);
        vector<int> data;
        for(int i=0;i<k;++i){
            data.push_back(input[i]);
        }
        return data;
    }
     
    void Qsort(vector<int>& data,int left,int right)
    {  
        if (left < right)
        {      
            //此步保证data[pivot]大于左边的元素小于右边的元素,arry[pivot]被正确安排     
            int pivot = partition(data, left, right);      
            Qsort(data, left, pivot - 1);      
            Qsort(data, pivot + 1, right);   
        }
    }
 
 
    void QuickSort(vector<int>&data)
    {      
        Qsort(data, 0, data.size() - 1);
    }
     
    void swap(int&a, int&b) {
        int t = a;a = b;b = t;
    }
     
    int partition(vector<int>& data,const int& start,const int& end){
         
        int left=start,right=end;
        int pivot=data[left];
         
        while(left<right){
            while(left<right&&data[right]>=pivot)
                --right;
            swap(data[left],data[right]);
             
            while(left<right&&data[left]<=pivot)
                ++left;
            swap(data[left],data[right]);
        } 
        return left;
    }
};
View Code

快排必须将第一个数值作为基准,当然,你要想选取中间数值,可以将中间数值与第一个数值进行交换。

 

13.反转链表

class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
         
        if(NULL==pHead||NULL==pHead->next)
            return pHead;
         
        ListNode* reversehead=NULL;
        ListNode* prenode=NULL;
        ListNode* currnode=pHead;
        ListNode* nextnode=NULL;
         
        while(currnode){
             
            nextnode=currnode->next;
            if(NULL==nextnode){
                reversehead=currnode;
            }
             
            currnode->next=prenode;
             
            prenode=currnode;
            currnode=nextnode;
        }
         
        return reversehead;
    }
};
View Code

 

14.调整数组顺序,奇数位于偶数之前

class Solution {
public:
    void swap(int& a,int& b){
        int t=a;a=b;b=t;
    }
    
    void reOrderArray(vector<int> &array) {
        
        int len=array.size();
        if(0==len||1==len)
            return;
        
        int left=0,right=len-1;
        while(left<right){
            
            while(left<right&&array[left]%2==1)
                ++left;
            
            while(left<right&&array[right]%2==0)
                --right;
            
            if(left<right)
                swap(array[left],array[right]);
        }
    }
};
View Code

不过此方法会改变奇数与奇数,偶数与偶数之间的相对关系。

 

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

class Solution {
public:
    int MoreThanHalfNum_Solution(vector<int> numbers) {
         
        int len=numbers.size();
        if(0==len)
            return 0;
        else if(1==len) return numbers[0];
        else if(len<=3) return numbers[1];
             
        int index,start=0,end=len-1;
        int mid=len>>1;
        index=partition(numbers,start,end);
        while(index!=mid){
            if(index>mid){
                end=index-1;
                index=partition(numbers,start,end);
            }else{
                start=index+1;
                index=partition(numbers,start,end);
            }
        }
         
        if(judge(numbers,numbers[index],len)){
            return numbers[index];
        }else return 0;
    }
     
private:
    void swap(int& a,int& b){
        int t=a;a=b;b=t;
    }
     
    //此处因为调用函数确保了鲁棒性,故此处不添加相关检验
    int partition(vector<int>& num,const int& start,const int& end){
         
        int left=start,right=end,pivot=num[start];
         
        while(left<right){
             
            while(left<right&&num[right]>=pivot)
                --right;
            swap(num[left],num[right]);
             
            while(left<right&&num[left]<=pivot)
                ++left;
            swap(num[left],num[right]);
        }
        return left;
    }
     
    bool judge(vector<int>& num,const int&k,const int& len){
         
        int i,n=0;
        for(i=0;i<len;i++){
            if(num[i]==k){
                ++n;
            }
        }
         
        return (n>len/2)?true:false;
    }
};
View Code

此题还是犯了错误,一个是没有判断中位数究竟是不是在数组中超过一半,即先天条件满不满足。

另外一个就是数组维数为1的时候,应该返回此数字,因为明显满足条件。。。

 

16.二维数组的寻找

class Solution {
public:
    bool Find(vector<vector<int> > array,int target) {
         
        int i,j,len=array.size();
         
        //鲁棒性检查
        if(0==len) return false;
        for(i=0;i<len;++i){
            if(array[i].size()!=len)
                return false;
        }
        if(array[0][0]>target)
            return false;
        if(array[len-1][len-1]<target)
            return false;
         
        for(j=len-1;j>=0;--j){
             
            //数据不在当前列,跳出循环
            if(target<array[0][j]||target>array[len-1][j])
                continue;
                 
            for(i=0;i<len;++i){
                if(target==array[i][j])
                    return true;
            }
        }
         
        return false;
    }
};
View Code

 起始这个有更为优化的方式,我是通过列去寻找,有设置while循环,缩减行和列的数值,在逐渐缩小的块状区域寻找

posted @ 2015-08-15 21:51  从此寂静无声  阅读(234)  评论(0编辑  收藏  举报