剑指offer-53

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

解法一:遍历数组到X,开始计数,O(N)

解法二:递归使用二分法遍历计数,直至当前分段上下节点出现目标数字K时开始计数

解法三:二分法先查找数字k,再从k开始,往上往下计数 O(logn)

解法四:找出最左一个k和最右一个K,计数 O(logn)

解法三:
int GetNumberOfK_Kth(const int* data, int length, int k)//find Kth
{
	if (data == nullptr || length <= 0) return 0;
	if (k<data[0] || data[length - 1]<k) return 0;
	int cnt = 0;
	int L = 0, R = length - 1;
	int mid = 0;
	while (L<=R)
	{
		mid = (L + R) >> 1;
		if (data[mid] == k)
		{
			for (int i = mid; i >= L;i--)
			{
				if (data[i] == k)
					cnt++;
				else
					break;
			}

			for (int i = mid + 1; i <= R;i++)
			{
				if (data[i] == k)
					cnt++;
				else
					break;
			}
			break;
		}
		else if (data[mid]>k)
			R = mid - 1;
		else
			L = mid + 1;
	}
	return cnt;
}
解法二:
int GetNumberOfK_binaryCnt(const int* data, int start, int end, int k)//binaryCnt
{
	if (start > end || end < start) return 0;
	int cnt=0;
	int mid = (start + end) >> 1;
	if (data[start]==k)
	{
		for (int i = start; i <= end;i++)
		{
			if (data[i] == k)
				cnt++;
			else
				break;
		}
		return cnt;
	}
	else if (data[end]==k)
	{
		for (int i = end; i >= start; i--)
		{
			if (data[i] == k)
				cnt++;
			else
				break;
		}
		return cnt;
	}
	else
	{
		if (data[mid] < k)
			cnt += GetNumberOfK_binaryCnt(data, mid + 1, end, k);
		else if (data[mid]>k)
			cnt += GetNumberOfK_binaryCnt(data, start, mid-1, k);
		else
			return GetNumberOfK_binaryCnt(data, mid + 1, end, k) + GetNumberOfK_binaryCnt(data, start, mid, k);
	}

	return cnt;
}

int GetNumberOfK_binaryCnt(const int* data, int length, int k)//binaryCnt
{
	if (data == nullptr || length <= 0) return 0;
	if (k<data[0] || data[length - 1]<k) return 0;

	return GetNumberOfK_binaryCnt(data, 0, length-1, k);
}

解法一
int GetNumberOfK_Bruteforce(const int* data, int length, int k)//diy Brute force
{
	if (data == nullptr || length <= 0) return 0;
	if (k<data[0] || data[length - 1]<k) return 0;
	
	int cnt = 0;
	bool appreared = false;
	for (int i = 0; i < length;i++)
	{
		if (!appreared && data[i] == k)
		{
			cnt++;
			appreared = true;
		}
		else if (appreared && data[i]==k)
			cnt++;
		else if (appreared && data[i]!=k)
			break;
	}
	return cnt;
}

53.2 0~n-1中缺失的数字,长度为n-1的递增排序数组,所有数字都是唯一的,且在[0,n-1]内,在0-n-1内有且只有一个数字不在该数组中,找出该数

解法一:找到第一个下标与数字不同的数,返回下标o(n)

解法二:记录所有组的和,计算N个数的和,求差,o(n)

解法三:用二分法,找到第一个下标与数字不同的数字,往左偏移,即如果中位数与下标相等,从右边找;否则往左试探一位,如果下标与数字不等,往坐标找,如果下标与数字相等,该中位数就是那缺失的数字 o(log)

解法三
int GetMissingNumber(const int* numbers, int length)//diy
{
	if (numbers == nullptr || length <= 0) return -1;
	int L = 0, R = length - 1;
	while (L<=R)
	{
		int mid = (L + R) >> 1;
		if (numbers[mid] == mid)
			L = mid + 1;
		else
		{
			if (mid - 1 >= L && numbers[mid - 1] == mid - 1)
				return numbers[mid]-1;
			else if (mid - 1 >= L && numbers[mid - 1] != mid - 1)
				R = mid - 1;
			else
				return numbers[mid]-1;
		}
	}
	if (L > R)
		return numbers[length - 1] + 1;
    return -1;
}

 

53.3 在单调递增数组中找到任意一个数值等于其下标的元素,数组中的数可能为负数

下标递增线和值递增线,趋势上可能会有一个相交点

int GetNumberSameAsIndex(const int* numbers, int length) //diy
{
	if (numbers == nullptr || length <= 0) return -1;
	int L = 0, R = length - 1;
	while (L<=R)
	{
		int mid = (L + R) >> 1;
		if (numbers[mid] == mid) return mid;
		else if (numbers[mid] > mid)
			R = mid - 1;
		else
			L = mid + 1;
	}
	return -1;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值