Leetcode经典面试题 – 第2周
题目来源于Leetcode
报了一个百面机器学习面试的课程
每周都有定时打卡的作业
都是常出现于面试中的题
总结在此,时常温习,
刷题小能手们觉得写的不错可以移步个人主页
(ps:最近忙着笔试面试,更新太少)
1.二分(Leetcode 69)
Implement int sqrt(int x).
Compute and return the square root of x, where x is guaranteed to be a non-negative integer.
Since the return type is an integer, the decimal digits are truncated and only the integer part of the result is returned.
实现根号n的函数,保留整数位
Example 1:
Input: 4
Output: 2
Example 2:
Input: 8
Output: 2
Explanation: The square root of 8 is 2.82842…, and since
the decimal part is truncated, 2 is returned.
思路
题目要求二分法,有根区间初始化为(0,n)
根据左右区间的函数乘积小于0
可以不断缩小有根区间到一定的误差值范围
快捷的方法是牛顿迭代法
目标函数是
f
(
x
)
=
x
2
−
a
f(x)=x^{2}-a
f(x)=x2−a
利用泰勒公式展开得到公式
x
k
+
1
=
x
k
−
f
(
x
k
)
f
′
(
x
k
)
{x_{k + 1}} = {x_k} - \frac{{f({x_k})}}{{f'({x_k})}}
xk+1=xk−f′(xk)f(xk)
进一步得到
x
k
+
1
=
x
k
+
a
x
k
2
x_{k+1} =\frac{x_{k}+\frac{a}{x_{k}}}{2}
xk+1=2xk+xka的迭代公式
比二分更容易收敛。
class Solution(object):
def mySqrt_binary_search(self, x):
lo = 0
hi = x
while lo <= hi:
mid = lo + (hi - lo) >> 1
if mid ** 2 <= x < (mid+1) ** 2:
return mid
if mid ** 2 > x:
hi = mid
else:
lo = mid + 1
def mySqrt_newton(self, x):
"""
:type x: int
:rtype: int
"""
y = 1
while(1):
new = ((y)+(x/y))/2
if abs(new-y) < 0.0000001:
break
y = new
return int(y)
2.分治(Leetcode 241)
Given a string of numbers and operators, return all possible results from computing all the different possible ways to group numbers and operators. The valid operators are +, - and *.
给定了一串数字和运算符,返回所有可能的计算结果
Example 1:
Input: “2-1-1”
Output: [0, 2]
Explanation:
((2-1)-1) = 0
(2-(1-1)) = 2
Example 2:
Input: “23-45”
Output: [-34, -14, -10, -10, 10]
Explanation:
(2*(3-(45))) = -34
((23)-(45)) = -14
((2(3-4))5) = -10
(2((3-4)5)) = -10
(((23)-4)*5) = 10
思路
分治的基本思想:
将一个规模为N的问题分解为K个规模较小的子问题
这些子问题相互独立且与原问题性质相同
求出子问题的解,就可得到原问题的解
具体到这一题:
基本出口:碰到当前操作的数据是数字返回当前数字
基本流程:搜索运算符,左右分治,分别得到左边运算结果和右边运算结果,细分向下搜索到最后一个子问题,完成对应运算即可解决原问题。
class Solution(object):
def helper(self, a, b, op):
if op == '+':
return a + b
if op == '-':
return a - b
if op == '*':
return a * b
def diffWaysToCompute(self, input):
"""
:type input: str
:rtype: List[int]
"""
res = []
if input.isdigit():
return [int(input)]
for i in range(len(input)):
cur_op = input[i]
if cur_op in'+-*':
res1 = self.diffWaysToCompute(input[:i])
res2 = self.diffWaysToCompute(input[i+1:])
for j in res1:
for k in res2:
res.append(j, k, cur_op)
return res
以
2
×
3
−
4
×
5
2\times3-4\times5
2×3−4×5为例,结合上述完成的代码,整个分治的流程的详细走势,如下图所示:
总的来说,分治就是查找最小的一个子问题,这里最小的一个子问题就是,+/-/*运算,用helper这个函数来完成这些基本运算,不断的循环这个过程,在不断处理这些子问题的同时,原问题也得到解决,注意在编程过程中的list和int类型的相互转化。
3.链表(Leetcode 160)
Write a program to find the node at which the intersection of two singly linked lists begins.
写一个函数返回两个链表的交叉点,交叉点之后的元素都要相等,返回交叉点的值,都是图不方便插入,直接留下传送门
思路
设两个链表长度差为n,让两个指针指向两个链表,若两个链表有交集,长链表的指针到头之后指向短链表,短链表的指针到头后指向长链表,能够实现将长链表提前走过长度差n,这样当两个指针相等时,那个点就是交叉点。
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def getIntersectionNode(self, headA, headB):
if headA is None or headB is None:
return None
pa, pb = headA, headB
while headA is not headB:
if pa is None:
pa = headB
else:
pa = pa.next
if pb is None:
pb = headA
else:
pb = pb.next
return pa
4.哈希表(Leetcode 1)
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
给定一组数,返回和为指定数的两个数组中的数的索引
思路
遍历数组,对每一个遍历到的数,判断剩下的数中有没有target-current,有的话返回索引即可
class Solution:
def twoSum(self, nums, target):
d = {}
first = -1
second = -1
for i in range(len(nums)):
r = target - nums[i]
if r in d:
first = d[r]
second = i
d[nums[i]] = i
return first, second
5.字符串(Leetcode 242)
Given two strings s and t , write a function to determine if t is an anagram of s.
给定两个字符串s和t,判断他们是不是相同字母的不同的组合
思路
1.利用字典统计出现的字母及数量,判断两个字符对应的字典是否相等即可
2.直接排序,看是否相等即可
# 第1种方法:字典
class Solution(object):
def isAnagram(self, s, t):
d1, d2 = {}, {}
for i in s:
d1[i] = d1.get(i, 0) + 1
for i in t:
d2[i] = d2.get(i, 0) + 1
return d1 == d2
# 第2种方法:排序
class Solution(object):
def isAnagram(self, s, t):
return sorted(s) == sorted(t)