剑指offer---基础知识:数组

1.sizeof关键字

1.1 定义一个空的类型,里面没有任何成员变量和成员函数,对该类型求sizeof,得到的结果是多少?
答案:1
解析:
空类型的实例中不包含任何信息,本来求sizeof应该是0,但是当我们声明该类型的实例的时候,它必须在内存中占有一定的空间,否则无法使用这些实例。至于占用多少内存,由编译器决定。Visual Studio中每个空类型的实例占用1字节的空间。

1.2 如果在该类型中添加一个构造函数和析构函数,再对该类型求sizeof得到的结果又是多少?
答案:1
解析:
调用构造函数和析构函数只需要直到函数的地址即可,而这些函数的地址只与类型相关,而与类型的实例无关,编译器也不会因为这两个函数而在实例内添加任何额外的信息。

1.3 如果把析构函数标记为虚函数,sizeof得到的结果又是多少?
答案:(32位系统)4、(64位系统)8
解析:
C++的编译器一旦发现一个类型中有虚函数,就会为该类型生成虚函数表,并在该类型的每一个实例中添加一个指向虚函数表的指针。在32位的机器上,一个指针占4字节的空间,如果在64位的机器上,一个指 针占8字节的空间。

2.数据结构

常用的数据结构:数组、字符串、链表、树、栈及队列

2.1 数组
数组占据一块连续的内存并按照顺序存储数据。创建数组时,首先指定数组的容量,然后根据大小分配内存。
数组中的内存是连续的,可根据下标读写任何元素,时间效率高,但经常有空闲的区域没有使用,空间效率不是很好。
2.2 找出数值中重复的数字
在一个长度为n的数组里的所有数字都在0~n-1的范围内。数组中某些数字是重复的,但不知道有哪几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或者是3。
方法一:排序,将数组的数字排序,在排好序的数组中找到重复的数组,时间复杂度很大O(nlogn)。
方法二:把每一个数字都扫描,看与其他剩下的数字是否相同。时间复杂度是O(n^2),两次for循环找出相同的数。
方法三:哈希表,扫描数组里的每个数字,看哈希表里是否有这个数字,没有就将这个数字加进去,有的话,则该数字重复。时间复杂度是O(n),但提高时间效率是以一个大小为O(n)的哈希表为代价
散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
方法四:数组里所有的数组都是0到n-1的范围内。如果数组里没有重复的数字,那么每个数字排序后的数字i都会在下标为i的位置上。由于数组中有重复的数字,那么这个位置上就会有多个数字,有些位置上也会没有数字。
从头到尾扫描这个数组的每个数字。当到下标为i的数字时,先比较这个数字m是否等于下标i,如果等于那么就扫描下一个数字;如果不是,那它和第m个数字相比较。如果和第m个数字一样,则找到重复的数字,因为该数字在第i个位置和第m个位置都出现了;如果不是则把该第i位置上的数字和第m个位置上的数字交换,刚在它原本属于的位置上去。重复此过程,找到重复的数字。(总体时间复杂度O(n))
测试用例:
(1)长度为n的数组里包含一个或多个重复的数字
(2)数组中不包含重复的数字
(3)无效的输入的测试用例:输入空指针、超出边界的数组值等
函数实现:
/
*********************************
Function: ai_findDuplicteDigit
Description:找到整型数组中的重复的数字
Parameter: number 需要查找的数组, 数字是0-n-1
len 数据长度
pDupDigit 返回重复的数字
Output: None
Return: None
*************************************************/
int ai_findDuplicteDigit(int number[], int len, int *pDupDigit)
{
int i = 0;
int tmp = 0;

if (!number || len <= 0 || !pDupDigit)
{
    return -1;
}

/* 校验值是否正确 */
for (i = 0; i < len; i++)
{
    if (number[i] < 0 || number[i] >= len)
    {
        return -1;
    }
}

for (i = 0; i < len; i++)
{
    while (i != number[i])
    {
        if (number[i] != number[number[i]])
        {
            tmp = number[i];
            number[i] = number[tmp];
            number[tmp] = tmp;
        }
        else
        {
            *pDupDigit = number[i];
            return 0;
        }
    }
}

return -1;

}

2.2 字符串

/*************************************************
Function: st_replaceBlank
Description:替换空格,实现将字符串中的每个空格替换成"%20"
在网络编程中,如果URL参数中含有特殊的字符,如空格、#等,则可能导致服务器端
无法获取正确的参数值,需要将这些特殊字符转换成服务器可识别的字符
转换规则:在’%'后面跟上ASCII码的两位十六进制表示。例如空格的ASCII是32,即十六进制0x20,
则空格替换为"%20"
解决方案有两种:空格是一个字符,但"%20"是三个字符
1.从前往后遇到空格将后面的字符往后移动,时间复杂度是O(n平方)
2. 时间空间为O(n)的方案
(1)遍历字符串,查找空格个数,替换字符串之后的总长度为原有字符串的总长度加上空格数乘以2
(2)从字符串的后面开始复制和替换,准备两个指针P1和P2,P1指向原始字符串的末尾,而P2指向替换之后的字符串的末尾
向前移动P1,逐个把它指向的字符复制到P2位置,遇到空格P1向前移动1格,P2移动3格
Parameter: string 字符串
length 字符串空间的总大小

Output: None
Return: None
*************************************************/
int st_replaceBlank(char string[], int length)
{
int blankNum = 0;
int realLength = 0;
int i = 0;
char *p1 = NULL;
char *p2 = NULL;
int outLength = 0;

if (!string || length <= 0)
{
    return -1;
}

realLength = strlen(string);
if (realLength <= 0)
{
    return 0;
}

/* 查询空字符个数 */
for (i = 0; i < realLength; i++)
{
    if (string[i] == ' ')
    {
        blankNum++;
    }
}

printf("blankNum:%d\n", blankNum);
if (blankNum == 0)
{
    return 0;
}

outLength = realLength + 1 + 2 * blankNum;
if (length < outLength)
{
    return -1;
}

p1 = &string[realLength + 1];
p2 = &string[outLength];
*p2 = *p1;
p1--;
p2--;
for (i = realLength; i >= 0; i--)
{
    if (string[i] == ' ')
    {
        p1--;
        *p2 = '0';
        *(--p2) = '2';

        *(--p2) = '%';
        p2--;
    }
    else
    {
        *p2 = *p1;
        p1--;
        p2--;
    }
}

return 0;

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值