实习整理(十一)

来源:互联网 发布:低学历 知乎 编辑:程序博客网 时间:2024/05/21 08:47
6.最长公共子序列和最长公共子串都可以用动态规划的方法来解决,递归的方式如下:
最长公共子序列  L[i][j] = (s[i]==t[j]) ? L[i-1][j-1] + 1:max(L[i-1][j],L[i][j-1])    L[i][j] ---- 子序列X1...Xi和子序列Y1...Yj的最长公共子序列的长度  数组下标从1开始 ,如果下标从0开始,就类似于下面这样

最长公共子串  L[i][j] = (s[i]==t[j]) ? L[i-1][j-1] + 1:0     L[i][j] ---- 子序列X1...Xi和子序列Y1...Yj的最长公共子串的长度
数组下标也是从1开始,如果下标从0开始,就类似于这样

动态规划的时间复杂度:O(n*2)  空间复杂度:O(n*2)
典型的以空间换时间的做法
连续子串:和最大  乘积最大(动态规划)
子序列:和最大  乘积最大
 

7.二叉树可以有许多种算法题,感觉基本上是可以用递归解决的,递归出口可以考虑根节点的情况,递归体一般就是递归左子树,递归右子树,当然有许多的细节还是要注意的,递归虽然从思想上来说比较简洁,但它需要额外的空间存储中间的临时数据,因此空间效率比较低,以LCA(最低公共祖先)问题为例
如果是二叉查找树,则只需要判断根节点和两个节点之间的大小关系,若根节点的值大于节点的值,则节点就在根节点的左子树中,之后递归左子树进行判断;若根节点的值小于节点的值,则节点就在根节点的右子树中,之后递归右子树进行判断;若根节点的值在两个节点值的中间,则两个节点的最低公共祖先为根节点
如果是一般的二叉树,则先判断两个节点是否在同一边,如果不在,则最低祖先为根节点,如果都在左边,则递归左子树,判断两个节点在左子树的情况,如果都在右边,则递归右子树,判断两个节点在右子树的情况
更多有关二叉树的面试题可以参考:http://blog.csdn.net/luckyxiaoqiang/article/details/7518888

8.求连续子数组之和
我觉得把握两个重点即可:1.若累加和<0,则累加和清0;2.若累加和大于当前的最大值,则最大值重新赋值为累加和

9.求一个数组中最小的k个元素
之前我自己的思路就是:1.堆排序的方法:将n个元素建堆(小堆),输出堆顶元素,接着调整堆,输出堆顶元素...O(klogn+n)
                                    2.快速排序的方法:以第一个元素作为主元,找到主元所在的位置,如果为m,若m=k,则输出前面k个元素;若m>k,则在前m个元素继续寻找排序后主元位置为k的元素,若m<k,则在后半部分的元素中继续寻找排序后主元位置为k-m的元素

但在网上看到其他的解决方法,我觉得比较可取的方法有先遍历前k个元素,找出k个元素中最大的元素kmax,之后将剩下的元素和kmax进行比较,若大于,则替换,否则不做任何操作,时间复杂度为O(n*k)
此外,研究者的博客说快速选择的方法可以使时间复杂度达到O(n),基本思想就是快速排序,只是主元的选取要随机或者主元为中位数,大概看了下,写的有点有点杂,不知道正确与否

10.关于字符的算法问题有一个比较好的想法,不考虑空间复杂度的话,比如说查找两个字符串中公共的字符,或者删除某字符串中出现在另一字符串中的字符等等,可以考虑这样做:
借助一个字符数组,因为字母就26或者52个,所以数组为25或者52个单元
还发现另外一种比较有意思的做法,就是将其中一个字符串映射成某一个素数,所有的字符都进行完如上操作后,将字符映射后的素数相乘,对另一个字符也进行素数映射,然后用前面一个字符串映射之后的乘积除以另一个字符串中的每一个字符,若余数为0,则该字符为公共字符,否则,不是。。。。思想很巧妙

11.再一次发现自己思维愚笨,一个问题有多种思路,所以要开拓思维(亲和数的求解过程就证明了思维真的很重要。。而我还是太笨了)
比如求两个日期之间相差的天数,我第一直觉就是去判断这两个日期年,月,日的大小,然后相减什么的,虽然这样也做得出,而且实现也并不复杂,但是很明显感觉复杂化了,其实只要找一个标准点,将这两个时间都与标准点进行比较,就能很明显的判断出他们的间隔了

12.寻找水王的变型题:出现次数等于数组一半的元素,那就可以将最后一个数去掉,这样就变为寻找水王的题,就可以用candidate和次数两个变量判断

13.翻转可以不改变数组的原有顺序,很多问题可以借助于这一点

从这些算法的思考过程当中学习到了一定那就是很多时候要学会去简化问题,我觉得自己在这一点上做的很不好,思维也跟不上,因此,还是需要多多锻炼了。。。
未完待续。。。


0 0
原创粉丝点击