常见面试题:二维递增数组的快速查找,复杂度(M+N-2),M,N分别为数组的行数和列数

题目:一个二维数组,按行按列都是递增的,要求程序在尽可能小的复杂度的情况下查找给定的元素。

例如:a[4][5]={
         {1, 3, 7, 11, 19},
         {2, 7, 10, 29, 30},
         {13, 28, 54, 69, 90},
         {46, 57, 78, 98, 101}
     }查找29,返回其下标(1,3)。

思路:需要充分利用数组的特点,按行按列都是递增的,这样才能减小复杂度。

下面就找一下特点喽,按行按列递增这是最明显的,还有隐含一点的就是,左上角和右下角分别是最小和最大的元素。恩,对的。哪还有呢?我们需要的是简便算法呀!继续看的话会发现,一列的最大元素在对应的最后一行,(废话),一行的最小一个在最左边。如果一个元素比一列的最下面一个元素还大的话,那它就一定不在这一列。诶,有点眉目了。如果要查找的元素比第一列的最下面一个元素还大的话,那它一定在之后的数组中。同理,目标如果比这个元素小的话,那它一定不在此行,且在上面的几行里。哈哈,数组又缩小了。然后,我们每次都能排除一行或一列,最难找的那个元素就是右上角的了。那它的复杂度是多少那?折线走过去,就是M-1+N-1,对啊,线性哎,不错1

//c语言
#include <stdio.h>
/*a是按行按列均递增的数组,该函数实现在数组中找出目标数据的下标,M和N表示数组的行数和列数*/
/*注:未考虑数组合法与否,返回的是数组的下标*/
int getIndexofIncArray(int *a, int M, int N, int target, int *x, int *y){
	int i=0, j = M-1, count;//找不到元素的话返回-1,找到的话返回0,i表示列
	*x = *y = -1;//初始化
	for(count=0; count<N+M;count++){
		printf("第%d次访问:%d\n",count, *(a + N*j + i));
		if(target == *(a + N*j + i)){
			*x = j;
			*y = i;
			return 0;
		}else	if(target > *(a + N*j + i)){//目标大于,右移
			if((i >= N) && (j < 0)){
				break;
			}else{
				i++;
			}
		}else{
			if((i >= N) && (j < 0)){
				break;
			}else{//目标小于,上移
				j--;
			}
		}
	}
	return -1;
}

 void  main(){
	 int i, j;
	 int *p1 = &i, *p2 = &j;
	 int a[4][5]={
		 {1, 3, 7, 11, 19},
		 {2, 7, 10, 29, 30},
		 {13, 28, 54, 69, 90},
		 {46, 57, 78, 98, 101}
	 };
	 getIndexofIncArray(&a[0][0], 4, 5, 19, p1, p2);
	 printf("%d, %d", i, j);
	 getchar();
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值