[剑指offer] 二维数组的查找

一.当我们需要解决一个复杂的问题时,一个很有效的办法就是从一个具体的问题入手,通过分析简单具体的例子,试图寻找普遍的规律。(减而治之)

二.题目要求用vector生成二维数组,对vector还不太熟悉,整理下。
1.vector用法:
(1)使用时需包含头文件

#include 

(2)vector的初始化(不能用包含多个值的括号来进行初始化vector)

1. vector  name(n); //定义了包含n个T型元素的向量
2. vector name(n,1);//定义了包含n个T型元素,其初值都为orin的向量
3. vector a(b);//用b向量来创建a
4. vector a(b.begin(),b.begin+3);//将b中的0-2个元素复制给a;
5./*若T为int,则可从数组中获得初值*/
   b[7]={0,1,2,3,4,5,6,7};
   vector a(b,b+7);

(3)vector对象的几个重要操作

    (1)a.assign(b.begin(), b.begin()+3); //b为向量,将b的0~2个元素构成的向量赋给a
    (2)a.assign(4,2); //是a只含4个元素,且每个元素为2
    (3)a.back(); //返回a的最后一个元素
    (4)a.front(); //返回a的第一个元素
    (5)a[i]; //返回a的第i个元素,当且仅当a[i]存在2013-12-07
    (6)a.clear(); //清空a中的元素
    (7)a.empty(); //判断a是否为空,空则返回ture,不空则返回false
    (8)a.pop_back(); //删除a向量的最后一个元素
    (9)a.erase(a.begin()+1,a.begin()+3); //删除a中第1个(从第0个算起)到第2个元素,也就是说删除的元素从a.begin()+1算起(包括它)一直到a.begin()+         3(不包括它)
    (10)a.push_back(5); //在a的最后一个向量后插入一个元素,其值为5
    (11)a.insert(a.begin()+1,5); //在a的第1个元素(从第0个算起)的位置插入数值5,如a为1,2,3,4,插入元素后为1,5,2,3,4
    (12)a.insert(a.begin()+1,3,5); //在a的第1个元素(从第0个算起)的位置插入3个数,其值都为5
    (13)a.insert(a.begin()+1,b+3,b+6); //b为数组,在a的第1个元素(从第0个算起)的位置插入b的第3个元素到第5个元素(不包括b+6),如b为1,2,3,4,5,9,8         ,插入元素后为1,4,5,9,2,3,4,5,9,8
    (14)a.size(); //返回a中元素的个数;
    (15)a.capacity(); //返回a在内存中总共可以容纳的元素个数
    (16)a.resize(10); //将a的现有元素个数调至10个,多则删,少则补,其值随机
    (17)a.resize(10,2); //将a的现有元素个数调至10个,多则删,少则补,其值为2
    (18)a.reserve(100); //将a的容量(capacity)扩充至100,也就是说现在测试a.capacity();的时候返回值是100.这种操作只有在需要给a添加大量数据的时候才         显得有意义,因为这将避免内存多次容量扩充操作(当a的容量不足时电脑会自动扩容,当然这必然降低性能) 
    (19)a.swap(b); //b为向量,将a中的元素和b中的元素进行整体性交换
    (20)a==b; //b为向量,向量的比较操作还有!=,>=,<=,>,<

(4)误区

vector a();
for(i=0;i<10;i++)
a[i]=i;

错误:下标只能用于获取已存在的元素;
改正:

    for (int i = 0; i < 10; i++)
        test.push_back(i);

或者 定义了容器的大小

vector test(10);
    for (int i = 0; i < 10; i++)
        test[i] = i;

(5)几种重要的算法,使用时需包含头文件

#include 
(1)sort(a.begin(),a.end()); //对a中的从a.begin()(包括它)到a.end()(不包括它)的元素进行从小到大排列
(2)reverse(a.begin(),a.end()); //对a中的从a.begin()(包括它)到a.end()(不包括它)的元素倒置,但不排列,如a中元素为1,3,2,4,倒置后为4,2,3,1
(3)copy(a.begin(),a.end(),b.begin()+1); //把a中的从a.begin()(包括它)到a.end()(不包括它)的元素复制到b中,从b.begin()+1的位置(包括它)开始复制,覆盖掉原有元素
(4)find(a.begin(),a.end(),10); //在a中的从a.begin()(包括它)到a.end()(不包括它)的元素中查找10,若存在返回其在向量中的位置

2.vector与数组
(1)区别
内存中的位置:C++中数组为内置的数据类型,存放在栈中,其内存的分配和释放完全由系统自动完成;vector,存放在堆中,由STL库中程序负责内存的分配和释放,使用方便。
大小能否变化:数组的大小在初始化后就固定不变,而vector可以通过push_back或pop等操作进行变化。
初始化:数组不能将数组的内容拷贝给其他数组作为初始值,也不能用数组为其他数组赋值;而向量可以。
执行效率:数组>vector向量。主要原因是vector的扩容过程要消耗大量的时间。
(2)vector “动态数组”
a.原因:弥补普通数组(如“int a[8]”)只能固定长度的缺陷;
弥补一般堆数组(如int *p = new int[n])需要预先知道长度,并且长度不可变的缺陷。
相对STL中其他容器,如list,vector与数组更接近,它内部的数据存储在一片连续的存储空间,访问效率会更高;而list是链表,数据在存储空间上不相邻。
b.vector与数组的相互转换
初始化5中有数组到vector的转换
vector转数组
由于vector内部的数据是存放在连续的存储空间,vector转数组事实上只需要获取vector中第一个数据的地址和数据的长度即可。如果仅仅是传参,无需任何操作,直接传地址即可,如果要进行数据复制,可以借用内存拷贝函数“memcpy”。例如:


 float *buffer = new float[vecHeight.size()];
    if (!vecHeight.empty())
    {
        memcpy(buffer, &vecHeight[0], vecHeight.size()*sizeof(float));
    }

3.应用建议
(1)vector作为动态数组,它的实现方法是:预先分配一个内存块,当感觉不够用的时候,再分配一个更大的内存块,然后自动将之前的数据拷贝到新的内存块中。
所以,出于效率考虑,如果实现知道待存储的数据长度,可以使用resize函数开辟足够的内存,避免后续的内存拷贝。
(2)如果数组的元素是字符,建议使用string,而不是vector
4.生成动态二维数组

int row,column;
cin<

使用vector

//申请空间
vector> array(row,vector(column));
//使用空间
    for(int j = 0;j < row;j++)
        for(int k = 0;k< column;k++)
            cin>>a[j][k] ;
/*若要获得二维数组的行数和列数*/
vector > array;
int row=array.size();
int column=array[0].size();

使用指针

int **a=new int*(row);
for(int i = 0;i < row;i++)
a[i] = new int[column];
//使用空间
for(int j = 0;j < row;j++)
for(int k = 0;k< column;k++)
        a[j][k] = rand()%100;
//释放空间
    for(int i = 0;i < row;i++)
            delete a[i]
    delete [] a;

三.编程时遇到的问题

class Solution {
public:
    bool Find(int target, vector > array) {
        bool find=false;
        int row=array.size();
        int column=array[0].size();
        for(int i=row-1;i>=0;i--)
            for(int j=0;j
image.png

逻辑错误 ,应为 a[i][j]

你可能感兴趣的:([剑指offer] 二维数组的查找)