目录
一、数组:
目录
优点:时间效率高,因为数组中内存是连续的,根据下标在时间复杂度为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;
}