这部分不会有很系统的讲解,只是列举一些题目,分享一下我和别人的思路。
1.1 数组的查找
数组,可以说是最简单的数据类型,它占用一块连续的内存并按照顺序存储数据。与vector不同,创建数组时,需要指定数组的大小,而且不允许动态增加数组元素。
数组中的内存是连续的,而且可以根据下标读写元素,时间效率高,正是这一点,我们可以使用它来实现简单的哈希表。
在C/C++中,数组和指针是互相关联,而又有区别的两个概念。当我们声明一个数组时,数组名同时也是一个指针,我们可以用指针访问数组。而两者的区别,我们可以使用sizeof()看出来:
#include <iostream>
using namespace std;
int GetSize(int data[])
{
return sizeof(data);
}
int main()
{
int data1[] = {1,2,3,4,5};
int size1 = sizeof(data1);
int *data2 = data1;
int size2 = sizeof(data2);
int size3 = GetSize(data1);
cout << size1 << " " << size2 << " "<< size3;
}
运行结果:
sizeof(data1) - 求的是整个数组的大小;
sizeof(data2) - 求的是指针的大小,32位系统中为4;
GetSize(data3) - 函数调用用时,数组会自动退化为同类型的指针。
进入正题:二维数组中的查找
题目:(摘抄自剑指offer) 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
思路:不要使用逐个遍历,因为这个数组是有特点的,要利用数组本身的特点,进行计算。
举个实例:
如果寻找数字”1”,则返回true;如果寻找数字11,则返回false。
那么如何查找呢?
我们可以先查找最后的一列的第一行的元素,此处是4;如果target是小于该元素,则可略过该列,直接寻找它的前一列;如果target是大于该元素,则可以略过该行,直接寻找它的下一行。
程序实现:
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
/*二维数组的行数和列数*/
int rowCount = array.size(); //
int colCount = array[0].size();
int i, j;//i指定行的变化,j指定列的变化
//循环
for (i = 0, j = colCount-1; j>=0&&i<rowCount;)
{
if(target == array[i][j]) // 如果刚好等于target
return true;
if(target < array[i][j]) // 如果target较小,则查找上一列
{
--j;
continue;
}
if(target > array[i][j]) // 如果target较大,则查找下一行
{
++i;
continue;
}
}
return false;
}
};
同样用示例的数组作为实参,target设为1和11,运行得到结果:
运行成功,结果正确!
1.2 字符串的空格替换
在C/C++中,字符串都是以’\0’结尾的,这样我们很容易得到它的长度,当然,由于这个特性,我们在定义和使用字符串时,需要注意,不要造成字符串越界。
注意:为了节省内存,C/C++把常量字符串存放在独立的一个内存区域中,当指针赋值给相同的字符串时,它们实际上会指向相同的内存地址。
下面实例说明这一点
Exp:
#include <iostream>
using namespace std;
int main(int argv, char** argc)
{
char s1[20] = "hello world";
char s2[20] = "hello world";
char *p = "hello world";
char *q = "hello world";
if(s1 == s2)
cout << "s1 and s2 are the same!" << endl;
else
cout << "s1 and s2 are not the same!" << endl;
if(p==q)
cout << "p and q are the same!" << endl;
else
cout << "p and q are not the same!" << endl;
}
运行结果:
s1和s2是两个字符串数组,在C/C++中,它们各自存放在不同的内存区域中,因此,输出的结果显示两者不同;
而p和q是两个指针,C/C++中无须为它们分配内存以及存储字符串的内容,而只需要把它们指向”hello world”在内存中的地址即可。而”hello world”是常量字符串,它在内存中只有一个拷贝,因此p和q指向的是同一个地址。所以,p和q得到的结果相同的。
替换空格
题目:请实现一个函数,把字符串中的每一个空格替换成"%20"。例如:输入"We Are Happy",则输出"We%20Are%20Happy"。
分析:
与实际结合,在网络编程中,当URL参数中含有特殊字符,如空格、#号等,可能导致服务器无法获取正确的参数值。我们需要将这些特殊字符转换成服务器能识别的字符。
就本题而言,通过直接遍历,复制一个新的数组,这个是从前到后改变数组的值,可以实现该题功能,但是这样实现很复杂。
新思路:从后改变数组的值。先遍历求出数组的实际长度,并且求出新数组的实际长度,然后,使用下标从后给新数组赋值。如下图所示:
这样,就不需要两次遍历整个数组。
代码实现:
#include<stdio.h>
class Solution
{
public:
void replaceSpace(char *str, int length)
{
// 简单的错误性判断
if(*str==NULL && length <= 0)
return ;
// 首先计算原始数组长度,统计空格的个数
int OldLength = 0;
int i = 0;
int BlankNum = 0;
while(str[i] != '\0') // 字符串数组可以使用该特点
{
if(str[i] == ' ')
++ BlankNum;
++ i;
++ OldLength; // 注意:此处不能使用i作为数组长度,因为最后一个i对应的是'\0'
}
// 求出新数组的长度
// 并使用下表从尾到头进行赋值
int Oldindex = OldLength;
int Newindex = OldLength + 2*BlankNum;
while(Oldindex <= Newindex && Oldindex>=0)
{
if(str[Oldindex]==' ')
{
str[Newindex--] = '0';
str[Newindex--] = '2';
str[Newindex--] = '%';
}
else
{
str[Newindex--] = str[Oldindex];
}
--Oldindex;
}
}
};
int main()
{
char str11[20] = "We Are Happy"; // 注意:此处应该给出合理的大小,虽然也会有结果,
// 但是同时也会产生调试错误!
char *q = str11;
printf("Original char array: \n");
while(*q != '\0')
{
printf("%c",*q);
q++;
}
printf("\n\n");
Solution s1;
s1.replaceSpace(str11,50);
char *p = str11;
printf("After solution: \n");
while(*p != '\0')
{
printf("%c",*p);
p++;
}
printf("\n");
return 0;
}
运行结果:
运行成功!