1->比如给你一个数组,里面的数有200个,最大的数是1000,时间效率的重要性高于空间效率,那么你会采用哪种排序策略呢?能否达到O(n)
思路:对于这种问题,可能我们会想到很多种排序方法,冒泡排序,快速排序,希尔排序,堆排序,插入排序,选择排序以及归并排序;
可是仔细想想他们的时间复杂度:
冒泡排序中第n个数据分别比较n-1次,时间复杂度是O(n^2);复杂度太高;
快速排序,也是基于分治的思想,他的每次划分都至少把一个元素放在正确位置上,基本有序时间复杂度为O(n^2),最好情况O(nlogn);
希尔排序,需要定义步长的排序方法,对于大数据量的排序,比插入排序效率高很多,最好时间复杂度O(n),最坏时间复杂度O(n^2);
堆排序,对于大数据量查找最大值,最小值问题可以采用大顶堆,小顶堆方法,时间复杂度O(nlogn);
插入排序,时间复杂度,每个元素都要比较n-1次,每次都能把一个元素放在正确位置上,时间复杂度O(n^2);
选择排序,其中的直接选择排序,每次找一个最小元素,放在第一个位置,在选取剩下元素最小的,与第二个值交换,依次。。。第n趟要比较n-1次,时间复杂度O(n^2);
归并排序,基于分治的排序方法,先将待排序数组分为两个数组,依次类推,切分数组知道只剩一个数据单元,然后排序合并,时间复杂度,n(logn)。
都不是很满意题目的要求,所以换个思路:
首先定义一个整型数组B,由于待排最大值是1000,数组可以定义大小为1001,全部初始化为0,然后遍历待排序的数组,以待排数组中的数据值作为下标,更改B数组此下标的值+1,之后遍历B数组,相应不为0的小标就是待排序数组排序后的值。可能出现某下标的数值不为1,为n,说明待排数组出现了n次。
这叫做桶排序,时间复杂度O(n)。
2->现在给定一个整数K,问你如何确定这个数组里是否有两个整数的加和为K存在?时间复杂度O(n)
这道题的思路就是:假如sum= 10, 已知数组A为[3,4,5,7,9],首先定义一个整型数组B,全部初始化0,当遍历数组A时,每获取一个数组A中的元素K,都去判断以sum-K为下标的B数组中的值是否大于0,如果不是,说明还没出现与K相加为sum的那个数字,将B[K]加1,继续遍历下一个,依次类推,知道出现K且B[sum-K]也大于0,那么可以返回这组数字啦,他们就是在这个数组中第一个加和为sum的值。
有个思维定势:就是在内存没有限制的时候,字符型数组、整型数组排序的很多问题都可以用这样的一个数据结构存储处理。
3->给定一个字符数组,求它的子字符串中字母不重复的最长子串,例如abeomeabscqescan(求出结果为eabscq)
#include<stdio.h> #include<stdlib.h> void get_str(int start, int length, char*str) { int i=0; char p[16]; for(i = start; i<length+start; i++) { p[i-start] = str[i]; } printf(" %s ", p); } void find_str() { char str[16] = {"abeomeabscqescan"}; int last_start=0, last_length=0; int cur_start = 0, cur_length = 0; int temp[26] = {0}; int i=0; char *result; while(i<sizeof(str)) { if((temp[str[i]-'a'] +1) > 1) { //比较length if(last_length < cur_length) { last_length = cur_length; last_start = cur_start; cur_length = 0; cur_start = i; i++; } else { cur_length += 1; i++; } }else { temp[str[i]-'a'] += 1; cur_length += 1; i++; } } if(last_length < cur_length) { get_str(cur_start, cur_length, str); printf(" %d ", cur_length); } else { get_str(last_start, last_length, str); printf(" %d ", last_length); } } int main(int argc, char* argv[]) { find_str(); return 0; }
返回eabscq~时间复杂度O(n);