剑指offer36-40

不多说,就是干

数字在排序数组中出现的次数

题目描述:统计一个数字在排序数组中出现的次数。
题目分析:这道题如果用count函数的话会超级简单,但是这样就失去了这道题的意义。

class Solution {
public:
    int GetNumberOfK(vector<int> data ,int k) {
        return count(data.begin(),data.end(),k);
    }
};

既然是排序数组的话,其实也很容易,首先用二分法找到这个数组中的这个数,然后向前向后找,加起来就好了。只要遇到排序数组就二分法就完了。但是垃圾编译器会超空间,这里我就不细说了。

class Solution {
public:
	int weizhi;
	void dian(vector<int>data, int k, int low, int high) {    //利用二分法找到存在的位置
		if (low == high)return;
		int mid = (low + high) / 2;
		if (data[mid] == k) {
			weizhi = mid;
			return;
		}
		if (data[mid] < k) {
			dian(data, k, mid, high);
		}
		else {
			dian(data, k, low, mid);
		}
	}
	int GetNumberOfK(vector<int> data, int k) {            //向前向后找相同数字
		int number = data.size();
		dian(data, k, 0,number-1);
		int prenumber = 0;
		int nextnumber = 0;
		int i = weizhi-1;
		int j = weizhi+1;
		if (i >= 0) {
			while (data[i] == k && i>=0) {
				prenumber++;
				i--;
			}
		}
		if (j < number) {
			while (data[j] == k && j < number) {
				nextnumber++;
				j++;
			}
		}
		return 1 + prenumber + nextnumber;
	}
};

二叉树的深度

题目描述:输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
题目分析:就是找遍历找深度,仅此而已。

class Solution {
public:
	int maxdepth = 0;
	void Treebianli(TreeNode* pRoot, int k) {
		if (pRoot == nullptr) {
			if (k > maxdepth) {
				maxdepth = k;
            }
			return;
		}
		Treebianli(pRoot->left,  k+1);
		Treebianli(pRoot->right, k+1);
	}
	int TreeDepth(TreeNode* pRoot)
	{
		if (pRoot == nullptr)return 0;
		Treebianli(pRoot, 0);
		return maxdepth;
	}
};

平衡二叉树

题目描述:输入一棵二叉树,判断该二叉树是否是平衡二叉树。
题目分析:任何二叉树的题,本质上都是递归求解,否者都会贼难。

 class Solution {
    public:
    bool IsBalanced_Solution(TreeNode* pRoot) {
        if(pRoot == nullptr) {
            return true;
        }
        return abs(maxDepth(pRoot->left) - maxDepth(pRoot->right)) <= 1 &&
            IsBalanced_Solution(pRoot->left) && IsBalanced_Solution(pRoot->left);
    }
      
     int maxDepth(TreeNode* root) {
        if(root == nullptr) {
            return 0;
        }
        return 1 + max(maxDepth(root->left), maxDepth(root->right));
    }
};

数组中只出现一次的数字

题目描述:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
题目分析:当然这个题遍历也是可以的,但是很傻,面试官肯定不会喜欢这个方案,所以必须采用异或的方法。如果一个整形数组中只有一个数字出现了1次,应该用异或是很容易实现的。出现两个的话就先找两个异或结果,再根据这个结果将整个数组分成两部分,然后在对分组结果进行处理,之后分别在两个数组中找到只出现了一次的数。

class Solution {
public:

	int differpoint(int count) {        //找到两个单独数的异或值的最小位不同
		int point = 1;
		while (1) {
			if (count & 1 == 1)break;
			count=count >> 1;
			point=point << 1;
		}
		return point;
	}
 	void FindNumsAppearOnce(vector<int> data, int* num1, int *num2) {
		if (data.size() == 0)return;
		if (data.size() == 1) {	*num1 = data[0]; return; }
		int count=0;
		for (int i = 0; i < data.size(); i++) {
			count = count ^ data[i];                     //找到两个单独数的异或值
		}
		int differ = differpoint(count);
		vector<int>cun1;
		vector<int>cun2;
		for (int i = 0; i < data.size(); i++) {
			if ((data[i] & differ) == differ) {       //分别将数据放在不同的篮子中
				cun1.push_back(data[i]);
			}
			else {    
				cun2.push_back(data[i]);
			}
		}
		int word1 = 0;
		int word2 = 0;
		for (int i = 0; i < cun1.size(); i++) {
			word1 = word1 ^ cun1[i];
		}
		for (int i = 0; i < cun2.size(); i++) {
			word2 = word2 ^ cun2[i];
		}
		*num1 = word1;
		*num2 = word2;
	}
};

和为S的连续正数序列

题目描述:小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
题目分析:最简单的方法就是用两个指针走,判断两个指针之间的数是否符合结果。

class Solution {
public:
    vector<vector<int> > FindContinuousSequence(int sum) {
        vector<vector<int> > res;
        int begin = 1, end = 2;
        int mid = (sum+1)/2;
        int cur = begin+end;
        while(begin<mid && end < sum){   //终止条件,开始值大于等于半值或者中值大于等于sum
            while(cur>sum){              //大于sum
                cur-=begin;
                begin++;
            }
            if(cur == sum){              //等于sum
                vector<int> tmp;
                for(int i = begin;i<=end;i++) tmp.push_back(i);
                res.push_back(tmp);
            }
            end++;                      //小于sum
            cur+=end;
        }
        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值