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