两个list求和_Leetcode 之 求和问题

今天讲讲在第二次百度二面时遇到的一道编程题,确切的说是很多道一类题,他们都指向一个经典的数学问题,那就是——多数求和

概述:

回顾两次百度面试,面试官都极其重视编程题,最主要的原因可能是我是学机器学习,主攻领域是计算机视觉,但是百度面试官似乎不是来自这个领域,6个面试官似乎都不是很了解计算机视觉,而都是研究自然语言处理或者是搜索算法领域。所以在面试过程中,6位面试官都把精力编程题的考察上。

虽然自己两次面试都倒在了第三面的编程题上,但是整体面试过程自己受益匪浅,这里和大家分享一下第二次面试二面的编程题。

整个算法部分的考察,主要就围绕求和问题,主要有关LeetCode1,15,18,19,40题,涉及哈希表,双指针,回溯法等经典算法知识。面试过程中还反复问到时间复杂度和空间复杂度问题。

一.两数求和

面试官率先问我,Leetcode第一题:

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。

我内心窃喜,心想这也太简单了吧,这不就是leetcode第一题吗,用哈希表不就完事了,就觉得这二面也稳了。然后我就回答用哈希表,代码如下:

def two_sum(nums, target):
    dct = {}for i, n in enumerate(nums):
        cp = target - nif cp in dct:return [dct[cp], i]else:
            dct[n] = i

当然,面试官没有直接让我写代码,而是直接问我算法的复杂度,我会回答说,时间复杂度O(N),空间复杂度O(N)。

面试官接着问有没有空间复杂度为O(1)的方法,我当时想到本科老师提到的,“降低空间复杂度最无脑的办法就是提高时间复杂度”,我就懂了,要用暴力枚举的办法。

二.三数之和

题目简单,我从容应对,然而面试官继续刁难。改问我三数之和,leetcode第15题:

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。注意:答案中不可以包含重复的三元组。

当时刚刷完leetcode前50题,对第15题还是有印象的。记得是用双指针法。算法流程是,排序,遍历,双指针。代码如 下:
def threeSum(self, nums: List[int]) -> List[List[int]]:
        n=len(nums)
        res=[]if(not nums or n<3):return []
        nums.sort()
        res=[]for i in range(n):if(nums[i]>0):return resif(i>0 and nums[i]==nums[i-1]):continue
            L=i+1
            R=n-1while(L                if(nums[i]+nums[L]+nums[R]==0):
                    res.append([nums[i],nums[L],nums[R]])while(L1]):
                        L=L+1while(L-1]):
                        R=R-1
                    L=L+1
                    R=R-1
                elif(nums[i]+nums[L]+nums[R]>0):
                    R=R-1else:
                    L=L+1return res
时间复杂度为O(n*n),空间复杂度为O(1)。同样的leetcode18题,四数之和也是用相同的方法。

三.组合总数

在回答完双指针后,我觉得这次面试肯定成了。万万妹想到啊,面试官继续问我更难的求和问题。我以为他在第一层,我在第二层,没想到他已经在第五层等我了。这次是leetcode39:

给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。candidates 中的数字可以无限制重复被选取。说明:所有数字(包括 target)都是正整数。解集不能包含重复的组合。

 我回答说是,经典回溯法了。他终于让我开始编程了。代码如 下:
def combinationSum(self, candidates, target):
        candidates.sort()
        n = len(candidates)
        res = []
        def backtrack(i, tmp_sum, tmp):if  tmp_sum > target or i == n:return if tmp_sum == target:
                res.append(tmp)return for j in range(i, n):if tmp_sum + candidates[j] > target:break
                backtrack(j,tmp_sum + candidates[j],tmp+[candidates[j]])
        backtrack(0, 0, [])return res

四.组合总数II

顺利编程后,面试官赞赏地点了点头,却依旧不依不饶,继续问我leetcode40题:

给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。candidates 中的每个数字在每个组合中只能使用一次。说明:所有数字(包括目标数)都是正整数。解集不能包含重复的组合。

让我在原有的基础上改。同样的回溯法,代码 如下:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
        if not candidates:
            return []
        candidates.sort()
        n = len(candidates)
        res = []

        def backtrack(i, tmp_sum, tmp_list):
            if tmp_sum == target:
                res.append(tmp_list)
                return 
            for j in range(i, n):
                if tmp_sum + candidates[j]  > target : break
                if j > i and candidates[j] == candidates[j-1]:continue
                backtrack(j + 1, tmp_sum + candidates[j], tmp_list + [candidates[j]])
        backtrack(0, 0, [])    
        return res

五.小结

改完代码,和百度第二次二面面试官的斗智斗勇终于结束了。只感觉,面试如同比武论剑,一来一回,相互过招,不胜爽快。这次我们一次解决了面试会遇到的所有求和问题,涉及哈希表,双指针,回溯,剪枝等知识。小伙伴们都学会了吗~记得关注我们的公众号呀~~ e5a647f793fc7ba4d815fe547dd383e7.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值