头像

coorch

深研院


访客:623

离线:1天前



coorch
2天前

二面

还是牛客网的视频面。

先自我介绍,然后做题。

算法部分

有序数组的平方

一道leetcode的简单题, 997.有序数组的平方
加了一个不能重复的条件。

首先给出了简单粗暴的哈希表去重+排序的方法;
然后指出这个方法没有用到原本的数组就是有序的这个性质,可以用二分找到第一个大于等于0的位置,然后对左右两边分别处理;写了二分的代码;
面试官问我有没有不用二分的方法,当时没转过来弯,其实可以直接双指针来着。
相当于是两个有序数组的合并;

两个有序数组求交集

可能是看我没转过来双指针的弯,进一步提示。
给出了双指针的思路以及代码。

m个有序数组求交集

我给了两个思路:一种是先求前两个的交集,然后求交集与下个数组的交集,以此类推;
还有一种是设置m个指针指向这m个数组,每次最大的那一个(或几个)指针不动,其他指针右移。
面试官主要让我写了第二种思路的代码,然后分析复杂度。

其他问题

卷积有几种padding方法?
resNet解决了什么问题?
为什么会出现梯度消失或梯度爆炸?
梯度消失或梯度爆炸还有什么其他的方法可以解决?




coorch
3天前

起初是看到一个在华为云的师兄发的朋友圈,然后上周三联系了他发了简历,本来想投CV,他说CV没有坑位,后来就让帮忙投到nlp;

一面(电话面)

然后第二天下午,华为就打电话面了一下(其实上午就打了,但是当时手机调静音没接到,纠结了很久是否还会再打呢)

这个电话貌似就是一面了,让我自我介绍,然后简单介绍了项目,不过因为项目确实很烂,而且关系也不大,没花多长时间。不过面试官真的有耐心,各种找话题问,甚至还问了Leetcode刷了几题,平时看了哪些技术博客公众号啥的。

强行尬聊了30多分钟结束,话说我当时还在开组会来着,这个面试确实挺突然的。

二面(终面、zoom视频面)

接着这周一,这个部门的一个小哥加了我微信,问我能不能从事一些nlp偏开发类的工作,刚好不久前看了y总的分享,果断回复没问题。就在昨天,hr小姐姐打电话约今天下午5点面试,尴尬的是,第一次打的电话又没接到。电话打得也很有效率,先通知我一面过了,安排今天终面是否可以;然后说了一下终面的时间就挂了。之后发了面试邮件,有zoom的房间号。

面试官小哥哥很敬业,我本来想着提前10分钟进来先调试准备一下,没想到一进来发现他已经在了;不过刚开始听不到他那边的声音,调通了以后面试就开始了。

首先是自我介绍,然后问了一下基本情况,什么时候毕业?能实习多久?之后的职业规划是怎么打算的?常用的语言是什么?之前有没有做一些偏工程的小项目?代码量有多少?

然后就让打开IDE,共享屏幕,写写代码。

题目是两个无序的数组,返回他们的中位数,这个中位数是指两个数组中所有数据排序之后中间的数或中间两个数的平均。
其实可以理解为,将两个数组合并后,对新数组的topK问题。不过当时有点紧张,第一次用自己的IDE在其它人面前写代码,纠结了半天,是用快排呢还是堆排。
面试官看我几分钟都没怎么写就让我说说思路,我就说了堆排的思路,然后他说其实简单的想法就是对合并的数组排序后取第k个,如果考虑优化那就要用到堆排这些了。

最后问我有没有啥问题,我就问了下如果去实习要做些什么工作,他简单介绍了一下,面试就结束了。

总结

我这两面都有点突然,面的时候有点紧张。特别是二面做题,现在反思感觉面试官是想考察一下我的代码能力,没get到点,其实直接排序几行就解决了。而且想的时候也没怎么和面试官沟通,不确定是否可以直接将二者合并然后直接排序。

做题的时候和面试官及时交流确实很重要,有不太清楚的就大胆去问,不要自己在心里纠结。其实我如果问清楚了,先把合并排序的代码快速写出来,然后慢慢优化,肯定比我心里默默纠结然后犹犹豫豫最后啥也没写出来好多了。

现在就是马后炮一下,告诫自己下次面试要注意,也希望我的这波错误经验分享能够提醒到有需要的同学。不过看过再多经验终究是不够深刻,自己踩了一下才真的是印入骨髓,总之还是要多多去面试,积累经验。




coorch
8天前

一面

视频面,下午3点开始,时间45分钟。
第一次用牛客的系统,本来提前进去了,等到时间了发现面试官一直没进来;然后面试官给我打了电话,问我知不知道现在面试,尴尬😅。
之后把那个界面刷新一下就好了。
首先是自我介绍,介绍差不多,面试官说可以了,简历已经看完了。
然后直接开始做题,一共两道算法题。

算法部分

第一题

用两个栈实现队列

剑指offer原题,AcWing上的第20题。
思路就是一个栈用来实现入队,另一个栈来实现出队。
不要求跑通,边写边讲思路,很快就写出来了。

第二题

acwing1612. 最大正方形
一开始没什么思路,后来面试官提示,先考虑一维的情况;
一维的时候就是 Leetcode45 最大连续1的个数
想到用动态规划的方法来解;然后类推到二维的情况,最后面试官就让把状态转移方程写出来就好。

基础知识

TCP和UDP
进程、线程、协程这些
最后问机器学习的模型如何判断其性能。讲到了交叉熵和AUC。

一面结束后不到一小时,hr来商量二面的时间,让我多准备一下CS基础和机器学习基础,可能是自己在这部分答得确实不太好。

二面

还是牛客网的视频面。

先自我介绍,然后做题。

算法部分

有序数组的平方

一道leetcode的简单题, 997.有序数组的平方
加了一个不能重复的条件。

首先给出了简单粗暴的哈希表去重+排序的方法;
然后指出这个方法没有用到原本的数组就是有序的这个性质,可以用二分找到第一个大于等于0的位置,然后对左右两边分别处理;写了二分的代码;
面试官问我有没有不用二分的方法,当时没转过来弯,其实可以直接双指针来着。
相当于是两个有序数组的合并;

两个有序数组求交集

可能是看我没转过来双指针的弯,进一步提示。
给出了双指针的思路以及代码。

m个有序数组求交集

我给了两个思路:一种是先求前两个的交集,然后求交集与下个数组的交集,以此类推;
还有一种是设置m个指针指向这m个数组,每次最大的那一个(或几个)指针不动,其他指针右移。
面试官主要让我写了第二种思路的代码,然后分析复杂度。

其他问题

卷积有几种padding方法?
resNet解决了什么问题?
为什么会出现梯度消失或梯度爆炸?
梯度消失或梯度爆炸还有什么其他的方法可以解决?




coorch
15天前
class Solution:
    def countRoutes(self, locations: List[int], start: int, finish: int, fuel: int) -> int:
        # 通过将dfs的思路转化为dp,类似记忆化搜索
        n = len(locations)
        dp = [[0] * n for _ in range(fuel + 1)]
        # dp[i][j]表示从j地出发,到finish,拥有汽油为i时的方案数
        for i in range(fuel+1):
            for j in range(n):  
                # j就是finish,呆在原地就是一条路          
                if j == finish:
                    dp[i][j] = 1
                # 类似于dfs,
                # 因为每个城市可以经过多次,所以只要还有油,就可以继续去除了j之外的任意位置
                # 下一次去k地,汽油还剩i-abs(locations[k] - locations[j]),
                for k in range(n):
                    if k != j:
                        dis = abs(locations[k] - locations[j])
                        if i - dis >= 0:
                            dp[i][j] += dp[i-dis][k]


        return dp[fuel][start] % (10**9+7)



coorch
15天前
class Solution:
    def minCost(self, s: str, cost: List[int]) -> int:
        n = len(s)
        res = 0
        for i in range(1, n):
            if s[i] == s[i-1]:
                res += min(cost[i], cost[i-1])
                cost[i] = max(cost[i], cost[i-1])
        return res



coorch
15天前
class Solution:
    def numTriplets(self, nums1: List[int], nums2: List[int]) -> int:
        nums1.sort()
        nums2.sort()
        ans = 0

        m, n = len(nums1), len(nums2)
        dict1 = {}

        for j in range(n-1):
            for k in range(j+1, n):
                temp = nums2[j] * nums2[k]
                if temp not in dict1:
                    dict1[temp] = 0
                dict1[temp] += 1
        for i in range(m):
            if nums1[i] * nums1[i] in dict1:
                ans += dict1[nums1[i] * nums1[i]]

        dict1 = {}
        for j in range(m-1):
            for k in range(j+1, m):
                temp = nums1[j] * nums1[k]
                if temp not in dict1:
                    dict1[temp] = 0
                dict1[temp] += 1
        for i in range(n):
            if nums2[i] * nums2[i] in dict1:
                ans += dict1[nums2[i] * nums2[i]]

        return ans



coorch
15天前
class Solution:
    def modifyString(self, s: str) -> str:
        n = len(s)
        var = "abcdefghijklmnopqrstuvwxyz"
        ans = []

        for i in range(n):
            if s[i] == '?':
                used = set()
                if i > 0 and ans[-1] != '?':
                    used.add(ans[-1])
                if i < n-1 and s[i+1] != '?':
                    used.add(s[i+1])
                for c in var:
                    if c not in used:
                        ans.append(c)
                        break
            else:
                ans.append(s[i])

        return ''.join(ans)



coorch
17天前
class Solution:
    def findLengthOfShortestSubarray(self, arr: List[int]) -> int:
        # 也就是要找到最长的非递减序列
        # 并且因为删除的是连续子数组,所以这个非递减序列一定是以第一个元素开头或以最后一个元素结尾的


        # 分别找到左右两侧的非递减序列

        # 从第0个元素开始的非递减:arr[:l+1]
        l = 0
        n = len(arr)
        for i in range(1, n):
            if arr[i] >= arr[i-1]:
                l += 1
            else:
                break

        # 以第n-1个元素结尾的非递减:arr[r:]
        r = n-1
        for i in range(n-2, -1, -1):
            if arr[i] <= arr[i+1]:
                r -= 1
            else:
                break

        if l >= r:
            return 0

        # 右序列都选arr[r:],左序列取不大于右序列最后一个元素的部分
        r_l = n-r
        for i in range(l+1):
            # 从第0位开始,只要不大于arr[r],这部分就可以合并到右序列中
            if arr[i] <= arr[r]:
                r_l += 1
            else:
                break

        # 左序列都选,右序列取不小于左序列最后一个元素的部分
        l_r = l+1
        for i in range(n-1, r-1, -1):
            if arr[i] >= arr[l]:
                l_r += 1

        return n - max(l_r, r_l)





coorch
17天前
class Solution:
    def numWays(self, s: str) -> int:
        one_count = 0
        n = len(s)

        for c in s:
            if c == '1':
                one_count += 1

        if one_count == 0:
            return int((n-1) * (n-2) // 2 % (1e9 + 7))

        if one_count % 3 != 0:
            return 0

        fir = one_count // 3
        sec = 2 * fir
        one_count = 0
        for i in range(n):
            if s[i] == '1':
                one_count += 1
                if one_count == fir:
                    f1 = i
                if one_count == fir + 1:
                    f2 = i
                if one_count == sec:
                    s1 = i
                if one_count == sec + 1:
                    s2 = i

        return int((f2 - f1) * (s2 - s1)  % (1e9 + 7))



coorch
17天前
class Solution:
    def diagonalSum(self, mat: List[List[int]]) -> int:
        n = len(mat)
        ans = 0
        for i in range(n):
            ans += mat[i][i]
            if n-1-i != i:
                ans += mat[i][n-1-i]

        return ans