目录
入门:
1. 反转字符串
2. 螺旋矩阵
3. 斐波那契数列
4. 判断回文
5. 寻找峰值
6. 旋转数组
7. 最大公约数
简单:
8. 反转链表
9. 两数之和
10. 合并有序链表
11. 用两个栈实现队列
12. 跳台阶
13. 子数组的最大累加和问题
14. 判断链表中是否有环
15. 括号序列
16. 两个链表的第一个公共结点
17. 求平方根
17.1 在旋转过的有序数组中寻找目标值
18. 设计getMin功能的栈
19. 买卖股票的最好时机
20. 二叉树的最大深度
21. 单链表的排序
22. 平衡二叉树
23. 数组中出现次数超过一半的数字
24. 进制转换
25. 判断一个链表是否为回文结构
26. 求路径
27. 反转数字
28. 缺失数字
29. 判断二叉树是否对称
30. 删除有序链表中重复的元素
31. 二叉树中是否存在节点和为指定值的路径
32. 最长公共前缀
33. 回文数字
34. 二叉搜索树的第k个结点
35. 字符串变形
36. 换钱的最少货币数
37. 股票(无限次交易)
38. 二叉树的镜像
39. 判断t1树中是否有与t2树拓扑结构完全相同的子树
40. 合并二叉树
41. 将升序数组转化为平衡二叉搜索树
42. 扑克牌顺子
43. 第一个只出现一次的字符
44. 旋转数组的最小数字
45. 数字在升序数组中出现的次数
46. 未排序数组中累加和为给定值的最长子数组长度
47. 三个数的最大乘积
48. 旋转字符串
49. 01背包
50. 数组中只出现一次的数(其它数出现k次)
51. 二分查找-I
中等:
52. 排序
53. 最长公共字符串
54. 链表内指定区间反转
写出一个程序,接受一个字符串,然后输出该字符串反转后的字符串。(字符串长度不超过1000)
示例1
输入:"abcd"
输出:"dcba"
解题代码:
#
# 反转字符串
# @param str string字符串
# @return string字符串
#
class Solution:
def solve(self , str ):
# write code here
li = list(str)
# list反转内置函数
#l.reverse()
#return "".join(l)
i = 0
j = len(li) - 1
while i < j:
tmp = li[i]
li[i] = li[j]
li[j] = tmp
i += 1
j -= 1
return "".join(li)
给定一个m x n大小的矩阵(m行,n列),按螺旋的顺序返回矩阵中的所有元素。
输入:[[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
#
#
# @param matrix int整型二维数组
# @return int整型一维数组
#
class Solution:
def spiralOrder(self , matrix ):
# write code here
# matrix = [[1,2,3],[4,5,6],[7,8,9]]
# matrix[0] = [1,2,3]
# matrix矩阵如下:
# 1 2 3
# 4 5 6
# 7 8 9
res = []
while matrix:
res += matrix[0]
# zip(*matrix[1::]) = [(4,7), (5,8), (6,9)]
matrix = zip(*matrix[1:])[::-1]
# matrix = [(6,9), (5,8), (4,7)]
return res
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0,第1项是1)。
n\leq 39n≤39
输入:4
返回值:3
# -*- coding:utf-8 -*-
class Solution:
def Fibonacci(self, n):
# write code here
s = [0] * (n+1)
if n == 0:
return 0
if n == 1:
return 1
if n == 2:
return 1
s[0]=0
s[1]=1
if n > 1:
for i in range(2, n+1):
s[i] = s[i-1] + s[i-2]
return s[n]
给定一个字符串,请编写一个函数判断该字符串是否回文。如果回文请返回true,否则返回false。
输入:"absba"
返回值:true
输入:"yamatomaya"
返回值:false
备注:字符串长度不大于1000000,且仅由小写字母组成
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# @param str string字符串 待判断的字符串
# @return bool布尔型
# 回文:从左至右和从右至左一样的字符串
#
class Solution:
def judge(self , str ):
# write code here
list1 = list(str)
list2 = list1[:]
list1.reverse()
return list1 == list2
# 法二:字符串翻转,步长为-1
# return str == str[::-1]
山峰元素是指其值大于或等于左右相邻值的元素。给定一个输入数组nums,任意两个相邻元素值不相等,数组可能包含多个山峰。找到索引最大的那个山峰元素并返回其索引。
假设 nums[-1] = nums[n] = -∞。
输入:[2,4,1,2,7,8,4]
返回值:5
#
# 寻找最后的山峰
# @param a int整型一维数组
# @return int整型
#
class Solution:
def solve(self , a ):
# write code here
if a[len(a)-1] > a[len(a)-2]:
return len(a)-1
for i in range(len(a)-2,1,-1):
if a[i] >= a[i-1] and a[i] > a[i+1]:
return i
if a[0] > a[1]:
return 0
一个数组A中存有N(N>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(M>=0)个位置,即将A中的数据由(A0 A1 ……AN-1 )变换为(AN-M …… AN-1 A0 A1 ……AN-M-1 )(最后M个数循环移至最前面的M个位置)。如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?
输入:6,2,[1,2,3,4,5,6]
返回值:[5,6,1,2,3,4]
备注:(1<=N<=100,M>=0)
#
# 旋转数组
# @param n int整型 数组长度
# @param m int整型 右移距离
# @param a int整型一维数组 给定数组
# @return int整型一维数组
#
class Solution:
def solve(self , n , m , a ):
# write code here
m = m % n
if m == 0 or n == 1:
return a
# 1.整体反转
a[:] = a[::-1]
# 2.反转前m个元素
a[0:m] = a[m-1::-1]
# 3.反转后n-m个元素
a[m:n] = a[n-1:m-1:-1]
return a
求出两个数的最大公约数,如果有一个自然数a能被自然数b整除,则称a为b的倍数,b为a的约数。几个自然数公有的约数,叫做这几个自然数的公约数。公约数中最大的一个公约数,称为这几个自然数的最大公约数。
输入:3,6
返回值:3
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 求出a、b的最大公约数。
# @param a int
# @param b int
# @return int
#
# a和b的最大公约数等于 b%(a%b),如果余数为0,公约数为除数
class Solution:
def gcd(self , a , b ):
# write code here
tmp = 0
while b != 0:
tmp = a % b
a = b
b = tmp
return a
输入一个链表,反转链表后,输出新链表的表头。
输入:{1,2,3}
返回值:{3,2,1}
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# 返回ListNode
def ReverseList(self, pHead):
# write code here
tmp = None
pre = None
while(pHead):
# 先把当前节点的下一个节点保存
tmp = pHead.next
# 然后转向
pHead.next = pre
# 再把pre放到当前节点
pre = pHead
# 当前节点后移
pHead = tmp
return pre
给出一个整数数组,请在数组中找出两个加起来等于目标值的数,
你给出的函数twoSum 需要返回这两个数字的下标(index1,index2),需要满足 index1 小于index2.。注意:下标是从1开始的
假设给出的数组中只存在唯一解
例如:
给出的数组为 {20, 70, 110, 150},目标值为90
输出 index1=1, index2=2
输入:[3,2,4],6
返回值:[2,3]
说明:因为 2+4=6 ,而 2的下标为2 , 4的下标为3 ,又因为 下标2 < 下标3 ,所以输出[2,3]
#
#
# @param numbers int整型一维数组
# @param target int整型
# @return int整型一维数组
#
class Solution:
def twoSum(self , numbers , target ):
# write code here
for i in range(len(numbers)):
if numbers[i] > target:
continue
for j in range(i+1, len(numbers)):
if numbers[i] + numbers[j] == target:
return [i+1, j+1]
将两个有序的链表合并为一个新链表,要求新的链表是通过拼接两个链表的节点来生成的,且合并后新链表依然有序。
输入:{1},{2}
返回值:{1,2}
输入:{2},{1}
返回值:{1,2}
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
#
#
# @param l1 ListNode类
# @param l2 ListNode类
# @return ListNode类
#
class Solution:
def mergeTwoLists(self , l1 , l2 ):
# write code here
# head是把当前头结点记录,0不影响数据,只是占位
if not l1 and not l2: return None
tmp = ListNode(0)
# tmp是为了记录新链表
head = tmp
while True:
# 第一个链表为空,把第二个链表接上,break
if not l1:
tmp.next = l2
break
# 第二个链表为空,把第一个链表接上,break
elif not l2:
tmp.next = l1
break
# 第一个链表小于第二个链表的值,把第一个链表的val给新链表
elif l1.val <= l2.val:
tmp.next = l1
l1 = l1.next
tmp = tmp.next # 注意l1和tmp都要后移
# 否则把第二个链表的val给新链表
elif l1.val > l2.val:
tmp.next = l2
l2 = l2.next
tmp = tmp.next # 注意l2和tmp都要后移
return head.next # 第一个是0,返回头结点的后面next
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
# -*- coding:utf-8 -*-
# 堆栈直接append(a),pop()出入,默认删除最后一个
# 队列append(a),pop(0)出入,队列从第一个开始删除
class Solution:
def __init__(self):
self.stack1 = []
self.stack2 = []
def push(self, node):
# write code here
# 栈1用来入队列,栈和队列的入是一样的,直接append
self.stack1.append(node)
def pop(self):
# return xx
# 栈2用来出队列,当栈2为空时,栈1全部出栈到栈2,栈2再出栈
if self.stack2 == []:
while self.stack1:
self.stack2.append(self.stack1.pop())
return self.stack2.pop()
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
# -*- coding:utf-8 -*-
class Solution:
def jumpFloor(self, number):
# write code here
if number<=1: return 1
dp = [] * (number+1)
dp[0] = dp[1] = 1
for i in range(2,number+1):
dp[number] = dp[number-1] + dp[number-2]
return dp[number]
给定一个数组arr,返回子数组的最大累加和
例如,arr = [1, -2, 3, 5, -2, 6, -1],所有子数组中,[3, 5, -2, 6]可以累加出最大的和12,所以返回12.
题目保证没有全为负数的数据
[要求]
时间复杂度为O(n)O(n),空间复杂度为O(1)O(1)
输入:[1, -2, 3, 5, -2, 6, -1]
返回值:12
#
# max sum of the subarray
# @param arr int整型一维数组 the array
# @return int整型
#
class Solution:
def maxsumofSubarray(self , arr ):
# write code here
# dp[i]为下标i之前的大于0的最大累加和,当累加和小于0时,重新开始累加
dp = [0] * (len(arr)+1)
dp[0] = arr[0]
for i in range(1,len(arr)):
if dp[i-1] >= 0:
dp[i] = dp[i-1] + arr[i]
else:
dp[i] = arr[i]
return max(dp)
判断给定的链表中是否有环。如果有环则返回true,否则返回false。
你能给出空间复杂度O(1)的解法么?
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
#
#
# @param head ListNode类
# @return bool布尔型
#
class Solution:
def hasCycle(self , head ):
# write code here
# 快慢指针 解决链表中是否有环,快指针每次走两步,慢指针每次走一步
# 如果相遇了就证明有环,如果没有相遇(快指针遇到了None)就证明没有环。
# 其中需要注意的是判断空链表,以及快指针为空和即将为空的情况
quick = head
slow = head
while quick and quick.next:
quick = quick.next.next
slow = slow.next
if quick == slow:
return True
return False
给出一个仅包含字符'(',')','{','}','['和']',的字符串,判断给出的字符串是否是合法的括号序列
括号必须以正确的顺序关闭,"()"和"()[]{}"都是合法的括号序列,但"(]"和"([)]"不合法。
输入:"["
返回值:false
输入:"[]"
返回值:true
#
#
# @param s string字符串
# @return bool布尔型
#
class Solution:
def isValid(self , s ):
# write code here
# 1.压栈和取栈
# '(','[','{' 这三个就压栈
# ')',']','}' 这三个就取栈,取栈时判断一下是不是对应的括号,如果是就取栈成功,不是就不能取。
# 这样最后看栈是不是为空,不为空就说明顺序不正确
# 2.'()','[]','{}'替换为'',最后字符串为空就true
stack = []
x = ['(', '{', '[']
y = [')', '}', ']']
for i in s:
if i in x:
stack.append(i)
elif i in y:
# 若i为}, 栈顶元素为{.
# ps: x[y.index(i)]为{
if stack and stack[-1] == x[y.index(i)]:
stack.pop()
elif stack == []:
stack.append(i)
if stack == []:
return True
else:
return False
输入两个无环的单链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def FindFirstCommonNode(self, pHead1, pHead2):
# write code here
if pHead1 == None or pHead2 == None:
return None
# 什么是公共节点,两个链表从某一节点开始,他们的next都指向同一个节点。
# 但由于是单向链表的节点,每个节点只有一个next,因此公共节点之后他们的所有节点都是重合的。
# 两个链表从头开始遍历,next相等时返回
p1 = pHead1
p2 = pHead2
while p1 != p2:
p1 = p1.next
p2 = p2.next
if p1 != p2:
# 若到最后一个节点,又从头开始
if p1 == None:
p1 = pHead1
if p2 == None:
p2 = pHead2
return p1
实现函数 int sqrt(int x).
计算并返回x的平方根(向下取整)
#
#
# @param x int整型
# @return int整型
#
class Solution:
def sqrt(self , x ):
# write code here
if x==0:
return 0
left = 1
right = x
while left <= right:
# /表示浮点数除法,//表示整数除法
mid = (left + right) / 2
tmp = mid * mid
# 若中间的平方大于x,则取左边,left不动,right移到中间
if tmp > x:
right = mid - 1
elif tmp < x:
left = mid+1
else:
return mid
return right
给定一个整数数组nums,按升序排序,数组中的元素各不相同。
nums数组在传递给search函数之前,会在预先未知的某个下标 t(0 <= t <= nums.length-1)上进行旋转,让数组变为[nums[t], nums[t+1], ..., nums[nums.length-1], nums[0], nums[1], ..., nums[t-1]]。
比如,数组[0,2,4,6,8,10]在下标2处旋转之后变为[6,8,10,0,2,4]
现在给定一个旋转后的数组nums和一个整数target,请你查找这个数组是不是存在这个target,如果存在,那么返回它的下标,如果不存在,返回-1
输入:[6,8,10,0,2,4],10
返回值:2
输入:[6,8,10,0,2,4],3
返回值:-1
输入:[2],1
返回值:-1
法1:
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param nums int整型一维数组
# @param target int整型
# @return int整型
#
# 法一:直接遍历
class Solution:
def search(self , nums , target):
# write code here
if not nums and len(nums) == 0:
return -1
for i in range(len(nums)):
if nums[i] == target:
return i
return -1
法2:
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param nums int整型一维数组
# @param target int整型
# @return int整型
# 二分法
class Solution:
def search(self , nums , target):
# write code here
if not nums and len(nums) == 0:
return -1
left, right = 0, len(nums) - 1
while left <= right:
mid = left + (right-left)//2
if nums[mid] == target:
return mid
# mid在旋转数组前半截
elif nums[mid] >= nums[left]:
# 在前半截的前半截
if target >= nums[left] and target < nums[mid]:
right = mid - 1
# 在前半截的后半截
else:
left = mid + 1
# mid在旋转数组后半截
else:
# 在后半截的后半截
if target <= nums[right] and target > nums[mid]:
left = mid+1
# 在后半截的前半截
else:
right = mid-1
return -1
实现一个特殊功能的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作。
输入:[[1,3],[1,2],[1,1],[3],[2],[3]]
返回值:[1,2]
备注:
有三种操作种类,op1表示push,op2表示pop,op3表示getMin。你需要返回和op3出现次数一样多的数组,表示每次getMin的答案
1<=操作总数<=1000000
-1000000<=每个操作数<=1000000
数据保证没有不合法的操作
#
# return a array which include all ans for op3
# @param op int整型二维数组 operator
# @return int整型一维数组
#
class Solution:
def getMinStack(self , op ):
# write code here
# 新建一个list当成栈存放数据
st1 = []
res = []
for a in op:
# 1表示push
if a[0] == 1:
st1.append(a[1])
# 2表示pop
elif a[0] == 2:
st1.pop()
# 3表示获取最小值
elif a[0] == 3:
res.append(self.getMin(st1))
return res
def getMin(self, st):
min_st = st[0]
for i in st:
if min_st > i:
min_st = i
return min_st
假设你有一个数组,其中第\ i i 个元素是股票在第\ i i 天的价格。
你有一次买入和卖出的机会。(只有买入了股票以后才能卖出)。请你设计一个算法来计算可以获得的最大收益。
输入:[1,4,2]
返回值:3
#
#
# @param prices int整型一维数组
# @return int整型
#
class Solution:
def maxProfit(self , prices ):
# write code here
if len(prices) == 1:
return 0
max_p = max(prices)
min_p = min(prices)
# 若最大值索引大于最小值,则是最大最小之差
if prices.index(max_p) > prices.index(min_p):
return max_p - min_p
else:
# 删除最小
new = prices[:]
del new[new.index(min(new))]
new_min = self.maxProfit(new)
# 删除最大
new2 = prices[:]
del new2[new2.index(max(new2))]
new_max = self.maxProfit(new2)
return max(new_min, new_max)
求给定二叉树的最大深度,
最大深度是指树的根结点到最远叶子结点的最长路径上结点的数量。
输入:{1,2}
返回值:2
输入:{1,2,3,4,#,#,5}
返回值:3
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
#
#
# @param root TreeNode类
# @return int整型
#
class Solution:
def maxDepth(self , root ):
# write code here
# 左子树的最大深度 和 右子树的最大深度 比大小,再加上本节点 1 的深度。
if not root:
return 0
return 1 + max(self.maxDepth(root.left), self.maxDepth(root.right))
给定一个无序单链表,实现单链表的排序(按升序排序)。
输入:[1,3,2,4,5]
返回值:{1,2,3,4,5}
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
#
#
# @param head ListNode类 the head node
# @return ListNode类
#
class Solution:
def sortInList(self , head ):
# write code here
p = head
plist = []
while p:
plist.append((p.val,p))
p = p.next
# 按值排序
plist.sort(key=lambda x:x[0])
n = len(plist)
for i in range(n-1):
# 按排序结果调整链表方向
plist[i][1].next = plist[i+1][1]
# 最后一个指向None
plist[n-1][1].next = None
# 返回链表
return plist[0][1]
输入一棵二叉树,判断该二叉树是否是平衡二叉树。
在这里,我们只需要考虑其平衡性,不需要考虑其是不是排序二叉树
平衡二叉树(Balanced Binary Tree),具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
注:我们约定空树是平衡二叉树。
输入:{1,2,3,4,5,6,7}
返回值:true
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def IsBalanced_Solution(self, pRoot):
# write code here
# 先写一个求深度的函数,再对每一个节点判断,看该节点的左子树的深度和右子树的深度的差是否大于1
if not pRoot:
return True
if abs(self.maxDepth(pRoot.left) - self.maxDepth(pRoot.right)) > 1:
return False
return self.IsBalanced_Solution(pRoot.left) and self.IsBalanced_Solution(pRoot.right)
# 树的最大深度
def maxDepth(self, root):
if not root:
return 0
return max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1
知识点哈希、数组
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组[1,2,3,2,2,2,5,4,2]。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。你可以假设数组是非空的,并且给定的数组总是存在多数元素。1<=数组长度<=50000
输入:[1,2,3,2,2,2,5,4,2]
返回值:2
输入:[3,3,3,3,2,2,2]
返回值:3
输入:[1]
返回值:1
# -*- coding:utf-8 -*-
class Solution:
def MoreThanHalfNum_Solution(self, numbers):
# write code here
# 用一个字典存放元素和出现次数。key为列表元素,value为元素出现次数
dict1 = {}
for i in range(len(numbers)):
if numbers[i] in dict1.keys():
dict1[numbers[i]] += 1
else:
dict1[numbers[i]] = 1
if len(numbers) / 2 < max(dict1.values()):
for k,v in dict1.items():
try:
# python3中dict.keys()的顺序与插入顺序一致,dict.values()、dict.items()同理
# python2中dict.keys()直接排序过,但两个版本都是dict.keys()与dict.values()顺序一致
# 找出value最大的索引
index_v = list(dict1.values()).index(max(dict1.values()))
# 输出元素key
tmp = list(dict1.keys())[index_v]
except:
tmp = 0
return tmp
else:
return 0
给定一个十进制数M,以及需要转换的进制数N。将十进制数M转化为N进制数
输入:7,2
返回值:"111"
备注:
M是32位整数,2<=N<=16.
#
# 进制转换
# @param M int整型 给定整数
# @param N int整型 转换到的进制
# @return string字符串
#
class Solution:
def solve(self , M , N ):
# write code here
res = ""
minus = False
# 考虑10进制以上的表示
des = {10: "A", 11: "B", 12: "C", 13: "D", 14: "E", 15: "F"}
if M == 0: return ""
# 考虑负数的情况,否则死循环
if M < 0:
minus = True
M = -M
while M != 0:
# 一步步取余,从尾数开始排,直到M为0
yu = M % N
if yu >= 10:
res = des[yu] + res
else:
res = str(yu) + res
M /= N
if minus:
return "-" + res
else:
return res
给定一个链表,请判断该链表是否为回文结构。
输入:[1,2,2,1]
返回值:true
备注:
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
#
#
# @param head ListNode类 the head
# @return bool布尔型
# 本题用python会超时,只能用java!
class Solution:
def isPail(self , head ):
# write code here
# 快慢指针 + 栈
stack = []
fast = head
slow = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
# 此时slow已到中间,后半段入栈
while slow:
stack.append(slow)
slow = slow.next
# 前半段跟栈中数据比较
while stack:
if stack.pop().val != head.val:
return False
head = head.next
return True
一个机器人在m×n大小的地图的左上角(起点)。
机器人每次向下或向右移动。机器人要到达地图的右下角(终点)。
可以有多少种不同的路径从起点走到终点?
备注:m和n小于等于100,并保证计算结果在int范围内
输入:2,1
返回值:1
输入:2,2
返回值:2
#
#
# @param m int整型
# @param n int整型
# @return int整型
#
class Solution:
def uniquePaths(self , m , n ):
# write code here
# 定义二维数组index为[0,1,...,m-1] * [0,1,..,n-1],元素全为1
dp = [[1 for i in range(n)] for j in range(m)]
# dp[i][0] = dp[0][j] = 1不用改,一行或一列的矩阵,都只有一种走法
# 从dp[1][1]开始遍历
for i in range(1,m):
for j in range(1,n):
dp[i][j] = dp[i][j-1] + dp[i-1][j]
return dp[m-1][n-1]
将给出的32位整数x翻转。
例1:x=123,返回321
例2:x=-123,返回-321
你有注意到翻转后的整数可能溢出吗?因为给出的是32位整数,则其数值范围为[−2^{31}, 2^{31} − 1][−231,231−1]。翻转可能会导致溢出,如果反转后的结果会溢出就返回 0。
输入:-123
返回值:-321
#
#
# @param x int整型
# @return int整型
#
class Solution:
def reverse(self , x ):
# write code here
str_x = str(x)
if "-" in str_x:
str_x = str_x.replace("-", "")
return -int(str_x[::-1])
else:
return int(str_x[::-1])
知识点:位运算、数组、数学、二分
从0,1,2,...,n这n+1个数中选择n个数,找出这n个数中缺失的那个数,要求O(n)尽可能小。
输入:[0,1,2,3,4,5,7]
返回值:6
输入:[0,2,3]
返回值:1
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 找缺失数字
# @param a int整型一维数组 给定的数字串
# @return int整型
#
class Solution:
def solve(self , a ):
# write code here
tmp = 0
for i in a:
if i != tmp:
return i-1
tmp += 1
# 若是最后一个数缺失,则返回tmp
return tmp
给定一棵二叉树,判断其是否是自身的镜像(即:是否对称)
例如:下面这棵二叉树是对称的
1
/ \
2 2
/ \ / \
3 4 4 3
下面这棵二叉树不对称。
1
/ \
2 2
\ \
3 3
备注:
希望你可以用递归和迭代两种方法解决这个问题
输入:{1,2,2}
返回值:true
输入:{1,2,3,3,#,2,#}
返回值:false
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
#
#
# @param root TreeNode类
# @return bool布尔型
#
class Solution:
def isSymmetric(self , root ):
# write code here
# 未返回False,遍历到最后,即为True
if not root: return True
return self.compare(root.left, root.right)
# 判断左子树和右子树是否对称
def compare(self, left, right):
# 4种简单情况,直接判断:
if left and not right: return False
elif right and not left: return False
elif not left and not right: return True
elif left and right and left.val != right.val: return False
# 第5种情况:判断子树的子树是否对称
outside = self.compare(left.left, right.right)
inside = self.compare(left.right, right.left)
return outside and inside
知识点链表
删除给出链表中的重复元素(链表中元素从小到大有序),使链表中的所有元素都只出现一次
例如:
给出的链表为1→1→2,返回1→2.
给出的链表为1→1→2→3→3,返回1→2→3.
输入:{1,1,2}
返回值:{1,2}
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
#
#
# @param head ListNode类
# @return ListNode类
#
class Solution:
def deleteDuplicates(self , head ):
# write code here
p=head
q=head
while p and q:
# 若相等,p、q指向同一个,裁剪一个
if q.val == p.val:
p.next = q.next
# 若不等,p正常后移
else:
p = p.next
# q后移带节奏
q = q.next
return head
知识点树、dfs
给定一个二叉树和一个值\ sum sum,判断是否有从根节点到叶子节点的节点值之和等于\ sum sum 的路径,
例如:
给出如下的二叉树,\ sum=22 sum=22,
返回true,因为存在一条路径 5\to 4\to 11\to 25→4→11→2的节点值之和为 22
输入:{1,2},0
返回值:false
输入:{1,2},3
返回值:true
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
#
#
# @param root TreeNode类
# @param sum int整型
# @return bool布尔型
#
class Solution:
def hasPathSum(self , root , sum ):
# write code here
self.sum = sum
if not root:
return False
return self.pre_order(root, 0)
def pre_order(self, root, res):
if not root:
return False
res += root.val
if not root.left and not root.right and res == self.sum:
return True
return self.pre_order(root.left, res) or self.pre_order(root.right, res)
知识点字符串
编写一个函数来查找字符串数组中的最长公共前缀。
输入:["abca","abc","abca","abc","abcc"]
返回值:"abc"
#
#
# @param strs string字符串一维数组
# @return string字符串
#
class Solution:
def longestCommonPrefix(self , strs ):
# write code here
str = ""
if strs == [] or strs == [""]:
return ""
# 遍历第一个元素的每个列
for i in range(len(strs[0])):
# 遍历第一个元素后的元素
for item in strs[1:]:
# 元素不相等或索引到达长度就停止并返回
if len(item) == i or strs[0][i] != item[i]:
return str
str += strs[0][i]
return str
在不使用额外的内存空间的条件下判断一个整数是否是回文数字
提示:
负整数可以是回文吗?(比如-1)
如果你在考虑将数字转化为字符串的话,请注意一下不能使用额外空间的限制
你可以将整数翻转。但是,如果你做过题目“反转数字”,你会知道将整数翻转可能会出现溢出的情况,你怎么处理这个问题?
输入:121
返回值:true
#
#
# @param x int整型
# @return bool布尔型
#
class Solution:
def isPalindrome(self , x ):
# write code here
x_str = str(x)
for i in range(len(x_str)):
# 比较对称的两个位置元素是否相同
if x_str[i] != x_str[len(x_str)-1-i]:
return False
else:
return True
知识点树
给定一棵二叉搜索树,请找出其中的第k小的TreeNode结点。
输入:{5,3,7,2,4,6,8},3
返回值:{4}
说明:按结点数值大小顺序第三小结点的值为4
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 返回对应节点TreeNode
def KthNode(self, pRoot, k):
# write code here
res = self.sortr(pRoot)
if k == 0 or k > len(res):
return None
return res[k-1]
def sortr(self, root):
res = []
# 二叉搜索树按大小排序就是中序遍历:左->中->右
if not root:
return res
res = self.sortr(root.left)
res.append(root)
res += self.sortr(root.right)
return res
知识点字符串
对于一个给定的字符串,我们需要在线性(也就是O(n))的时间里对它做一些变形。首先这个字符串中包含着一些空格,就像"Hello World"一样,然后我们要做的是把着个字符串中由空格隔开的单词反序,同时反转每个字符的大小写。比如"Hello World"变形后就变成了"wORLD hELLO"。
输入描述:
给定一个字符串s以及它的长度n(1≤n≤500)
返回值描述:
请返回变形后的字符串。题目保证给定的字符串均由大小写字母和空格构成。
输入:"This is a sample",16
返回值:"SAMPLE A IS tHIS"
# -*- coding:utf-8 -*-
class Solution:
def trans(self, s, n):
# write code here
s_list = s.split(" ")
s_list.reverse()
res = []
# 遍历每一个单词
for item in s_list:
str = ""
# 遍历每一个字符串
for i in item:
if i.isupper():
i = i.lower()
elif i.islower():
i = i.upper()
str += i
res.append(str)
return " ".join(res)
知识点动态规划
此题讲解:https://www.bilibili.com/video/BV1dp4y1W72d/
给定数组arr,arr中所有的值都为正整数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个aim,代表要找的钱数,求组成aim的最少货币数。
如果无解,请返回-1.
【要求】
输入:[5,2,3],20
返回值:4
输入:[5,2,3],0
返回值:0
输入:[3,5],2
返回值:-1
备注:
#
# 最少货币数
# @param arr int整型一维数组 the array
# @param aim int整型 the target
# @return int整型
#
class Solution:
def minMoney(self , arr , aim ):
# write code here
# 完全背包问题
if aim == 0:
return 0
# dp[i]为给定钱为i时的最小货币
dp = [aim+1] * (aim+1)
dp[0] = 0
for i in range(1, aim+1):
for j in arr:
dp[i] = min(dp[i], dp[i-j]+1)
# 无解
if dp[aim] > aim:
return -1
return dp[aim]
假定你知道某只股票每一天价格的变动。
你最多可以同时持有一只股票。但你可以无限次的交易(买进和卖出均无手续费)。
请设计一个函数,计算你所能获得的最大收益。
输入:[5,4,3,2,1]
返回值:0
说明:由于每天股票都在跌,因此不进行任何交易最优。最大收益为0。
输入:[1,2,3,4,5]
返回值:4
说明:第一天买进,最后一天卖出最优。中间的当天买进当天卖出不影响最终结果。最大收益为4。
备注:总天数不大于200000。保证股票每一天的价格在[1,100]范围内。
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
# 计算最大收益
# @param prices int整型一维数组 股票每一天的价格
# @return int整型
#
class Solution:
def maxProfit(self , prices ):
# write code here
# 简便方法
# 题解:【数据结构和算法】动态规划和贪心算法,图文详解
# 后一个数减前一个数,正数则保留相加,负数去除
total = 0
for i in range(len(prices)-1):
total += max(0, prices[i+1] - prices[i])
return total
知识点树
操作给定的二叉树,将其变换为源二叉树的镜像。
比如: 源二叉树
8
/ \
6 10
/ \ / \
5 7 9 11
镜像二叉树
8
/ \
10 6
/ \ / \
11 9 7 5
输入:{8,6,10,5,7,9,11}
返回值:{8,10,6,11,9,7,5}
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param pRoot TreeNode类
# @return TreeNode类
#
class Solution:
def Mirror(self , pRoot ):
# write code here
if not pRoot: return None
return self.switch(pRoot)
def switch(self, root):
if not root: return None
# 左子树换到右边,右子树换到左边
right = self.switch(root.left)
left = self.switch(root.right)
root.right = right
root.left = left
return root
知识点树
给定彼此独立的两棵二叉树,判断 t1 树是否有与 t2 树拓扑结构完全相同的子树。
设 t1 树的边集为 E1,t2 树的边集为 E2,若 E2 等于 E1 ,则表示 t1 树和t2 树的拓扑结构完全相同。
输入:{1,2,3,4,5,6,7,#,8,9},{2,4,5,#,8,9}
返回值:true
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
#
#
# @param root1 TreeNode类
# @param root2 TreeNode类
# @return bool布尔型
#
class Solution:
def isContains(self , root1 , root2 ):
# write code here
if not root1 and not root2:
return True
if not root1 or not root2:
return False
# 两个完全相同
if self.res(root1, root2):
return True
# root1左子树包含root2,或root1右子树包含root2
return self.isContains(root1.left, root2) or self.isContains(root1.right, root2)
# 判断是否相同
def res(self, root1, root2):
# 完全相同则两个同时为空,否则不相同
if not root1 and not root2:
return True
if not root1 or not root2:
return False
return root1.val == root2.val and self.res(root1.left, root2.left) and self.res(root1.right, root2.right)
知识点树
已知两颗二叉树,将它们合并成一颗二叉树。合并规则是:都存在的结点,就将结点值加起来,否则空的位置就由另一个树的结点来代替。例如:
两颗二叉树是:
Tree 1
1
/ \
3 2
/
5
Tree 2
2
/ \
1 3
\ \
4 7
合并后的树为
3
/ \
4 5
/ \ \
5 4 7
输入:{1,3,2,5},{2,1,3,#,4,#,7}
返回值:{3,4,5,5,4,#,7}
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
#
#
# @param t1 TreeNode类
# @param t2 TreeNode类
# @return TreeNode类
#
class Solution:
def mergeTrees(self , t1 , t2 ):
# write code here
if not t1: return t2
if not t2: return t1
if t1 and t2:
# 合并节点
t1.val = t1.val + t2.val
# 合并左子树
t1.left = self.mergeTrees(t1.left, t2.left)
# 合并右子树
t1.right = self.mergeTrees(t1.right, t2.right)
return t1
知识点树、dfs
给出一个升序排序的数组,将其转化为平衡二叉搜索树(BST).
输入:[-1,0,1,2]
返回值:{1,0,2,-1}
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
#
#
# @param num int整型一维数组
# @return TreeNode类
#
class Solution:
def sortedArrayToBST(self , num ):
# write code here
if not num: return None
return self.treeArray(num, 0, len(num)-1)
def treeArray(self, num, left, right):
if left > right: return None
# 中间的为根节点
mid = (left + right + 1) / 2
root = TreeNode(num[mid])
#root.val = num[mid]
# 左子树为左边半截数组
root.left = self.treeArray(num, left, mid-1)
# 右子树为右边半截数组
root.right = self.treeArray(num, mid+1, right)
return root
知识点模拟
现在有2副扑克牌,从扑克牌中随机五张扑克牌,我们需要来判断一下是不是顺子。
有如下规则:
1. A为1,J为11,Q为12,K为13,A不能视为14
2. 大、小王为 0,0可以看作任意牌
3. 如果给出的五张牌能组成顺子(即这五张牌是连续的)就输出true,否则就输出false。
例如:给出数据[6,0,2,0,4]
中间的两个0一个看作3,一个看作5 。即:[6,3,2,5,4]
这样这五张牌在[2,6]区间连续,输出true
数据保证每组5个数字,每组最多含有4个零,数组的数取值为 [0, 13]
输入:[6,0,2,0,4]
返回值:true
输入:[0,3,2,6,4]
返回值:true
输入:[1,0,0,1,0]
返回值:false
输入:[13,12,11,0,1]
返回值:false
# -*- coding:utf-8 -*-
class Solution:
def IsContinuous(self, numbers):
# write code here
if not numbers:
return False
numbers.sort()
# 记录0的个数
tmp = 0
# 记录差值
cha = 0
for i in range(len(numbers)-1):
if numbers[i] == 0:
tmp += 1
continue
if numbers[i] + 1 < numbers[i+1]:
cha += numbers[i+1]-numbers[i]-1
# 有两个相同的值
elif numbers[i] + 1 > numbers[i+1]:
return False
if tmp < cha:
return False
else:
return True
知识点字符串
在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).(从0开始计数)
输入:"google"
返回值:4
# -*- coding:utf-8 -*-
class Solution:
def FirstNotRepeatingChar(self, s):
# write code here
dict = {}
# 第一次遍历字符串,将每个字符串的次数存入字典。key为字符串,value为字符串出现次数。
for i in range(len(s)):
# dict.get(key, default=None)
# default -- 如果指定键的值不存在时,返回该默认值。
dict[s[i]] = dict.get(s[i], 0) + 1
# 取value为1的key
for i in range(len(s)):
if dict[s[i]] == 1:
return i
return -1
知识点二分
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
输入:[3,4,5,1,2]
返回值:1
# -*- coding:utf-8 -*-
class Solution:
def minNumberInRotateArray(self, rotateArray):
# write code here
# 因为是有序数组旋转,只需要找到第一个比初始值小的数返回即可
for i in rotateArray:
if rotateArray[0] > i:
return i
return 0
知识点数组、二分
统计一个数字在升序数组中出现的次数。
输入:[1,2,3,3,3,3,4,5],3
返回值:4
# -*- coding:utf-8 -*-
class Solution:
def GetNumberOfK(self, data, k):
# write code here
datadict = {}
for i in data:
if i not in datadict.keys():
datadict[i] = 1
else:
datadict[i] += 1
if k in datadict.keys():
return datadict[k]
else:
return 0
知识点哈希
给定一个无序数组arr, 其中元素可正、可负、可0。给定一个整数k,求arr所有子数组中累加和为k的最长子数组长度
输入:[1,-2,1,1,1],0
返回值:3
#
# max length of the subarray sum = k
# @param arr int整型一维数组 the array
# @param k int整型 target
# @return int整型
#
class Solution:
def maxlenEqualK(self , arr , k ):
# write code here
n = len(arr)
if n == 0:
return 0
# 前idx+1个和为sum_val
sum_val = 0
data = {}
# 用哈希存字典,key为sum_val,value为idx
data[0] = -1
max_len = 0
for idx, item in enumerate(arr):
sum_val += item
if sum_val not in data:
data[sum_val] = idx
if (sum_val - k) in data:
# 1、不累加;2、
max_len = max(max_len, idx - data[sum_val - k])
return max_len
知识点数组、数学
给定一个无序数组,包含正数、负数和0,要求从中找出3个数的乘积,使得乘积最大,要求时间复杂度:O(n),空间复杂度:O(1)。
输入:[3,4,1,2]
返回值:24
#
# 最大乘积
# @param A int整型一维数组
# @return long长整型
#
class Solution:
def solve(self , A ):
# write code here
max1 = -999999999
max2 = -999999999
max3 = -999999999
min1 = 999999999
min2 = 999999999
# 三个数的乘积,最大的情况有2种:全为正,选最大的三个;1正2负,正的选最大,负的选最小
# 2种情况选大的返回
for i in A:
# min1最小
if i < min1:
min2 = min1
min1 = i
elif i < min2:
min2 = i
# max1最大
if i > max1:
max3 = max2
max2 = max1
max1 = i
elif i > max2:
max3 = max2
max2 = i
elif i > max3:
max3 = i
res1 = max1 * max2 * max3
res2 = min1 * min2 * max1
return max(res1,res2)
知识点字符串
字符串旋转:
给定两字符串A和B,如果能将A从中间某个位置分割为左右两部分字符串(都不为空串),并将左边的字符串移动到右边字符串后面组成新的字符串可以变为字符串B时返回true。
例如:如果A=‘youzan’,B=‘zanyou’,A按‘you’‘zan’切割换位后得到‘zanyou’和B相同返回true。
输入:"youzan","zanyou"
返回值:true
输入:"youzan","zyouan"
返回值:false
#
# 旋转字符串
# @param A string字符串
# @param B string字符串
# @return bool布尔型
#
class Solution:
def solve(self , A , B ):
# write code here
for i in range(len(A)):
if A[i+1:] + A[0:i+1] == B:
return True
return False
知识点动态规划
已知一个背包最多能容纳物体的体积为V
现有n个物品第i个物品的体积为vi,第i个物品的重量为wi
求当前背包最多能装多大重量的物品
输入:10,2,[[1,3],[10,4]]
返回值:4
说明:第一个物品的体积为1,重量为3,第二个物品的体积为10,重量为4。只取第二个物品可以达到最优方案,取物重量为4
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
# 计算01背包问题的结果
# @param V int整型 背包的体积
# @param n int整型 物品的个数
# @param vw int整型二维数组 第一维度为n,第二维度为2的二维数组,vw[i][0],vw[i][1]分别描述i+1个物品的vi,wi
# @return int整型
#
class Solution:
def knapsack(self , V , n , vw ):
# write code here
# 行为物品数,列为体积
dp = [[0 for j in range(V+1)] for i in range(n+1)]
for i in range(1, n+1):
for j in range(1, V+1):
# 体积太大,不装第i个
if vw[i-1][0] > j:
dp[i][j] = dp[i-1][j]
# 可以装第i个时,装与不装取最大
else:
dp[i][j] = max(dp[i-1][j], dp[i-1][j-vw[i-1][0]] + vw[i-1][1])
return dp[n][V]
知识点位运算
给定一个整型数组 arrarr 和一个整数k(k>1)。
已知 arrarr 中只有 1 个数出现一次,其他的数都出现 kk 次。
请返回只出现了 1 次的数。
输入:[5,4,1,1,5,1,5],3
返回值:4
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param arr int一维数组
# @param k int
# @return int
#
class Solution:
def foundOnceNumber(self , arr , k ):
# write code here
# 排序后,对比前后两个数
arr.sort()
for i in range(len(arr)-1):
if arr[i] != arr[i-1] and arr[i] != arr[i+1]:
return arr[i]
return arr[-1]
知识点二分
请实现无重复数字的升序数组的二分查找
给定一个 元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1
输入:[-1,0,3,4,6,10,13,14],13
返回值:6
说明:13 出现在nums中并且下标为 6
输入:[],3
返回值:-1
说明:nums为空,返回-1
输入:[-1,0,3,4,6,10,13,14],2
返回值:-1
说明:2 不存在nums中因此返回 -1
备注:
数组元素长度在[0,10000]之间
数组每个元素都在 [-9999, 9999]之间。
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param nums int整型一维数组
# @param target int整型
# @return int整型
#
class Solution:
def search(self , nums , target ):
# write code here
if not nums:
return -1
if len(nums) == 1:
if nums[0] == target:
return 0
else:
return -1
if len(nums) == 2:
if nums[0] == target:
return 0
elif nums[1] == target:
return 1
else:
return -1
left = 0
right = len(nums)-1
# 向下取整,靠近右边
mid = len(nums) // 2
while left < right:
if nums[mid] > target:
right = mid
elif nums[mid] < target:
left = mid
else:
return mid
mid = (left + right + 1) // 2
return -1
给定一个数组,请你编写一个函数,返回该数组排序后的形式。
输入:[5,2,3,1,4]
返回值:[1,2,3,4,5]
输入:[5,1,6,2,5]
返回值:[1,2,5,5,6]
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
# 将给定数组排序
# @param arr int整型一维数组 待排序的数组
# @return int整型一维数组
# 参考:https://zhuanlan.zhihu.com/p/63227573
# 题解:快排python手写
class Solution:
def MySort(self , arr ):
# write code here
return self.QuickSort(arr,0,len(arr)-1)
def QuickSort(self,arr,i,j):
# 递归到最后一次,i和j相遇,返回数组
if i>=j:
return arr
# 取第一个元素为基准元素
point=arr[i]
low=i
high=j
while i
给定两个字符串str1和str2,输出两个字符串的最长公共子串
题目保证str1和str2的最长公共子串存在且唯一。
输入:"1AB2345CD","12345EF"
返回值:"2345"
#
# longest common substring
# @param str1 string字符串 the string
# @param str2 string字符串 the string
# @return string字符串
#
class Solution:
def LCS(self,str1 , str2 ):
# write code here
# 让str1是较长的字符串
if len(str1) < len(str2):
str1, str2 = str2, str1
res = ''
max_len = 0
for i in range(len(str1)):
if str1[i - max_len : i+1] in str2:
res = str1[i - max_len : i+1]
max_len += 1
return res
输入:{1,2,3,4,5},2,4
返回值:{1,4,3,2,5}
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
#
#
# @param head ListNode类
# @param m int整型
# @param n int整型
# @return ListNode类
#
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
def reverseBetween(self , head , m , n ):
if m==n:return head
#题目中虽然限制了m和n的条件,节约了我们的代码,但是存在m==n的情况
tmp = ListNode(None)
tmp2 = head
tmp.next = tmp2
for i in range(m-1):#找到第n个位置
tmp = tmp.next
tmp2 = tmp2.next
for i in range(n-m):#逆转m to n的链表
tmp3 = tmp2.next
tmp2.next = tmp3.next
tmp3.next = tmp.next
tmp.next = tmp3
if m==1:return tmp.next #没有这个条件会卡在30%
else :return head