键指offer——面试题4:二维数组中的查找(p44-48)

二维数组的查找

题目描述:
在一个二维数组中,每行都按从左到右的方向递增排序,每列按从上到下的方式递增排序。完成一个函数,输入一个要查找的数num和这个二维数组,判断这个二维数组中是否有这个值。

分析:
办法就是现在这个二维数组中找到一个值,和num比较大小:相同,则return True;否则不相同 :num大于这个值的话一定是在这个数的右方和下方区域,num小于这个值的话一定是在这个数的左下方区域。
相对简单的就是把二维数组中的这个要和num进行比较的数放在右上角或者左下角区域。

放右上角:这样若num大于这个值就删除这整个行;若num小于这个值就删除这整个列,然后在剩下的区域继续寻找。

放左下角:这样若num大于这个值就删除这整个列;若num小于这个值就删除这整个行,然后在剩下的区域继续寻找。

代码:

  • 放右上角的情况:
bool find(int a[4][4],int rows,int cols,int num)
{
	bool found = false;
	if(a == nullptr || rows<0 || cols<0)
		return found;
	int row = 0, col = cols-1;
	while(row<rows && col>=0)
	{
		if(num == a[row][col])
		{
			found = true;
			break;
		}
		else if(num > a[row][col])
			++row;
		else
			--col;
	}
	return found;
}
  • 放左下角的情况:
bool find(int a[4][4],int rows,int cols,int num)
{
	bool found = false;
	if(a == nullptr || rows<0 || cols<0)
		return found;
	int row = rows-1, col = 0;
	while(row>=0 && col<cols)
	{
		if(num == a[row][col])
		{
			found = true;
			break;
		}
		else if(num < a[row][col])
			--row;
		else
			++col;
	}
	return found;
}

在源码中,用的就是一维数组打印法,调用:Find(matrix, rows, columns, number);,传参:bool Find(int* matrix, int rows, int columns, int number),打印:matrix[row * columns + column]

bool Find(int* matrix, int rows, int columns, int number)
{
    bool found = false;

    if(matrix != nullptr && rows > 0 && columns > 0)
    {
        int row = 0;
        int column = columns - 1;
        while(row < rows && column >=0)
        {
            if(matrix[row * columns + column] == number)
            {
                found = true;
                break;
            }
            else if(matrix[row * columns + column] > number)
                -- column;
            else
                ++ row;
        }
    }

    return found;
}

笔记:

各个指针之间的区别
  1. int a;表示一个内存空间,这个空间用来存放一个整数(int);
  2. int* a;表示一个内存空间,这个空间用来存放一个指针,这个指针指向一个存放整数的空间,即a)中提到的空间;
  3. int** a;表示一个内存空间,这个空间用来存放一个指针,这个指针指向一个存放指针的空间,并且指向的这个空间中的指针,指向一个整数。也简单的说,指向了一个b)中提到的空间;
  4. int (*a)[4];表示一个内存空间,这个空间用来存放一个指针,这个指针指向一个长度为4、类型为int的数组;int** a的区别在于,++、+=1之后的结果不一样,其他用法基本相同。
    以上四种类型见上图表示。
  5. int (*a)(int);表示一个内存空间,这个空间用来存放一个指针,这个指针指向一个函数,这个函数有一个类型为int的参数,并且函数的返回类型也是int。
定义已知维度的二维数并初始化
int a[5][3]={ {80,75,92}, {61,65,71}, {59,63,70}, {85,87,90}, {76,77,85} };
int a[5][3]={80, 75, 92, 61, 65, 71, 59, 63, 70, 85, 87, 90, 76, 77, 85};

对于二维数组的初始化还要注意以下几点:

  1. **可以只对部分元素赋值,未赋值的元素自动取“零”值。**例如:
int a[3][3] = {{1}, {2}, {3}};
  1. **如果对全部元素赋值,那么第一维的长度可以不给出。**例如:
    int a[3][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    可以写为:
int a[][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
  1. 二维数组可以看作是由一维数组嵌套而成的;如果一个数组的每个元素又是一个数组,那么它就是二维数组。
  2. 二维数组转化成一维数组
    有些时候,我们觉得用二维数组来描述一样事物很方便。比如我们用二维数组来画一个迷宫地图,行下标和列下标就如同直角坐标系一样。可是在某些情况下,不能使用二维数组,或者难以制造一个二维数组。二维数组在内存中的存储情况和一维数组是相同的,所以我们只好用一个一维数组来代替它了。
    于是,我们不难总结出一个结果,一个二维数组元素a[x][y]在一维数组b中,是:a[x][y] = b[x*列数+y]
定义未知维度的二维数组并进行赋值(还是得知道具体的行值和列值才能进行初始化)
int **a;
    a = (int**)malloc(sizeof(int*)*3);//为二维数组分配3行
    //为每列分配4个大小空间
    for (int i = 0; i < 3; ++i)
    {
        a[i] = (int*)malloc(sizeof(int)*4);
    }
    //初始化
    for (int i = 0; i < 3; ++i)
    {
        for (int j = 0; j < 4; ++j)
        {
            a[i][j] = i+j;
        }
    }
    
	//输出测试
    for (i = 0; i < 3; ++i){
        for (j = 0; j < 4; ++j){
            printf ("%d ", a[i][j]);
        }
        printf ("\n");
    }
    
    //释放动态开辟的空间
    for (i = 0; i < 3; ++i){
        free(a[i]);
    }
    free(a);
    return 0;
}
/*
输出:
0 1 2 3
1 2 3 4
2 3 4 5
*/
打印二维数组方法
  1. 常规法:
    调用print1(arr, 3, 5);, 传参void print1(int arr[3][5], int row, int col)
void print1(int arr[3][5], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
}
int main()
{
	int arr[3][5] = { 1,2,3,4,5,6,7,8,9,10 };
	print1(arr, 3, 5);
	return 0;
}

  1. 传指针法
    数组传参都会发生降维,降维成指向其内部元素的指针,因为二维数组被看成一个数组元素为一维数组的一维数组。所以在这里,二维数组arr降维成一个指向一维数组的指针,即(*arr)[5],这里与3也就没有任何关系了。
void print2(int (*arr)[5], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
}
int main()
{
	int arr[3][5] = { 1,2,3,4,5,6,7,8,9,10 };
	print2(arr, 3, 5);
	return 0;
}

  1. 一维数组打印法
    在我所总结的关于规律里,认为所有的不管几维数组,都可以被看为一维数组。所以二维数组就是一维数组,只不过里面的元素为一维数组。所以我想要通过一维数组来打印二维数组。这里假设打印一个3行3列的数组。arr[3][3].
void print3(int *arr, int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			printf("%d ", arr[i*row+j]);
		}
		printf("\n");
	}
}
int main()
{
	int arr[3][3] = { 1,2,3,4,5,6,7,8,9};
	print3(arr, 3, 3);
	return 0;
}

你可能感兴趣的:(剑指offer,面试题,指针,数据结构,算法,c++)