创新工场两道笔试题0919

来源:互联网 发布:淘宝集分宝 编辑:程序博客网 时间:2024/06/15 17:02

【题目1】

字符串去重,老题目,只是要求不能开辟新空间用来复制原字符串
思路:使用布尔型的简单hash表可以节省空间,用来存储字符是否出现的信息,刚开始hash表里面都是false,当第一次字符出现的时候,置成true,再次碰见的时候直接删除这个字符就行了。
char* remove_multiple_char(char* str){assert(str != NULL);char* tmp = str;char* tmp2 = str;bool hash_table[256] = {false};while(*tmp2 != '\0'){if (!hash_table[*tmp2 - '\0']){hash_table[*tmp2 - '\0'] = true;*tmp++ = *tmp2++;}else{tmp2++;}}*tmp = '\0';return str;}

【题目2】

求逆序对个数,在一个数组a里,如果i < j,a[i]>a[j],那么<a[i],a[j]>称为一个逆序对,如3,5,1,2 一共有<3,1><3,2><5,1><5,2>四个逆序对
思路1:对数组中的每个数字,扫描它后面的数字,如果后面的数比这个数小,则存在逆序对,这样将数组扫描完需要的时间复杂度是O(N^2)
思路2:利用归并排序,归并排序的核心算法中,合并两个前后两个序列的时候,可以统计这两个前后序列之间的逆序对,再加上每个序列的逆序对,就是一共的逆序对,
//每个序列的逆序对,可以用递归分治
int g_inverse_count = 0;void merge_core(int a[], int begin, int mid, int end){int i = begin;int j = mid+1;int *b = new int[end - begin + 1];int k = 0;while(i <= mid && j <= end){if(a[i] < a[j])b[k++] = a[i++];else{b[k++] = a[j++];g_inverse_count += (mid - i + 1);//举个例子,原序列是9 10 2 4 3//最后要合并的两个左右序列是2 9 10 和4 3//刚开始a[i]=2 a[j] = 4,a[i]<a[j]不存在逆序对,将i++,a[i]->9//这时候a[i]>a[j],存在逆序对,并且前一个序列中a[i+1...mid]因为是已经排序的,//后面的每个数肯定也大于a[i],当然也大于a[j],当然也和a[j]成逆序对,这时候的逆序对的个数应该为mid-i+1}}while(i <= mid){b[k++] = a[i++];}while(j <= end)b[k++] = a[j++];for (i = 0; i < k; i++)a[begin + i] = b[i];//替换原来的delete []b;}void merge_sort(int a[], int first, int last){if (first < last){int mid = (last + first)/2;merge_sort(a, first, mid);merge_sort(a, mid+1, last);merge_core(a, first, mid, last);}}

【测试】

int main(){int data[] = {7, 1, 9, 10, 2, 3, 4};merge_sort(data, 0, 6);cout<<g_inverse_count;g_inverse_count = 0;int data2[] = {9, 10, 2, 4, 3};merge_sort(data2, 0, 4);cout<<g_inverse_count;}



原创粉丝点击