75.颜色分类(中等)
这题又被称为荷兰国旗问题。
给定一个包含红色、白色和蓝色,一共n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
此题中,我们使用整数 0、1 和 2 分别表示红色、白色和蓝色。
注意:
不能使用代码库中的排序函数来解决这道题。
示例:
输入: [2,0,2,1,1,0]
输出: [0,0,1,1,2,2]
解法一:
题目中只会出现0,1,2,其实就是要把题目中的0,1,2按照升序排好就可以了,我们可以从头遍历输入的数组,碰到是0,就把数组对应位置改为0,碰到1,就计数,遍历完后,0就已经排好了,按照记录的1的数目把1放到0的后面,然后把剩下位置改为2就可以了。代码如下:
class Solution(object):
def sortColors(self, nums):
"""
:type nums: List[int]
:rtype: None Do not return anything, modify nums in-place instead.
"""
i, j = 0, 0
for s in nums:
if s == 0:
nums[i] = 0
i += 1
elif s == 1:
j += 1
for s in range(i, i + j):
nums[s] = 1
for s in range(i + j, len(nums)):
nums[s] = 2
解法二:
用三个指针p0,p2,curr来分别表示最右边一个0,最左边一个2,以及当前元素。
当curr=0时,把p0与curr的元素互换,并且两个指针都加1,如果curr=2,则互换p2与curr,并把p2减一,但是注意curr不加一,因为交换过来的元素还要判断一次,如果curr=1,则curr加1即可。
class Solution(object):
def sortColors(self, nums):
"""
:type nums: List[int]
:rtype: None Do not return anything, modify nums in-place instead.
"""
p0 = 0
p2 = len(nums)-1
curr = 0
while curr <= p2:
if nums[curr] == 2:
nums[p2], nums[curr] = nums[curr], nums[p2]
p2 -= 1
elif nums[curr] == 0:
nums[p0], nums[curr] = nums[curr], nums[p0]
curr += 1
p0 += 1
else:
curr += 1
455.分发饼干(简单)
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i ,都有一个胃口值gi ,这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j ,都有一个尺寸 sj。如果 sj >= gi,我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。
注意:
你可以假设胃口值为正。
一个小朋友最多只能拥有一块饼干。
示例1:
输入: [1,2,3], [1,1]
输出: 1
解释:
你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。
虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。
所以你应该输出1。
示例2:
输入: [1,2], [1,2,3]
输出: 2
解释:
你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。
你拥有的饼干数量和尺寸都足以让所有孩子满足。
所以你应该输出2.
解法一:
首先把两个list进行升序排列,之后从第一个孩子和第一块饼干开始判断,如果g[i]>s[j],说明不能满足孩子的胃口,j+1,否则j,i,count都加一,循环条件是某一个列表遍历完。这里注意的是循环条件其实可以是两个一起制定的,用and连接就好,方便很多。
class Solution(object):
def findContentChildren(self, g, s):
"""
:type g: List[int]
:type s: List[int]
:rtype: int
"""
g.sort()
s.sort()
i = 0
j = 0
count = 0
while i < len(g) and j < len(s):
if g[i] > s[j]:
j += 1
else:
count += 1
i += 1
j += 1
return count
解法二:
可以改的更加优雅一些,观察上面的代码,可以发现无论什么操作j都要加一,且i和count都是同步的,所以可以这样精简。
class Solution(object):
def findContentChildren(self, g, s):
"""
:type g: List[int]
:type s: List[int]
:rtype: int
"""
g.sort()
s.sort()
i = 0
j = 0
while i < len(g) and j < len(s):
if g[i] <= s[j]:
i += 1
j += 1
return i
69.x的平方根 (简单)
实现 int sqrt(int x) 函数。
计算并返回 x 的平方根,其中 x 是非负整数。
由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。
示例1:
输入: 4
输出: 2
示例2:
输入: 8
输出: 2
说明: 8 的平方根是 2.82842...,
由于返回类型是整数,小数部分将被舍去。
解法一:
使用二分法,但是二分法的边界问题很恶心,一不小心就进入了死循环
class Solution(object):
def mySqrt(self, x):
"""
:type x: int
:rtype: int
"""
left = 0
right = x // 2 + 1 #为了照顾输入1
while left<right:
mid = (left+right) // 2 + 1
square = mid*mid
if square == x:
return mid
elif square>x:
right = mid-1
else:
left = mid
return left
解法二:
用牛顿迭代法,求a的平方根,相当于求
f(x) = x^2 -a
当f(x)=0时的根
这个函数的导函数是2x,也就是我猜的每一个x等于x-f(x)/2x,把f(x)=x^2-a带进去,可以得到迭代公式x = 1/2(x+a/x),进行迭代就可以,终止迭代的条件是前后两次的x值相差小于1*10^-6,即返回x。
class Solution(object):
def mySqrt(self, x):
"""
:type x: int
:rtype: int
"""
cur = x #这个数随便写,多少都行
while True:
pre = cur
cur = (cur + x/cur) / 2
if abs(cur-pre)<1e-6:
return int(cur)
241.为运算表达式设计优先级(中等)
给定一个含有数字和运算符的字符串,为表达式添加括号,改变其运算优先级以求出不同的结果。你需要给出所有可能的组合的结果。有效的运算符号包含 +, - 以及 * 。
示例1:
输入: "2-1-1"
输出: [0, 2]
解释:
((2-1)-1) = 0
(2-(1-1)) = 2
示例2:
输入: "2*3-4*5"
输出: [-34, -14, -10, -10, 10]
解释:
(2*(3-(4*5))) = -34
((2*3)-(4*5)) = -14
((2*(3-4))*5) = -10
(2*((3-4)*5)) = -10
(((2*3)-4)*5) = 10
解法一:
采用分治+递归的思想,把字符串按照运算符号分为左边和右边,一直分到只剩单独一个数字时,根据输入的符号进行运算,简单的说就是,函数返回的就是目前输入的字符串的所有的运算结果可能。
class Solution(object):
def diffWaysToCompute(self, input):
"""
:type input: str
:rtype: List[int]
"""
if input.isdigit():
return [int(input)]
res = []
for i in range(len(input)):
if input[i] in "+-*":
res1 = self.diffWaysToCompute(input[:i])
res2 = self.diffWaysToCompute(input[i+1:])
for l in res1:
for r in res2:
res.append(self.helper(l, r, input[i]))
return res
def helper(self, a, b, op):
if op == "+":
return a+b
elif op == "-":
return a-b
else:
return a*b
#helper函数也可以这么写:
"""
def helper(self, a, b, op):
return {
'+': a + b,
'-': a - b,
'*': a * b
}[op]
"""
160.相交链表(中等)
编写一个程序,找到两个单链表相交的起始节点。
如下面的两个链表:
在节点 c1 开始相交。
示例1:
输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Reference of the node with value = 8
输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
示例2:
输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Reference of the node with value = 2
输入解释:相交节点的值为 2 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。
示例3:
输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
输入解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
解释:这两个链表不相交,因此返回 null。
解法一:
首先计算出两个链表的长度差,把长的那一条的指针往后移动差值步,之后两个链表一起向后遍历,当遇到一样的值时就是相交的节点。
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def getIntersectionNode(self, headA, headB):
"""
:type head1, head1: ListNode
:rtype: ListNode
"""
a = headA
b = headB
len_a = 0
len_b = 0
while a:
a = a.next
len_a += 1
while b:
b = b.next
len_b += 1
if a != b:
return None
a = headA
b = headB
if len_a > len_b:
for _ in range(len_a-len_b):
a = a.next
elif len_b > len_a:
for _ in range(len_b - len_a):
b = b.next
while a!=b:
a = a.next
b = b.next
return a
解法二:
其实还是消除长度差,不过我们可以把两个链表拼在一起,一个长-短,一个短-长,当两个指针相同时即达成条件,如下图所示:
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def getIntersectionNode(self, headA, headB):
"""
:type head1, head1: ListNode
:rtype: ListNode
"""
a = headA
b = headB
while a!=b:
a = a.next if a else headB
b = b.next if b else headA
return a