剑指offer-第三题方法总结

杨氏矩阵:每一行自左向右递增,每一列自上向下递增。

题目:输入一个杨氏矩阵和一个整数,判断这个数是在杨氏矩阵中出现。


分析:有三种时间复杂度各不相同的解法。
          第一种:遍历整个二维数组,这种方法效率最低。
          第二种:因为杨氏矩阵每行都是递增的,是有序的,我们可以先判断这个整数是否大于等于每行的第一个元素,小于等于最后一个元素。如果是的话,则对这行使用折半查找法进行查找。这种方法效率次之。

           第三种:因为每行是递增的,每列也是递增的,我们可以将这个数与最右上角的元素进行比较。如果这个数大于右上角元素,则表明这个数大于这一行元素,因此这个数只可能在这一行的下方出现,所以查找方位缩小到这一行的下方。同样的,如果这个数小于右上角元素,则表明这个数小于这一列元素,因此查找范围可以缩小到这一列的左侧。(也可以与左下角的元素进行比较)这种方式效率最高。



#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#define row 4
#define col 3

//第一种
int check_num(int (*p)[col], int num, int line, int rank)    //遍历数组
{
	int i = 0;
	int j = 0;
	for (i = 0; i < line; i++)
	{
		for (j = 0; j < rank; j++)
		{
			if (p[i][j] == num)
				return 1;             //存在则返回1
		}
	}

	return 0;
}

//第二种
int check_num(int(*p)[col], int num, int line, int rank)
{
	for (int i = 0; i < line; i++)
	{
		if (num>=p[i][0]&&num <= p[i][rank - 1])     //判断num是否有可能在这行,如果在的话进入if
		{
			int *left = &p[i][0];
			int *right = &p[i][rank - 1];
			int *tmp = NULL;
			while (left <= right)                  //折半查找法查找
			{
			    tmp = left + (right - left) / 2;
				if (num>=*tmp)
					left =tmp + 1;
				if (num <= *tmp)
					right = tmp - 1;
				if (num == *tmp)
					   return 1;                      //存在则返回1
			}
		}
	}
	return 0;
}

//第三种
int check_num(int(*p)[col], int num, int line, int rank)
{
	int i = 0;
	int j = rank-1;
	while (i < line || j >= 0)
	{
		if (num < p[i][j])      //如果num小于i行最后一个数,则列自减
			j--;
		if (num>p[i][j])        //如果num大于i行最后一个数,则行自增
			i++;
		if (num == p[i][j])
			return 1;                   // 存在则返回1
	}
	return 0;

}

int main()
{
	int n = 0;
	int arr[row][col] = { 0 };
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j <col; j++)
		{
			scanf("%d", &arr[i][j]);
		}
	}
	scanf("%d", &n);
	int ret = check_num(arr, n, row, col);
	if (ret==1)
		printf("YES\n");
	else
		printf("NO\n");
	system("pause");
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值