数据结构:数组

数组和字符串是两种最基本的数据结构,数组占据一块连续的内存并按照顺序存储数据。创建数组时,我们需要首先指定数组的容量大小,然后根据大小分配内存,因此数组的空间效率不是很好,会有空闲的区域,导致内存浪费。
1.数组与哈希表
因为数组中的内存是连续的,根据下标读写元素,它的效率比较高,我们可以利用数组的时间效率高的特点去实现简单的哈希表:把数组的下标设为哈希表的键值,数组中存放的值设为哈希表的值。
2.动态数组
为了避免浪费,设计了多种动态数组,先为数组开辟较小的空间。当数据的数目超出数组的容量时,我们再重新分配一块更大的空间。并把之前的数据复制到新内存中,把之前的内存释放,这样能减少内存浪费。但是每一次动态扩充是都会有很多的额外操作,这对时间性能不利,因此动态数组要尽量减少改变数组容量大小的次数。
3.数组与指针
sizeof(指针)大小恒定为4,sizeof(数组)是求数组的大小。
当数组作为函数参数进行传递时,数组就会自动退化为同类型的指针。

//=========剑指offer第二版面试题50===============
//字符串中第一只出现一次的字符
//在字符串中找出第一个只出现一次的字符,如输入“abaccdeff”,则输出‘b’
/*解题思路:在本题中我们只需要利用一个简单的哈希表,字符是一个长度为(0-255)*/
# include <stdio.h>
# include <string.h>


char FirstNotRepeatingChar(char * pString)
{
	if(pString == NULL)
	{
		return '\0';
	}
	const int size = 256;
	int array[size];
	for(int i=0;i<size;i++)
	{
		array[i]=0;
	}

	char *p = pString;
	while (*p!='\0')
	{
		array[*p++]++;
	}
	p=pString;
	while(*p!='\0')
	{
		if(array[*p]==1)
		{
			return *p;
		}
		p++;
	}
	return '\0';

}

//==========测试用例========
void Test(char *pString,char key)
{
	if(FirstNotRepeatingChar(pString) == key)
        printf("Test passed.\n");
    else
        printf("Test failed.\n");
}

int main()
{
    // 存在只出现一次的字符
    Test("google", 'l');

    // 不存在只出现一次的字符
    Test("aabccdbd", '\0');

    // 所有字符都只出现一次
    Test("abcdefg", 'a');

    // 输入nullptr
    Test(nullptr, '\0');

    return 0;
}

输出结果为:
Test passed.
Test passed.
Test passed.
Test passed.
请按任意键继续. . .

//===========剑指offer第二版面试题3========
//题目一:找出数组中重复的数字
/*解题思路:1.先把这个数组进行排序,从排序好的数组中从头到尾遍历一遍找到重复的数字时间复杂度为O(nlogn)
2.利用哈希表来解决,需要申请一个空间为n的哈希表,以空间换时间
3.重排这个数组,从头到尾扫描这个数组,当扫描到下标为i时,首先比较这个数字m是不是等于i,如果是则继续扫描如果不是,再拿他跟m下标下的数字
进行比较,如果它跟m下标所存放的数字相等,则找到一个重复数字,如果不相等,就把这个数与m下标的数进行互换,继续比较,直到发现一个重复数字。
*/

# include <stdio.h>
bool duplicate(int arr[],int length,int *duplicate)
{
	if(arr == NULL || length <=0)//先排除不符合条件的情况
	{
		return false;
	}
	for(int i=0;i<length-1;i++)
	{
		if(arr[i]<0||arr[i]>length-1)
		{
			return false;
		}
	}
	for(int i=0;i<length-1;i++)
	{
		while(arr[i]!=i)
		{
			if(arr[arr[i]]==arr[i])//如果该元素与m位置元素相同,则找到了一个重复数字
			{
				*duplicate = arr[i];
				return true;
			}
			//交换该元素与m位置元素
			int temp = arr[i];
			arr[i]=arr[arr[i]];
			arr[temp]=temp;//注意在这里犯错为了!!第一次错写为arr[arr[i]],此时会陷入死循环
		}
	}
	return false;//直到整个数组遍历完,表示还没找到,返回false
}
//==========测试用例===========
bool contains(int array[], int length, int number)
{
    for(int i = 0; i < length; ++i)
    {
        if(array[i] == number)
            return true;
    }

    return false;
}

void test(char* testName, int numbers[], int lengthNumbers, int expected[], int expectedExpected, bool validArgument)
{
    printf("%s begins: ", testName);

    int duplication;
    bool validInput = duplicate(numbers, lengthNumbers, &duplication);

    if(validArgument == validInput)
    {
        if(validArgument)
        {
            if(contains(expected, expectedExpected, duplication))
                printf("Passed.\n");
            else
                printf("FAILED.\n");
        }
        else
            printf("Passed.\n");
    }
    else
        printf("FAILED.\n");
}

// 重复的数字是数组中最小的数字
void test1()
{
    int numbers[] = { 2, 1, 3, 1, 4 };
    int duplications[] = { 1 };
    test("Test1", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int), true);
}

// 重复的数字是数组中最大的数字
void test2()
{
    int numbers[] = { 2, 4, 3, 1, 4 };
    int duplications[] = { 4 };
    test("Test2", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int), true);
}

// 数组中存在多个重复的数字
void test3()
{
    int numbers[] = { 2, 4, 2, 1, 4 };
    int duplications[] = { 2, 4 };
    test("Test3", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int), true);
}

// 没有重复的数字
void test4()
{
    int numbers[] = { 2, 1, 3, 0, 4 };
    int duplications[] = { -1 }; // not in use in the test function
    test("Test4", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int), false);
}

// 没有重复的数字
void test5()
{
    int numbers[] = { 2, 1, 3, 5, 4 };
    int duplications[] = { -1 }; // not in use in the test function
    test("Test5", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int), false);
}

// 无效的输入
void test6()
{
    int* numbers = NULL;
    int duplications[] = { -1 }; // not in use in the test function
    test("Test6", numbers, 0, duplications, sizeof(duplications) / sizeof(int), false);
}

int main()
{
    test1();
    test2();
    test3();
    test4();
    test5();
    test6();
	return 0;
}

输出结果为:
Test1 begins: Passed.
Test2 begins: Passed.
Test3 begins: Passed.
Test4 begins: Passed.
Test5 begins: Passed.
Test6 begins: Passed.
请按任意键继续. . .

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值