1,快速排序
題目形式:手寫一下快速排序算法。
題目難度:中等。
出現概率:約50%。手寫快排絕對是手撕代碼面試題中的百獸之王,掌握了它就是送分題,沒有掌握它就是送命題。
參考代碼:
def quick_sort(arr,start=0,end=None):
if end is None:
end = len(arr)-1
if end<=start:
return(arr)
i,j = start,end
ref = arr[start]
while j>i:
if arr[j]>= ref:
j = j - 1
else:
# 此處使用一行語句交換3個元素的值
arr[i],arr[j],arr[i+1] = arr[j],arr[i+1],arr[i]
i = i + 1
quick_sort(arr,start=start,end = i-1)
quick_sort(arr,start=i+1,end = end)
return(arr)
print(quick_sort([1,1,3,3,2,2,6,6,6,5,5,7]))
輸出結果:
[1, 1, 2, 2, 2, 3, 5, 5, 6, 6, 6, 7]
2,二分查找
題目形式:手寫一下二分查找算法。給定一個有序數組 arr 和一個目標元素 target ,返回該 target 在 arr 中的索引,若不存在,返回-1。
題目難度:簡單。
出現概率:約30%。二分查找絕對是手寫代碼題中的百獸之后,沒有妃子可以和她爭寵。連個二分查找都寫不出來,還來應聘程序員,你是不是對程序員這個職業有什么誤解?
參考代碼:
nums = [1, 2, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 10, 11, 11, 11,
11, 12, 13, 13, 15, 16, 16, 20, 21, 21, 23, 24, 26,
26, 27, 28, 28, 31, 33, 33, 34, 35, 38, 38, 39, 40,
42, 43, 45, 45, 46, 46, 47, 47, 51, 52, 52, 53, 53,
55, 55, 56, 56, 57, 57, 57, 58, 59, 61, 62, 64, 66,
66, 67, 68, 69, 69, 71, 72, 72, 74, 74, 75, 76, 78,
78, 79, 79, 79, 79, 80, 82, 85, 88, 89, 90, 90, 91,
91, 91, 94, 99, 99]
def find(num,nums):
mid = len(nums) // 2
if nums[mid] > num:
nums = nums[0:mid]
print(nums)
find(num, nums)
elif nums[mid] < num:
nums = nums[mid+1:]
print(nums)
find(num, nums)
else:
print('找到了')
print(nums[mid])
return nums[mid]
find(40,nums)
輸出結果:
- [1, 2, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 10, 11, 11, 11, 11, 12, 13, 13, 15, 16, 16, 20, 21, 21, 23, 24, 26, 26, 27, 28, 28, 31, 33, 33, 34, 35, 38, 38, 39, 40, 42, 43, 45, 45, 46, 46, 47]
[21, 23, 24, 26, 26, 27, 28, 28, 31, 33, 33, 34, 35, 38, 38, 39, 40, 42, 43, 45, 45, 46, 46, 47]
[38, 38, 39, 40, 42, 43, 45, 45, 46, 46, 47]
[38, 38, 39, 40, 42]
[40, 42]
[40]
找到了
40
3,爬樓梯
題目形式:有一個樓梯,總共有10級台階,每次只能走一級或者兩級台階,全部走完,有多少種走法?
題目難度:簡單。
出現概率:約20%。爬樓梯問題是手寫代碼題中的百獸之豹。爬樓梯問題可以用遞歸來解決,但是如果考慮到時間復雜度,最好用動態規划的思想來處理,這是一個動態規划算法的教科書級別的案例。連個樓梯都爬不明白,這個算法基礎令人堪憂啊!
參考代碼:
def climb_stairs(n):
if n==1:
return 1
if n==2:
return 2
a,b = 1,2
i = 3
while i<=n:
a,b = b,a+b
i +=1
return b
print(climb_stairs(10)) ## 也就是斐波那契數組
輸出結果:
89
4,兩數之和
題目形式:尋找列表中滿足兩數之和等於目標值的元素的下標。例如:arr = [2,7,4,9],target = 6 則返回 [0,2],若不存在,返回空列表[]。
題目難度:簡單。
出現概率:約20%。兩數之和是手寫代碼題中的百獸之狼。兩數之和問題考察候選人對哈希表可以用空間換取時間這個特性的理解。哎呦喂,寫個兩數之和還整上兩重循環了,你這時間復雜度是多少啊?
參考代碼:
def twoSum(self, nums: List[int], target: int) -> List[int]:
for i in range(len(nums)):
res = target - nums[i]
if res in nums and nums.index(res) != i:
return [i,nums.index(res)]
輸出結果:
(0, 2)
5,最大回撤
題目形式:有一個數組,求其中兩個數x,y,滿足x的索引小於y的索引,使得 x-y 最大。例如 arr = [3,7,2,6,4,1,9,8,5], 最大回撤是6,對應的x=7,y=1。
題目難度:中等。
出現概率:約20%。這道題目可能以買賣股票的最佳時機,或者最大抬升等各種形式出現,這也是一道動態規划的史詩級范例。呦呵,又整上兩重循環了,這循環寫的很可以啊。
參考代碼:
def max_drawdown(arr):
assert len(arr)>2, "len(arr) should > 2!"
x,y = arr[0:2]
xmax = x
maxdiff = x-y
for i in range(2,len(arr)):
if arr[i-1] > xmax:
xmax = arr[i-1]
if xmax - arr[i] > maxdiff:
maxdiff = xmax - arr[i]
x,y = xmax,arr[i]
print("x=",x,",y=",y)
return(maxdiff)
print(max_drawdown([3,7,2,6,4,1,9,8,5]))
輸出結果:
x= 7 ,y= 16
6,合並兩個有序數組
題目形式:給定兩個按升序排列的有序數組,將它們合並成一個新的有序數組。例如:a = [1,2,6,8], b = [2,4,7,10],輸出為 arr = [1,2,2,4,6,7,8,10]
題目難度:簡單。
出現概率:約15%。這道題目考察的是歸並排序的基本思想。注意,這兩個數組是有序的呢,你怎么可以無視這么有利的條件直接拼接上兩個數組開始冒泡了???
參考代碼:
def merge_sorted_array(a,b):
c = []
i,j = 0,0
while True:
if i==len(a):
c.extend(b[j:])
return(c)
elif j==len(b):
c.extend(a[i:])
return(c)
else:
if a[i]<b[j]:
c.append(a[i])
i=i+1
else:
c.append(b[j])
j=j+1
print(merge_sorted_array([1,2,6,8],[2,4,7,10]))
輸出結果:
[1, 2, 2, 4, 6, 7, 8, 10]
7,最大連續子數組和
題目形式:給定一個數組,求其最大連續子數組的和。例如:arr = [1,5,-10,2,5,-3,2,6,-3,1]. 輸出為:12。對應的連續子數組為 [2,5,-3,2,6]。
題目難度:中等。
出現概率:約15%。這道題目也是一道動態規划的祖傳范例。同學,你的這個兩重循環寫的確實很6,但是我們不能認為你的這道題目做對了!
參考代碼:
def max_sub_array(arr):
n = len(arr)
maxi,maxall = arr[0],arr[0]
for i in range(1,n):
maxi = max(arr[i],maxi + arr[i])
maxall = max(maxall,maxi)
return(maxall)
print(max_sub_array([1,5,-10,2,5,-3,2,6,-3,1]))
輸出結果:
12
8,最長不重復子串
題目形式:給定一個字符串,找出沒有重復字符的最長的子串。例如輸入“abcbefgf”,答案是 “cbefg”。
題目難度:困難。
出現概率:約10%。這是一道動態規划+哈希查找的綜合應用題。這道題能做出來,你的代碼功底很可以啊。對了,你的期望薪資是多少?
參考代碼:
def longest_substr(s):
dic = {}
start,maxlen,substr = 0,0,""
for i,x in enumerate(s):
if x in dic:
start = max(dic[x]+1,start)
dic[x] = i
else:
dic[x] = i
if i-start+1>maxlen:
maxlen = i-start+1
substr = s[start:i+1]
return(substr)
print(longest_substr("abcbefgf"))
print(longest_substr("abcdef"))
print(longest_substr("abbcddefh"))
輸出結果:
cbefgabcdefdefh
9,全排列
題目形式:給定一個數組,找出其所有可能的排列。例如: arr = [1,1,3],輸出為 [[1,1,3],[1,3,1],[3,1,1]]。
題目難度:中等
出現概率:約10%。這是一道動態規划+排列組合的綜合應用題。同學,你這里用遞歸的話你的這個時間復雜度得有多少?我們這個數組一旦有幾十個元素的話,你這還能跑得動嗎?
參考代碼:
import numpy as np
def permutations(arr):
if len(arr)<=1:
return([arr])
t = [arr[0:1]]
i = 1
while i<=len(arr)-1:
a = arr[i]
t = [xs[0:j]+[a]+xs[j:] for xs in t for j in range(i+1)]
t = np.unique(t,axis=0).tolist()
i = i+1
return(t)
print(permutations([1,1,3]))
輸出結果:
[[1, 1, 3], [1, 3, 1], [3, 1, 1]]
10,三數之和
題目形式:給定一個數組和目標數target,找出數組中a,b,c滿足 a+b+c = target 的所有組合。例如:arr = [-3,-1,-2,1,2,3],target = 0。輸出為 [(-3,1,2),(-2,-1,3)]
題目難度:困難
出現概率:約5%。這是一道非常有技巧的題目。你可以嘗試先將arr排序。注意,我們的時間復雜度要求為O(n**2) ,空間復雜度要求O(1),對,就是這么嚴格,你要好好想想……喲,有思路啦……emmm……大體上符合要求……同學,你現在手上還有其他家的offer嗎?
參考代碼:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort()
res =[]
i = 0
for i in range(len(nums)):
if i == 0 or nums[i]>nums[i-1]: ## 這個一步很重要
l = i+1
r = len(nums)-1
while l < r:
s = nums[i] + nums[l] +nums[r]
if s ==0:
res.append([nums[i],nums[l],nums[r]])
l +=1
r -=1
while l < r and nums[l] == nums[l-1]: ## 優化
l += 1
while r > l and nums[r] == nums[r+1]: ## 優化
r -= 1
elif s>0:
r -=1
else :
l +=1
return res
輸出結果:
[(-2, -1, 3), (-3, 1, 2)]