zoukankan      html  css  js  c++  java
  • 剑指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]==''){                    
                            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循环,缩减行和列的数值,在逐渐缩小的块状区域寻找

  • 相关阅读:
    JavaScript-4.5 事件大全,事件监听---ShinePans
    SparseArray具体解释,我说SparseArray,你说要!
    Spark Core源代码分析: RDD基础
    我的 Android 开发实战经验总结
    物联网的一种參考架构
    【LeetCode】 Rotate List 循环链表
    放苹果(整数划分变形题 水)poj1664
    ps白平衡
    jfinal对象封装Record原理
    ps通道混合器
  • 原文地址:https://www.cnblogs.com/jason1990/p/4733206.html
Copyright © 2011-2022 走看看