算法学习笔记(一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wen_fei/article/details/82934536

算法笔记(一)

一 什么是正确的回答一个算法问题

 回答一个算法问题,并不是一下子回答出来一个解决方案,而应该是和面试官探讨的过程,在探讨过程中逐渐选择一个最优方案

对一组数据进行排序

这组数据有什么样的特征?

  • 有没有包含大量重复的元素? 如果有,三路快排
  • 是否大部分数据距离它的正确位置很近?即是否近乎有序?插入排序最好
  • 取值范围是否有限?比如对学生成绩排序,这样计数排序更好

有什么额外要求?

  • 是否要求稳定排序? 如果是,快排不好,归并排序是更好的选择

数据的存储状态是怎样的?

  • 快排等算法依赖数组的随机存取的特征,如果数据存储在链表中,快排不适用,归并排序更好
  • 数据的大小是否可以装载在内存里?如果数据很大,或者内存很小,不足以装载到内存,需要使用外排序算法或者对数据进行转换,比如bitmap算法
即便一个问题一时回答不上来,也应该积极给出一个方向,让面试官知道所做出的努力和思考

二、算法面试优秀不意味着技术面试优秀

项目经历和项目中遇到的实际问题,考察做项目时是仅仅为了达到要求,还是自己进行了深入的思考

你遇到的印象最深的bug是什么?

面向对象

设计模式

网络相关;安全相关;内存相关;并发相关;

系统设计;scalability(系统在大规模使用时可能遇到的问题)

三、技术面试优秀不等于offer

经常会问其他问题,与人的交流合作、个人思考问题的方式、生活习惯、思维模式、价值观、对公司的了解等等

  • 遇到的最大挑战是什么?
  • 你是怎么解决xxxx的?
  • 遇到xxx你会xxx?
  • 你有什么要问面试官的?

四、如何准备算法面试?

算法导论

完全没必要那么大,如果喜欢读,必须有选择的读,跳过理论推导,记住结论即可,后面再回过来慢慢看

五、面试中的时间复杂度

时间复杂度

是一个近似,也跟指令条数有关。假如一个算法的时间复杂度是O(n),那么其执行时间是aO(n),前面是一个固定的常数,代表指令条数。

对于时间复杂度的对比,一定要注意是否在相同数据规模下,否则是没有意义的。

数据规模的概念

如果想要在1s之内解决问题:

  • O(n2)的算法可以处理大约104级别的数据
  • O(n)的算法可以处理大约10^8级别的数据
  • O(nlogn)的算法可以处理大约10^7级别的数据

这个数据是在仅进行简单的加法操作的情况下得出的,保险起见,可以再除以10

空间复杂度

多开一个辅助数组: O(n)

多开一个辅助的二维数组:O(n^2)

多开常数空间:O(1)

注意:递归调用是有空间代价的,其跟递归的深度有关,需要在系统栈中存入状态

时间复杂度分析

一般的时间复杂度都要从代码层面去分析,在有循环的代码里,一定要注意循环的上下界,举个例子:

 for (i = 0; i < n; i++) 
    for (j=0; j < 30; j++)
        swap(a, b);

这里虽然是两重循环,但里面的循环只循环了30次,外层循环n次,总共30n次,时间复杂度是O(n)

摊还分析

举个例子,构建一个动态数组,在数组元素个数达到数组容量时进行扩容

void push_back(T value) {
    if (size == capacity)
        resize(2 * capacity)
    data[size++] = value;
}

void resize(int newCapacity) {
    T* newData = new T[newCapacity];
    for (int i =0; i < size; i++)
        newData[i] = data[i];
    delete *data;
}

这里的代码,增加一个元素,时间复杂度是O(1),但里面增加了一个resize操作,resize的操作时间复杂度是O(n),那么,push_back的事件复杂度是多少呢?

这里应该还是O(1),具体分析来说,每增加一个元素时O(1),当增加到满的时候,此时进行了n次O(1),进行扩容,也是O(n),一共O(2n),一共n次操作,平均下来每次为O(2),还是O(1)

复杂度震荡问题

在动态数组实现中,有这样一种实现,增加元素时,每次元素个数达到数组容量的1/2便进行扩容。同时,在删除元素时,每次元素个数得到1/2时,进行数组容量缩减,这样存在一种极端情况:增加一个元素,进行了扩容,时间复杂度是O(n),扩容之后立马删除元素,又要对数组进行缩减,时间复杂度也是O(n),这样操作便退化了,造成了复杂度震荡。

猜你喜欢

转载自blog.csdn.net/wen_fei/article/details/82934536