2020/12/07---剑指offer打卡(1-20)

本文解析了如何根据二叉树的前序遍历和中序遍历重建树结构,以及如何计算整数的二进制中1个数。涉及到了递归、链表操作和二叉搜索树的转换。

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

[1,2,3,4,5,6,7],[3,2,4,1,6,5,7]

输出:

{1,2,5,3,4,6,7}

解题思路:

/**
 * 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* rebuild(vector<int>pre,int pre_left,int pre_right,vector<int>vin,int vin_left,int vin_right){
        if(pre_left>pre_right||vin_left>vin_right) return NULL;
        TreeNode *root=new TreeNode(pre[pre_left]);
        for(int i=vin_left;i<=vin_right;i++){
            if(vin[i]==root->val){
            //pre_left+i-vin_left注意理解
                root->left=rebuild(pre,pre_left+1,pre_left+i-vin_left,vin,vin_left,i);
                root->right=rebuild(pre,pre_left+i-vin_left+1,pre_right,vin,i+1,vin_right);
                break;
            }
        }
        return root;
    }
    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
        return rebuild(pre,0,pre.size()-1,vin,0,vin.size()-1);
    }
};

题目描述:

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

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

题目描述

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

class Solution {
public:
    void reOrderArray(vector<int> &array) {
        /*int n=array.size();
        int arr[n];
        int j=0;
        memset(arr,0,sizeof(arr));
        for(int i=0;i<n;i++){
           arr[i]=array[i];
        }
        for(int i=0;i<n;i++){
            if(arr[i]%2==1){
                array[j++]=arr[i];
            }
        }
        for(int i=0;i<n;i++){
            if(arr[i]%2==0){
                array[j++]=arr[i];
            }
        }*/
        int i=0;
        for(int j=0;j<array.size();++j){
            if(array[j]&1){
                int tmp=array[j];
                for(int k=j-1;k>=i;--k){
                    array[k+1]=array[k];
                }
                array[i++]=tmp;
            }
        }
    }
};

题目描述

输入一个链表,输出该链表中倒数第k个结点。

解题思路:

利用快慢指针,让快指针先行K步,然后快慢指针在一起走,当快指针走到空指针时,慢指针对应的即为倒数第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||k<=0) return nullptr;
        int n=0;
        ListNode *cur=pListHead;
        while(cur){
            cur=cur->next;
            n++;
        }
        if(n<k) return nullptr;
        n-=k;
        while(n--){
            pListHead=pListHead->next;
        }
        return pListHead;*/
        if(!pListHead||k<0) return nullptr;
        auto slow=pListHead,fast=pListHead;
        
        while(k--){
            if(fast){
                fast=fast->next;
            }else{
                return nullptr; //如果单链表长度 < K,直接返回
            }
        }
        while(fast){
            slow=slow->next;
            fast=fast->next;
        }
        return slow;
    }
};

题目描述
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)

//树的先序遍历
void preOrder(TreeNode *r) {
    if (!r) return;
    // process r
    preOrder(r->left);
    preOrder(r->right);
}
/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    bool dfs(TreeNode *r1,TreeNode *r2){
        if(!r2) return true;
        if(!r1) return false;
        return r1->val==r2->val&&dfs(r1->left,r2->left)&&dfs(r1->right,r2->right);
    }
    
    bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
    { 
        if(!pRoot1||!pRoot2) return false;
        return dfs(pRoot1,pRoot2)||HasSubtree(pRoot1->left, pRoot2)||HasSubtree(pRoot1->right, pRoot2);
        
    }
};

题目描述
操作给定的二叉树,将其变换为源二叉树的镜像。
在这里插入图片描述

/*
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==nullptr) return ;
        if(pRoot->left==nullptr&&pRoot->right==nullptr) return ;
        
        TreeNode *ptemp=pRoot->left;
        pRoot->left=pRoot->right;
        pRoot->right=ptemp;
        
        if(pRoot->left){
            Mirror(pRoot->left);
        }
        if(pRoot->right){
            Mirror(pRoot->right);
        }*/
        //层序遍历
        if(pRoot==nullptr) return ;
        queue<TreeNode*>pq;
        pq.push(pRoot);
        while(!pq.empty()){
            int sz=pq.size();
            while(sz--){
                TreeNode *node=pq.front();
                pq.pop();
                
                if(node->left) pq.push(node->left);
                if(node->right) pq.push(node->right);
                
                TreeNode *cur=node->left;
                node->left=node->right;
                node->right=cur;
            }
        }

    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值