正式找工作第二天

作者: 一路不向西 | 来源:发表于2019-08-27 23:40 被阅读0次

    这两天生物钟差不多调过来了,已经能正常按时早起,按时午休,身体出现的不适感也没有很多。今天在看书的时候感觉PRML对我来说还是有些太难了,很多公式和推导其实都看不懂,所以感觉不太适合现在的阶段去看,暂时先不想调整,看这周的面试情况吧。做题的话今天感觉比昨天顺畅一点了,但是还是没法得到正确解,慢慢来吧。


    一、PRML

    今天看了第一章的第六节,信息熵。讲了一些信息量的概念、平均信息量、乘数等等。对于离散变量,最大的熵值产生于均匀分布,对于连续变量,最大的熵值产生于高斯分布。还讲了相对熵和互信息的概念。
    第二章就开始讲各种概率分布了,各种公式真的爆炸多,我觉得基本的思路就是先讲概率密度函数,然后是均值、方差、似然估计,从伯努利分布到Beta分布再到高斯分布,都差不多的思路。今天看到高斯分布的最大似然估计部分,明天继续。

    二、LeetCode

    17# 电话号码的数字组合

    这个题目的意思就是要写出所有数字代表的字母的排列组合,可以抽象出来是求几个字符串的单字母排列组合。所以先要有一个字典存放数字对应的字符串。然后先取出第一个数字对应的所有字母,构成一个列表,然后从第二个数字开始,将它对应的所有字母与上一个列表里的所有元素进行拼接,比如第一个数字是2,那开始的类别是['a','b','c'],第二个数字是3,对应的是def,那现在的结果就是把d、e、f分别和abc拼,得到['ad','ae','af','bd','be','bf','cd','ce','cf'],之后都是用当前数字对应的所有字母与之前的结果进行拼接。

    19# 删除链表的倒数第N个节点

    这个题目的一种解法是,选择两个指针,fast和slow,先让fast指针前进n步,这时候fast和slow再同时出发,fast到达最后的时候slow指向的就是要删除的节点。这里有两点要注意的,一个是如果要删除的是第一个元素,要单独考虑,因为到fast走了n步的时候,最后一次执行fast=fast.next已经把fast指向最后一个值的next了,所以这时候如果fast为None,说明已经走到最后了,要删除的就是第一个元素,那么令head= head.next就可以了。另一点是最终fast和slow停下以后,slow停的位置就是要删除的节点,所以循环之后用slow.next = slow.next.next就是完成了删除操作。

    22# 括号生成

    括号生成用到了递归的方法,大致的意思是如果左括号还有剩余,那就把字符串加上左括号,然后递归,同时把左括号数量减去1,下一步如果右括号还有剩余,这时候要判断右括号的数量是不是小于左括号,如果是,就把右括号加上,并进行递归。我觉得递归还挺难懂的,就直接上代码吧。

    class Solution(object):
        def generateParenthesis(self, n):
            """
            :type n: int
            :rtype: List[str]
            """
            self.res = []
            self.generateParenthesisIter('', n, n)
            return self.res
        
        def generateParenthesisIter(self, mstr, l, r):
            if l == 0 and r == 0:
                self.res.append(mstr)
                return
            # 如果左括号还有剩余,加上左括号然后递归
            if l > 0:
                self.generateParenthesisIter(mstr+'(', l-1, r)
            # 如果右括号还有剩余,且目前右括号的数量小于左括号的,也就是
            # 剩余的r比剩余的l大,那么就加右括号然后递归
            if r > 0 and r>l:
                self.generateParenthesisIter(mstr+')', l, r-1)
    

    29# 两数相除

    这个题目首先要确定符号,然后把dividend和divisor都取绝对值,然后就是用dividend减去除数,当然这样的话时间会超时,所以做了一个改进就是先用divisor去减,然后在内层循环去给divisor左移一位,也就相当于2倍,加快减的过程。如果减的多了,再回到外循环,重新减divisor,而且i可以控制是减去了divisor的几倍。最后也上下代码吧。

    class Solution(object):
        def divide(self, dividend, divisor):
            """
            :type dividend: int
            :type divisor: int
            :rtype: int
            """
            flag = (dividend < 0) is (divisor < 0)
            
            num = 0
            dividend, divisor = abs(dividend), abs(divisor)
            
            while dividend >= divisor:
                tmp, i = divisor, 1
                while dividend - tmp >= 0:
                    dividend -= tmp
                    num += i
                    i <<= 1
                    tmp <<= 1
            if not flag:
                num = -num
            
            return min(2147483647, max(num, -2147483648))
    

    33# 搜索旋转排序数组

    这个题目我之前面试遇到过,所以大概知道思路,没想到写的时候还是翻了下车。因为数组是升序的,旋转之后就分成了两段升序的。因为是搜索的题目,所以我们可以考虑到用二分,但是往哪边分就是个问题了。解决的思路是这样的,用中间的元素跟最右边的元素比,如果比最右边的大,那左半边一定是有序的,反推很容易得到这个结论。那这样的话就可以判断target是不是在left和mid之间,如果是,就在左边二分,如果不是就在右边二分。同样的,如果中间的值右边的小,那么右半边一定是有序的,后面就跟上面类似了。

    35# 在排序数组中查找元素的第一个和最后一个位置

    题目时间复杂度的要求可以看出是要用到二分了,那分的关键就是要先不断二分,直到找到一个等于target的值,然后从这个位置开始,left和right指针合并,然后往前后两个方向走,直到出现不是target的位置,那就可以分别确定第一个和最后一个的位置了。

    写在最后:要写这么一段博客真的好不容易啊,要理清楚这些题目更是不容易,现在的阶段还仅仅是能把别人的思路看懂,实现一下,还总是出错,相信自己多多实践,也能自己写出来的,加油!

    相关文章

      网友评论

        本文标题:正式找工作第二天

        本文链接:https://www.haomeiwen.com/subject/ybzyectx.html