创新工场编程题
9月16日,创新工场校招笔试题:
1.输入一个整型无序数组,用堆排序的方法是数组有序
2.求一个正整数的开方,要求不能使用库函数sqrt,结果精度在0.01即可
3.给定一个矩阵int matrixA[m][n],每行没列都是增序的,实现一个算法寻找矩阵中的某个元素element
下面做出我的题解,能力有限,望见谅!
第一题:堆排序
考的排序算法中的堆排序,这里稍微讲一下堆排序的算法:
二叉树:
基本概念:
大根堆: 就是说父节点要比左右孩子都要大。
小根堆: 就是说父节点要比左右孩子都要小。
算法:
1、从最后一个父结点开始,从后往前遍历树的所有二叉树的父节点,构造大顶堆;
2、整个数都是大顶堆,那么树的根节点肯定是数组中的最大值,将其与最后一个元素交换swap,这时可能会破坏大顶堆,需要重新构建大顶堆,然后再取树的根节点与最后一个点交换,依次类推……
代码如下:
#include <stdio.h> #include <stdlib.h> void Heapadjust(int *arr, int parent, int cnt) { int child; int ValParent; for(ValParent = arr[parent]; 2 * parent + 1 < cnt; parent = child) { child = 2 * parent + 1; //父节点的左子节点 //右子节点存在且大于左子节点,则child+1 if(child + 1 < cnt && arr[child] < arr[child + 1]) { child++; } //若子节点大于根节点,则把子节点的值赋给根节点,否则跳出循环;跳出循环的原因是: //既然是从最后一个父节点开始往前构大根堆,如果父节点满足大根堆,那其子节点也满足大根堆 if(arr[child] > arr[parent]) { arr[parent] = arr[child]; } else { break; } //没有跳出循环说明,父节点与子节点值交换了,那有可能会导致大根堆被破坏,所以要检查子节点 //是否还是大根堆 arr[child] = ValParent; } } void Swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; } void HeapSort(int *arr, int cnt) { int iter = 0; //初始化大根堆,根据大根堆的特征,可以减少判断的次数 for(iter = cnt / 2 - 1; iter >= 0; iter--) { Heapadjust(arr, iter, cnt); } //大根堆的第一个数是最大的,将它与数组最后一个数作交换,每次交换都前移数组的尾数索引 //交换过程中可能会导致大根堆遭破坏,所以要调用Heapadjust(arr, 0 , iter)构建大根堆 //由于前面已经初始化大根堆,所以已经具备大根堆的特征,不需要再一个一个父节点的慢慢构建 //只需要将Heapadjust的第二个参数设置为0,即大根堆的第一个父节点即可 for(iter = cnt - 1; iter >= 0; iter--) { Swap(&arr[0], &arr[iter]); Heapadjust(arr, 0 , iter); } } int main(void) { int arr[] = {3, 2, 1, 4, 5 ,7 ,6, 12, 34, 34 ,56}; int len = 11; HeapSort(arr, len); int i = 0; for( i = 0; i < len; i++) { printf("%4d",arr[i]); } return 0; }