121.买卖股票的最佳价格
解题思路:用一个变量记下历史最低价格 minprice,在第 i 天卖出股票能得到的利润就是 prices[i] - minprice。遍历价格数组一遍,记录历史最低点,然后用prices[i] - minprice即可得到。
class Solution:
def maxProfit(self, prices: List[int]) -> int:
minprice = float('inf')
maxprofit = 0
for price in prices:
minprice = min(minprice,price)
maxprofit = max(maxprofit,price-minprice)
return maxprofit
198.打家劫舍
首先考虑最简单的情况。如果只有一间房屋,则偷窃该房屋,可以偷窃到最高总金额。如果只有两间房屋,则由于两间房屋相邻,不能同时偷窃,只能偷窃其中的一间房屋,因此选择其中金额较高的房屋进行偷窃,可以偷窃到最高总金额。
如果房屋数量大于两间,应该如何计算能够偷窃到的最高总金额呢?对于第 k~(k>2)k (k>2) 间房屋,有两个选项:
偷窃第 kk 间房屋,那么就不能偷窃第 k-1k−1 间房屋,偷窃总金额为前 k-2k−2 间房屋的最高总金额与第 kk 间房屋的金额之和。
不偷窃第 kk 间房屋,偷窃总金额为前 k-1k−1 间房屋的最高总金额。
在两个选项中选择偷窃总金额较大的选项,该选项对应的偷窃总金额即为前 kk 间房屋能偷窃到的最高总金额。
滚动数组是DP中的一种编程思想。简单的理解就是让数组滚动起来,每次都使用固定的几个存储空间,来达到压缩,节省存储空间的作用。起到优化空间,主要应用在递推或动态规划中(如01背包问题)。因为DP题目是一个自底向上的扩展过程,我们常常需要用到的是连续的解,前面的解往往可以舍去。所以用滚动数组优化是很有效的。利用滚动数组的话在N很大的情况下可以达到压缩存储的作用。
class Solution:
def rob(self, nums: List[int]) -> int:
if not nums:
return 0
length = len(nums)
if length ==1:
return nums[0]
first, second = nums[0], max(nums[0], nums[1])
for i in range(2,length):
first, second = second, max(first+nums[i],second)
return second
141.环形链表,给定一个链表,判断链表中是否有环。为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
解题思路:链表的题画图最直观!
从头遍历链表,将遍历到的元素放入字典里,如果有环的情况下那么必然会重复出现在哈希表;如果没有环,那么指针移动到最后就退出。
class Solution:
def hasCycle(self, head: ListNode) -> bool:
dic ={}
while head:
if head in dic:
return True
else:
dic[head] = 1
head = head.next
return False
160.相交链表
编写一个程序,找到两个单链表相交的起始节点。
解题思路:拼接方式:(1)当A走到尾部的Null的时候,转到B链表的头节点继续走(2)当B走到尾部的Null的时候,转到B链表的头节点继续走
值得注意的是,如图所示,无论是相交还是不相交,对于无环的链表来说,都一定会相遇,因此不会死循环。
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
cur1 = headA
cur2 = headB
while cur1 != cur2:
cur1 = cur1.next if cur1 else headB
cur2 = cur2.next if cur2 else headA
return cur1