剑桥offer面试题3:题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

目录

一、数组:

二、题目:

三、思路:


一、数组:

目录

一、数组:

1.数组是占据一块连续的内存并按照顺序存储数据。

2.数组和指针的区别与联系?

(1)概念

(2)赋值、存储方式、求sizeof、初始化

(3)传参

二、题目:

三、思路:

代码如下:


优点:时间效率高,因为数组中内存是连续的,根据下标在时间复杂度为O(1)下读/写任何元素。可以用数组此优点实现简单的哈希表。

缺点:空间效率不好,因为需要提前指定数组大小并预先分配内存,会使得有空闲区域没有被利用。(为了解决空间效率不高的问题,可以使用多种动态数组,比如C++的STL中的vector。先开辟较小的空间,当数组容量不够时,再重新扩容到以前容量的两倍,尽量减少扩容以免对时间性能有负面影响)

2.数组和指针的区别与联系?

(1)概念

* 数组:数组是用于储存多个相同类型数据的集合。
* 指针:指针相当于一个变量,但是它和不同变量不一样,它存放的是其它变量在内存中的地址。

(2)赋值、存储方式、求sizeof、初始化

1.赋值
同类型指针变量可以相互赋值,数组不行,只能一个一个元素的赋值或strcpy拷贝
2.存储方式
·数组:数组在内存中是连续存放的,开辟一块连续的内存空间。数组是根据数组的下进行访问的,多维数组在内存中是按照一维数组存储的,只是在逻辑上是多维的。
数组的存储空间,不是在静态区就是在栈上。
·指针:指针很灵活,它可以指向任意类型的数据。指针的类型说明了它所指向地址空间的内存。
指针本身就是一个变量,再加上它所存放的也是变量,所以指针的存储空间不能确定。
3.求sizeof
数组:
数组所占存储空间的
内存:sizeof(数组名)
数组的大小:sizeof(数组名)/sizeof(数据类型)
指针:
在32位平台下,无论指针的类型是什么,sizeof(指针名)都是4,在64位平台下,无论指针的类型是什么,sizeof(指针名)都是8。
4.初始化
数组:
int main()
{
    char arr[] = "hello";//6
    char brr[] = { "hello" };//6
    char crr[] = { 'h','e','l','l','o' };//5
    const char* drr = "abcde";//6
    cout << sizeof(arr) << endl;
    cout << sizeof(brr) << endl;
    cout << sizeof(crr) << endl;
    cout << sizeof("abcde") << endl;
}
这里补充一个大家的误区,就是关于数组的创建和销毁,尤其是多维数组的创建与销毁。
(1)一维数组:
int* arr = new int[n];//创建一维数组
delete[] arr;//销毁
(2)二维数组:
int** arr = new int*[row];//这样相当于创建了数组有多少行
for(int i=0;i<row;i++)
{
arr[i] = new int[col];//到这里才算创建好了
}
//释放
for(int i=0;i<row;i++)
{
delete[] arr[i];
}
delete[] arr;

指针:
//(1)指向对象的指针:()里面的值是初始化值
int *p=new int(0) ;    delete p;
//(2)指向数组的指针:(n表示数组的大小,值不必再编译时确定,可以在运行时确定)
int *p=new int[n];    delete[] p;
//(3)指向类的指针:(若构造函数有参数,则new Class后面有参数,否则调用默认构造函数,delete调用析构函数)
Class *p=new Class;  delete p;
//(4)指针的指针:(二级指针)
int **pp=new (int*)[1]; 
pp[0]=new int[6];
delete[] pp[0];

(3)传参

数组传参时,会退化为指针,所以我们先来看看什么是退化!(1)退化的意义:C语言只会以值拷贝的方式传递参数,参数传递时,如果只拷贝整个数组,效率会大大降低,并且在参数位于栈上,太大的数组拷贝将会导致栈溢出。(2)因此,C语言将数组的传参进行了退化。将整个数组拷贝一份传入函数时,将数组名看做常量指针,传数组首元素的地址。

二、题目:

在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

三、思路:

若从二维数组的左上角出发,如果该整数大于左上角的数字就会产生向右或者向下查找两条路径,所以我们应该选择从左下角或者右上角出发开始查找。

算法设计:假如从右上角开始查找

1.如果 arr[i][j] 等于target,则说明我们找到了目标值,返回true;

2.若arr[i][j] 小于target,左边的数一定都小于target,我们可以直接排除当前一整行的数,i++向下一行找;

3.如果 arr[i][j] 大于target,下边的数一定都大于target,我们可以直接排序当前一整列的数,j--向前一列找。

代码如下:

//每一步会排除一行或者一列,矩阵一共有 n行,m列,所以最多会进行 n+m步。所以时间复杂度是 O(n+m)
#include<stdio.h>
#include<stdlib.h>
#include<iostream>

using namespace std;
//C语言
bool Fun(int(*pr)[4], int row, int col, int val)
{
    int i = 0, j = 3;//从右上角开始
    while (i < row && j >=0)
    {
        if (val > pr[i][j])
        {
            i++;
        }
        else if (val < pr[i][j])
        {
            j--;
        }
        else if (val == pr[i][j])
        {
            return true;
        }
    }
    return false;
}

int main()
{
    int arr[4][4] = { {1,2,8,9},{2,4,9,12},{4,7,10,13},{6,8,11,15} };
    int val;
    scanf("%d",&val);
    bool res = Fun(arr, 4, 4, val);
    if (res)
    {
        printf("找到了/n");
    }
    else
    {
        printf("没找到/n");
    }
}

//C++
class Solution {
public:
    bool searchArray(vector<vector<int>> array, int target) {
        if (array.empty() || array[0].empty())
            return false;
        int i = 0;
        int j = array[0].size() - 1;
        while (i < array.size() && j > 0)
        {
            if (array[i][j] == target)
                return true;
            else if (array[i][j] > target)
                j--;
            else
                i++;
        }
        return false;
    }
};

int main()
{
    vector<vector<int>> nums;
    vector<int> tmp1;
    tmp1.assign({ 1,2,8,9 });
    nums.push_back(tmp1);
    tmp1.assign({ 2,4,9,12 });
    nums.push_back(tmp1);
    tmp1.assign({ 4,7,10,13 });
    nums.push_back(tmp1);
    tmp1.assign({ 6,8,11,15 });
    nums.push_back(tmp1);

    Solution s;
    if (s.searchArray(nums, 5))
        cout << "找到" << endl;
    else
        cout << "没找到" << endl;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宠宠熊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值