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)