题目(两数之和):
给定一组列表和目标值,从列表中找出两数之和为目标值,并返回两数的索引
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
Code :
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
dict = {}
for i, num in enumerate(nums):
if num in dict:
other_idx = dict[num]
return [other_idx, i]
else:
dict[target - num] = i
解题思路:
可运用字典形式存储值及索引,enumerate函数,可以返回索引及值,任意的数字,用目标值减去初始值,当找到相同的值,则返回此数的索引
总结:
巧用字典,可返回所需要的结果
题目(两数之和):
2. Add Two Numbers
You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.
You may assume the two numbers do not contain any leading zero, except the number 0 itself.
Example:
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
Explanation: 342 + 465 = 807.
有两个链表,分别是逆序了的十进制数字。现在要求两个十位数字的和,要求返回的结果也是链表
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
i=0
a=0
b=0
while l1:
a=a+l1.val*(10**i)
l1 = l1.next
i=i+1
i=0
while l2:
b=b+l2.val*(10**i)
l2 = l2.next
i=i+1
c=a+b
d=[int(i) for i in str(c)]
d.reverse()
head = ListNode(d[0])
current = head
for i in d[1:]:
current.next = ListNode(i)
current = current.next
return head
首先过一下python的一些基础知识,原先不是很清楚
链表
从提示代码可以看出这里涉及到单链表结构,代码如下:
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
链表由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间。
使用链表结构可以克服数组需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。
但是链表失去了数组随机读取的优点
同时链表由于增加了结点的指针域,空间开销比较大。
链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换。链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表 双向链表 以及 循环链表 。链表可以在多种编程语言中实现。
链表是数据结构中最基本常用的,C++语言中单链表是利用指针操作实现的,python作为面向对象编程的,可以使用创建一个ListNode类来实现链表,利用类的属性引用来代替指针操作。
下面我们创建了一个节点类,然后编写了几个链表操作,包括创建,插入,删除,输出等。代码如下:
class ListNode(): # 初始化 构造函数
def __init__(self,value):
self.value=value
self.next=None
def Creatlist(n):
if n<=0:
return False
if n==1:
return ListNode(1) # 只有一个节点
else:
root=ListNode(1)
tmp=root
for i in range(2,n+1): # 一个一个的增加节点
tmp.next=ListNode(i)
tmp=tmp.next
return root # 返回根节点
def printlist(head): # 打印链表 (遍历)
p=head
while p!=None:
print p.value
p=p.next
def listlen(head): # 链表长度
c=0
p=head
while p!=None:
c=c+1
p=p.next
return c
def insert(head,n): # 在n的前面插入元素
if n<1 or n>listlen(head):
return
p=head
for i in range(1,n-1): # 循环四次到达 5 (只能一个一个节点的移动 range不包含n-1)
p=p.next
a=raw_input("Enter a value:")
t=ListNode(value=a)
t.next=p.next
p.next=t
return head
def dellist(head,n): # 删除链表
if n<1 or n>listlen(head):
return head
elif n is 1:
head=head.next # 删除头
else:
p=head
for i in range(1,n-1):
p=p.next # 循环到达 2次
q=p.next
p.next=q.next # 把5放在3的后面
return head
def main():
print "Create a linklist"
head=Creatlist(7)
printlist(head)
print
print "___________________________"
n1=raw_input("Enter the index to insert")
n1=int(n1)
insert(head,n1)
printlist(head)
print
print "___________________________"
n2=raw_input("Enter the index to delete")
n2=int(n2)
dellist(head,n2)
printlist(head)
if __name__=='__main__':
main() # 主函数调用
解题思路:
类似加法的原理, 我们从低位(链条第一位)开始,同位相加,满10高位+1
总结:
这道题目是要将两个单链条相加。输出得到的新链条。
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
temp = 0
d = {}
start = 0
for i in range(len(s)):
if s[i] in d and start <= d[s[i]] :
start = d[s[i]] +1
temp = max(i-start+1,temp)
d[s[i]] = i
return temp
121. 买卖股票的最佳时机
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。
注意你不能在买入股票前卖出股票。
示例 1:
输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。
示例 2:
输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
思路:动态规划 前i天的最大收益 = max{前i-1天的最大收益,第i天的价格-前i-1天中的最小价格}
class Solution:
def maxProfit(self, prices: List[int]) -> int:
minprice=9999999
maxprofit=0
for i in prices:
if i<minprice:
minprice=i
elif i-minprice>maxprofit:
maxprofit=i-minprice
return maxprofit
不能提交,因为要导入numpy的包, list转为array 求最大,直接max(list)报错,整型数据不能直接用max函数
124. 二叉树中的最大路径和
给定一个非空二叉树,返回其最大路径和。
本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。
示例 1:
输入: [1,2,3]
1
/ \
2 3
输出: 6
示例 2:
输入: [-10,9,20,null,null,15,7]
-10
/
9 20
/
15 7
输出: 42
思路:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.left = None
# self.right = None
class Solution:
def maxPathSum(self, root: TreeNode) -> int:
self.result = -2 ** 31
self.recursive(root)
return self.result
def recursive(self, root):
if root == None:
return 0
# 当左右子树,是小于 0 的时候,就将左右子树赋值为 0 ,因为题干是要求最大值,所以不可能去加一个负数
left = max(0, self.recursive(root.left))
right = max(0, self.recursive(root.right))
# 比较当前节点下的最大值与上一个节点的值,将比较之后的结果记录下来
self.result = max(self.result, root.val + left + right)
# 题目中从树中任意节点出发,达到任意节点的序列。且最大路径和。这里是返回给父节点使用的,
# 所以,可以返回 root.val (就是当前节点),也可以返回 root.val + max(left, right) (就是当前节点和他的子树)。
# 又因为是求【最大路径和】所以最外层也使用了一个 max() 函数
return max(root.val, root.val + max(left, right))
207. 课程表
现在你总共有 n 门课需要选,记为 0 到 n-1。
在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们: [0,1]
给定课程总量以及它们的先决条件,判断是否可能完成所有课程的学习?
示例 1:
输入: 2, [[1,0]]
输出: true
解释: 总共有 2 门课程。学习课程 1 之前,你需要完成课程 0。所以这是可能的。
示例 2:
输入: 2, [[1,0],[0,1]]
输出: false
解释: 总共有 2 门课程。学习课程 1 之前,你需要先完成课程 0;并且学习课程 0 之前,你还应先完成课程 1。这是不可能的。
说明:
输入的先决条件是由边缘列表表示的图形,而不是邻接矩阵。详情请参见图的表示法。你可以假定输入的先决条件中没有重复的边。
提示:
这个问题相当于查找一个循环是否存在于有向图中。如果存在循环,则不存在拓扑排序,因此不可能选取所有课程进行学习。
通过 DFS 进行拓扑排序 - 一个关于Coursera的精彩视频教程(21分钟),介绍拓扑排序的基本概念。
拓扑排序也可以通过 BFS 完成。
class Solution:
def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
"""
:type numCourses: int 课程门数
:type prerequisites: List[List[int]] 课程与课程之间的关系
:rtype: bool
"""
# 课程的长度
clen = len(prerequisites)
if clen == 0:
# 没有课程,当然可以完成课程的学习
return True
# 入度数组,一开始全部为 0
in_degrees = [0 for _ in range(numCourses)]
# 邻接表
adj = [set() for _ in range(numCourses)]
# 想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们: [0,1]
# [0,1] 表示 1 在先,0 在后
# 注意:邻接表存放的是后继 successor 结点的集合
for second, first in prerequisites:
in_degrees[second] += 1
adj[first].add(second)
# print("in_degrees", in_degrees)
# 首先遍历一遍,把所有入度为 0 的结点加入队列
res = []
queue = []
for i in range(numCourses):
if in_degrees[i] == 0:
queue.append(i)
counter = 0
while queue:
top = queue.pop(0)
counter += 1
for successor in adj[top]:
in_degrees[successor] -= 1
if in_degrees[successor] == 0:
queue.append(successor)
return counter == numCourses
24. 两两交换链表中的节点
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例:
给定 1->2->3->4, 你应该返回 2->1->4->3.
解题思路:
我们首先需要建立pre、node1、node2和lat四个指针即可。
cur node1 node2 lat
h -> 1 -> 2 -> 3 -> 4
然后pre->next=node2;node2.next=node1;node1.next=lat
-----------
| |
h 1 <- 2 -> 3 -> 4
| |
-----------
接着更新四个指针即可。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def swapPairs(self, head: ListNode) -> ListNode:
h = ListNode(-1)
h.next = head
pre = h
while pre.next != None and pre.next.next != None:
node1 = pre.next
node2 = node1.next
lat = node2.next
pre.next = node2
node2.next = node1
node1.next = lat
pre = node1
return h.next