53 最大子序和
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
解:
class Solution:
def maxSubArray(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
count = -100000000000000000000
maxlen = [0]*len(nums)
for i in range(len(nums)):
for j in range(i,len(nums)):
maxlen[i] += nums[j]
if maxlen[i]>count:
count = maxlen[i]
if maxlen[i] <0:
break
return count
简写为:
class Solution:
def maxSubArray(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
count = nums[0]
for i in range(len(nums)):
maxlen = 0
for j in range(i,len(nums)):
maxlen += nums[j]
if maxlen>count:
count = maxlen[i]
if maxlen <0:
break
return count
但这样其实没有简单 复杂度高。
当我们加上一个正数时,和会增加;当我们加上一个负数时,和会减少。如果当前得到的和是个负数,那么这个和在接下来的累加中应该抛弃并重新清零,不然的话这个负数将会减少接下来的和。
class Solution:
def maxSubArray(self, num):
dp = num[0]
max_s = dp
for i in range(1, len(num)):
if dp <= 0:
dp = num[i]
else:
dp += num[i]
if dp > max_s:
max_s = dp
return max_s
198 打家劫舍
假设当前已经肆虐过了前i个房子(0…i-1),且rob[i]是抢劫了下标为i的房子时的最大收益,pass[i]是不抢劫下标为i的房子时的最大收益,那么可以得到状态转移方程:
参考 http://mzorro.me/2016/03/15/leetcode-house-robber/
状态方程:
rob[i] = nums[i] + pass[i-1]
pass[i] = max(rob[i-1], pass[i-1])
最重要的是先确定状态方程
class Solution:
def rob(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if len(nums)<=0:
return 0
rob,passc = [0]*len(nums),[0]*len(nums)
rob[0]=nums[0]
for i in range(1,len(nums)):
rob[i] = nums[i]+passc[i-1]
passc[i] = max(rob[i-1],passc[i-1])
return max(max(passc),max(rob))
也可以写为:
class Solution(object):
def rob(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if nums == []:
return 0
dp=[0]*(len(nums)+1)
dp[1] = nums[0]
for i in range(2,len(nums)+1):
dp[i] = max(dp[i-1],nums[i-1]+dp[i-2]) #因为有涉及i-2,所以这里dp向量维度多1
return dp[len(nums)]
413. 等差数列划分
如果一个数列至少有三个元素,并且任意两个相邻元素之差相同,则称该数列为等差数列。
例如,以下数列为等差数列:
1, 3, 5, 7, 9
7, 7, 7, 7
3, -1, -5, -9
以下数列不是等差数列。
1, 1, 2, 5, 7
数组 A 包含 N 个数,且索引从0开始。数组 A 的一个子数组划分为数组 (P, Q),P 与 Q 是整数且满足 0<=P<Q<N 。
如果满足以下条件,则称子数组(P, Q)为等差数组:
元素 A[P], A[p + 1], ..., A[Q - 1], A[Q] 是等差的。并且 P + 1 < Q 。
函数要返回数组 A 中所有为等差数组的子数组个数。
示例:
A = [1, 2, 3, 4]
返回: 3, A 中有三个子等差数组: [1, 2, 3], [2, 3, 4] 以及自身 [1, 2, 3, 4]。
解析:
参考 http://www.cnblogs.com/grandyang/p/5968340.html
要点在于 子数组个数怎么解。
我的第一种解法,三重循环,复杂度太高:
class Solution(object):
def numberOfArithmeticSlices(self, A):
"""
:type A: List[int]
:rtype: int
"""
n = len(A)
count=0
for i in range(2, n):
for j in range(n - i): # 考虑所有连续的长度为i+1的子串,s[j....j+i]
temp = 1
for k in range(j,j+i-1):
if A[k+2] - A[k+1] != A[k+1] - A[k]:
temp = 0
break
count += temp
return count
用动态规划的解法:这里有规律,如果知道了是等差数列,比如1,2,3 再加入下一个,比如2,3,4,也是等差,在已知前一个是等差的基础上,这里是加1了。
class Solution:
def numberOfArithmeticSlices(self, A):
"""
:type A: List[int]
:rtype: int
"""
dp = [0]*len(A)
res=0
for i in range(2,len(A)):
if A[i]-A[i-1] == A[i-1]-A[i-2]:
dp[i] = dp[i-1]+1
res+=dp[i]
return res
152. 乘积最大子序列
给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数)。
示例 1:
输入: [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。
示例 2:
输入: [-2,0,-1]
输出: 0
解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。
这题初看,以为是413等差数列划分的解法,但不太一样,因为有正负,没有一个衡量标准。
看了解答后,发现要设置最大最小两个参数,因为带负号的最小,只要遇到新的一个负号,就可能会变成最大。
class Solution(object):
def maxProduct(self, A):
mmax,mmin = [0]*len(A),[0]*len(A)
mmax[0],mmin[0],res = A[0],A[0],A[0]
for i in range(1,len(A)):
mmax[i] = max(mmax[i - 1] * A[i], mmin[i - 1] * A[i], A[i])
mmin[i] = min(mmax[i - 1] * A[i], mmin[i - 1] * A[i], A[i])
res = max(res,mmax[i])
return res
695. 岛屿的最大面积
给定一个包含了一些 0 和 1的非空二维数组 grid , 一个 岛屿 是由四个方向 (水平或垂直) 的 1 (代表土地) 构成的组合。你可以假设二维矩阵的四个边缘都被水包围着。找到给定的二维数组中最大的岛屿面积。(如果没有岛屿,则返回面积为0。)
示例 1:
[[0,0,1,0,0,0,0,1,0,0,0,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,1,1,0,1,0,0,0,0,0,0,0,0],
[0,1,0,0,1,1,0,0,1,0,1,0,0],
[0,1,0,0,1,1,0,0,1,1,1,0,0],
[0,0,0,0,0,0,0,0,0,0,1,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,0,0,0,0,0,0,1,1,0,0,0,0]]
对于上面这个给定矩阵应返回 6。注意答案不应该是11,因为岛屿只能包含水平或垂直的四个方向的‘1’。
示例 2:
[[0,0,0,0,0,0,0,0]]
对于上面这个给定的矩阵, 返回 0。
用广度优先搜索dfs解:
注意:这里不需要一个flag,直接把grid设置为0即可,因为grid是连通域,扫描过一次,之后不会再第二次用到,所以可以设成0.
def maxAreaOfIsland(grid):
count=0
def dfs(grid,i,j):
if i<0 or i>=len(grid) or j<0 or j>=len(grid[0]) or grid[i][j]==0:
return 0
grid[i][j]=0
return dfs(grid,i-1,j) + dfs(grid,i+1,j) + dfs(grid,i,j+1) + dfs(grid,i,j-1) +1
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j]==1:
count = max(dfs(grid,i,j),count)
return count
A = [[0,0,1],[1,0,1],[1,1,0]]
print(maxAreaOfIsland(A))
874. 模拟行走机器人
这题看了答案,没想出来。
自己重写了一遍,值得注意的是,如果用数组[],不用tuple()的话,会超出时间限制,不知为何。
class Solution:
def robotSim(self, commands, obstacles):
i = j = mx = d = 0
move, obstacles = [(0, 1), (-1, 0), (0, -1), (1, 0) ], set(map(tuple, obstacles))
for command in commands:
if command == -2: d = (d + 1) % 4
elif command == -1: d = (d - 1) % 4
else:
x, y = move[d]
while command and (i + x, j + y) not in obstacles:
i += x
j += y
command -= 1
mx = max(mx, i ** 2 + j ** 2)
return mx
以下用[]会超出时间限制:
class Solution(object):
def robotSim(self, commands, obstacles):
"""
:type commands: List[int]
:type obstacles: List[List[int]]
:rtype: int
"""
i = j = d = res= 0
move = [[0,1],[-1,0],[0,-1],[1,0]]
for com in commands:
if com == -2:
d = (d+1)%4
elif com == -1:
d = (d-1)%4
else:
x,y = move[d]
while com and [i+x,j+y] not in obstacles:
i += x
j += y
com -= 1
res = max(res, i**2 + j**2)
return res
104. 二叉树的最大深度
给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明: 叶子节点是指没有子节点的节点。
示例:
给定二叉树 [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回它的最大深度 3 。
这题要好好看看,最大深度就是深度优先搜索dfs,用递归!;还可以层次遍历,用bfs的方法也可以得到层数。
dfs递归:
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def maxDepth(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if root==None:
return 0
return 1 + max(self.maxDepth(root.left),self.maxDepth(root.right))
复杂度分析:
时间复杂度:我们每个结点只访问一次,因此时间复杂度为O(N),其中N是结点的数量。
空间复杂度:在最糟糕的情况下,树是完全不平衡的,例如每个结点只剩下左子结点,递归将会被调用N次(树的高度),因此保持调用栈的存储将是O(N)。
但在最好的情况下(树是完全平衡的),树的高度将是log(N)。因此,在这种情况下的空间复杂度将是O(log(N))
麻烦一点的bfs:
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def maxDepth(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if root == None:
return 0
res = 0
q = [root]
while q:
res+=1
for i in range(len(q),0,-1):
t = q[0]
q.pop(0)
if t.left:
q.append(t.left)
if t.right:
q.append(t.right)
return res
官方题解,迭代法:
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def maxDepth(self, root):
"""
:type root: TreeNode
:rtype: int
"""
stack = []
if root is not None:
stack.append((1, root))
depth = 0
while stack != []:
current_depth, root = stack.pop() #这里的current_depth很巧妙,不是每次让current_depth+=1,因为这样就错了,难点所在。
if root is not None:
depth = max(depth, current_depth)
stack.append((current_depth + 1, root.left))
stack.append((current_depth + 1, root.right))
return depth
谷歌一题
题目:
由输入字符串生成输出字符串数组, 实现linux指令echo的功能
1:输入:a{1,2,3}{4,3,2}
输出: [a14, a23, a32]
2:输入:{1,2,3}a{4,5,6}{7,8,9}
输出:[1a47, 2a58, 3a69]
3:输入:{a,d,s}{g,k,l}{j,k,l}f
输出:[agjf, dkkf, sllf]
思路:
{1,2,3}a{4,5,6}{7,8,9}
Step1: 按照{进行分割,会分为四组,确保最终输出的字符串长度正确
“”, “1,2,3}a”, “4,5,6}”, “7,8,9}”
Step2: 当上述例子中a出现在中间或者最右时可能分割不正确,进行纠正:
1) 去掉右括号,如果右括号不是出现在最后一个字符,将这个字符串拆成两个,例如,1,2,3}a”按照“}”的位置拆分为”1,2,3”和”a”
2) 忽略拆分的空字符串
Step3:拆分得到:“1,2,3”, “a”, “4,5,6”, “7,8,9”
将结果存储到一个二维数组。行为最后输出字符串要拼接的元素个数,列为{}中的元素个数,本例中分别为 4和3
Step4:将每行数组按照列的位置组合到一起,组成新的数组输出:
[1a47, 2a58, 3a69]
解答:
def expand(expression):
rawWord = expression.split('{')
l = 1
point = 0
word = [[0 for col in range(len(rawWord))] for row in range(len(rawWord))]
for i in range(len(rawWord)):
if len(rawWord[i]) < 1:
continue
if rawWord[i][len(rawWord[i])-1] != '}':
tmp = rawWord[i]
if rawWord[i].index('}') == -1:
word[point] = [0]
word[point][0] = rawWord[i]
point += 1
else:
rawWord[i] = rawWord[i][0:rawWord[i].index('}')].replace('}','')
word[point] = rawWord[i].split(',')
point += 1
word[point] = [0]
word[point][0] = tmp[tmp.index('}')+1:]
point += 1
else:
rawWord[i] = rawWord[i].replace('}','')
word[point] = rawWord[i].split(',')
point += 1
if l==1 and l<len(word[point-1]):
l = len(word[point-1])
answer = [0]*l
for j in range(l):
answer[j] = []
for i in range(len(rawWord)):
if word[i] == None:
continue
elif len(word[i]) == 1:
answer[j] += word[i][0]
else:
answer[j] += word[i][j]
ans = [0]*l
for j in range(l):
ans[j] = ''.join(answer[j])
return ans
c = '{3,5,6}{7,8,9}{a,b,c}{3,4,5}a'
a = '{3,5,6}{7,8,9}a{a,b,c}{3,4,5}'
ans = expand(a)
print(ans)