首先是 557. Reverse Words in a String III (easy)
https://leetcode.com/problems/reverse-words-in-a-string-iii/
題目要求很簡單,會給一個串列s,裡面有很多單字,字與字之間有一格空格。要把每個單字都進行翻轉。
雖然標籤有two pointer,但python做這題用pointer反而覺得有點矯情。
就簡單用個split() + [::-1]就解決了
class Solution:
def reverseWords(self, s: str) -> str:
s = s.split(" ")
for i in range(len(s)):
s[i] = s[i][::-1]
return " ".join(s)
再來是 121. Best Time to Buy and Sell Stock (easy)
https://leetcode.com/problems/best-time-to-buy-and-sell-stock
這題題目會給一個叫做price的list,裡面所存的數字可以當作是某項物品的價位。
當只能買賣一次時,能夠賺取的最大金額為多少(買的日期一定要比賣的日期早)
像這種題目首先要試的方法當然就是暴力法:
兩層for迴圈,把後面所有的數字都減過一遍,找最小值直接取絕對值就結束了。
class Solution:
def maxProfit(self, price: List[int]) -> int:
#這樣寫果然會TLE
ansList = [0]
for i in range(len(prices)):
for j in range(i+1,len(prices)):
temp = prices[i] - prices[j]
if temp < 0:
ansList.append(temp)
ans = min(ansList)
return abs(ans)
那像這種毫無效率的方法會TLE就不意外。
因此接下來改成以下的作法
class Solution:
#這題是用兩個pointer沒有錯,從前往後
ansList = [0]
front ,back = 0, 1
while back<len(price):
if price[front] >= price[back]:
front = back
back +=1
else:
ansList.append(price[back] - price[front])
back +=1
ans = max(ansList)
return ans
接下來是 409. Longest Palindrome (easy)
https://leetcode.com/problems/longest-palindrome
這題會給一個字串s,要從這s裡面拼湊出回文字串,並且找出最長的長度。
想法:
class Solution:
#別忽略了可以是多個奇數的狀況ex:3個a、5個b
#別忘記一件事情奇數個東西也可以變成偶數阿-1就好
#簡單來說我只要計算有多少個奇數就好假設有3個奇數就總字數-2,n個奇數就總字數-(n-1)
def longestPalindrome(self, s: str) -> int:
sDict = Counter(s)
# print(sDict)
count = 0
flag = 0
for i in sDict.values():
if i % 2:
flag = 1
count += i-1
else:
count += i
if flag:
return count+1
return count
這是一開始的想法,但這樣寫其實有幾個問題
class Solution:
#別忽略了可以是多個奇數的狀況ex:3個a、5個b
#別忘記一件事情奇數個東西也可以變成偶數阿-1就好
#簡單來說我只要計算有多少個奇數就好假設有3個奇數就總字數-2,n個奇數就總字數-(n-1)
def longestPalindrome(self, s: str) -> int:
sDict = Counter(s)
flag = 0
for i in sDict.values():
if i % 2:
flag += 1
if flag:
return len(s) - flag + 1
else:
return len(s)
相對而言簡單很多,指需要統計奇數有多少個,超過一個的話扣掉他即可。
下一題 142. Linked List Cycle II (medium)
https://leetcode.com/problems/linked-list-cycle-ii/
需要思考一下的題目
要求找出這個linked list是否cycle,以及從哪個node開始cycle
由圖可知,從back走了A+B到撞擊點,也就是說front要走2A+2B-1若中間跑loop跑了n圈,距離為nL,則可以這樣說 A+B+nL = 2A+2B-1 -> A+B-1 = nL 我們要找的A就是nL-B+1,那因為跟跑操場一樣,每圈長度固定,所以可以簡寫為L-B+1。
所以首先第一步,使用Floyd確定是否為cycle後
第二步就是back跟head一起往前L-B步即可,由於front有偷走一步,所以back也要先走一步把那個+1去掉。
所以會變成以下的程式碼
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
#龜兔賽跑檢查是否為cycle
if head is None or head.next is None:
return None
back = head
front = head.next
flag = 0
while front:
if flag:
back = back.next
flag = 0
front = front.next
if front == back:
break
else:
front = front.next
flag = 1
else:
return None
#尋找重複開始的地方
back = back.next
while head != back:
head = head.next
back = back.next
return head
稍微參考一下別人的想法以及簡化,程式碼又可以變成如下:
class Solution:
def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
back,front = head,head
while front and front.next:
front = front.next.next
back = back.next
if back == front:
while head != back:
head = head.next
back = back.next
return head
return None