入门级难度的几道题目
简单乘法->斐波那契数列->链表->整数排序->二叉树
一点一点过度, 让思维进入到刷题状态.
矩阵面积
实现一个矩阵类Rectangle,包含如下的一些成员变量与函数:
两个共有的成员变量 width 和 height 分别代表宽度和高度。
一个构造函数,接受2个参数 width 和 height 来设定矩阵的宽度和高度。
一个成员函数 getArea,返回这个矩阵的面积。
python3.5
import os
class ReactAngle():
width = None
height = None
def __init__(self, *args):
self.width = args[0]
self.height = args[1]
def getArea(self):
if self.width < 0 or self.height < 0 or self.width == None or self.height == None:
raise AssertionError("参数错误")
return self.width * self.height
react = ReactAngle(1,1)
print(react.getArea())
斐波那契数列
斐波那契数列, 查找斐波那契数列中的第N个数.
所谓斐波那契数列是指.
前两个数是0,1
第i个数是第i-1个数和第i-2个数的和.
举例前十个数字
0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ...
输出举例
in 1 out 0,
in 3 out 1
in 10 out 34
递归解法
def fibonacci_recursion(n):
if n < 1:
return None
if n == 1:
return 0
if n == 2:
return 1
return fibonacci_recursion(n - 1) + fibonacci_recursion(n - 2)
print(fibonacci_recursion(11))
循环解法
def fibonacci(n):
if n < 1 or not isinstance(n, int):
return None
if n == 1:
return 0
elif n == 2:
return 1
previousNum0 = 0
previousNum1 = 1
result = None
for i in range(n - 2):
result = previousNum0 + previousNum1
previousNum0 = previousNum1
previousNum1 = result
return result
print(fibonacci(11))
动态规划+递归(动态规划的思想优化递归过程)
def fibonacci_recursion_guihua(array, n):
if n < 1:
return None
if n == 1:
array[1] = 0
return 0
if n == 2:
array[2] = 1
return 1
try:
if array[n] != None and array[n] >= 0:
return array[n]
except Exception as e:
pass
array[n] = fibonacci_recursion_guihua(array, n - 1) + fibonacci_recursion_guihua(array, n - 2)
return fibonacci_recursion_guihua(array, n - 1) + fibonacci_recursion_guihua(array, n - 2)
array = {}
print(fibonacci_recursion_guihua(array, 11))
删除链表中的元素
删除链表中等于给定值val的所有节点。
给出链表 1->2->3->3->4->5->3, 和 val = 3, 你需要返回删除3之后的链表:1->2->4->5。
思路: 定义链表结点, 构造链表, 编写删除函数, 链表使用不带头结点的单向链表.
python3.5
# 定义结点
class ListNode:
val = None
next = None
def __init__(self, val, next):
self.val = val
self.next = next
# 构造链表函数
def createList(param=[]):
firstNode = None
lastNode = None
if not isinstance(param, list) or param == []:
return None
for i in param:
node = ListNode(i, None)
if firstNode == None:
firstNode = node
lastNode = node
else:
lastNode.next = node
lastNode = node
return firstNode
# 输出链表以查看删除结果
def printList(list):
print(id(list))
while(list != None):
print(list.val)
list = list.next
param = [3,3,3,3,1,2,3,4,5,6,5,7,8,9,3]
List = createList(param)
printList(List)
# 删除函数
def removeVal(list, val):
finalList = list
previousNode = None
while(list != None):
if list.val == val:
if previousNode == None:
finalList = list.next
else:
previousNode.next = list.next
else:
previousNode = list
list = list.next
return finalList
import copy
finalList = removeVal(copy.deepcopy(List), 3)
printList(finalList)
整数排序
给一组整数,按照升序排序, 对于数组 [3, 2, 1, 4, 5], 排序后为:[1, 2, 3, 4, 5]
排序算法很多种, 都试一下吧.
首先给出待排序数组
data = [22,2,2,88,8,985,47,12,5544,63,52,48,41,22,33,69,8,52,7,4,1,4,47,47,22,2]
插入排序
插入排序大致思路是依次取各个元素, 遍历 以排序部分, 将新元素插入到以排序部分的合适位置. 整个数组中左侧为以排序部分, 右侧为待排序部分.
最终返回的是原始数组对象, 并没有返回新对象, 仅操作原数组中的元素完成排序.
python3.5
data = [22,2,2,88,8,985,47,12,5544,63,52,48,41,22,33,69,8,52,7,4,1,4,47,47,22,2]
def insertSort(data):
location = 0
if not isinstance(data, list):
return None
for i in range(1, len(data)):
for x in range(location + 1):
if data[x] == data[i]:
val = data[i]
del data[i]
data.insert(x+1, val)
continue
elif data[x] > data[i]:
val = data[i]
del data[i]
data.insert(x, val)
continue
if x == location:
val = data[i]
del data[i]
data.insert(x+1, val)
location = location + 1
print(data)
insertSort(data)
print(data)
选择排序
选择排序大致思路, 是每次选出最小值和以排序部分的最右侧进行交换
data = [22,2,2,88,8,985,47,12,5544,63,52,48,41,22,33,69,8,52,7,4,1,4,47,47,22,2]
def chooseSort(data):
if not isinstance(data, list):
return None
for i in range(len(data)):
minNum = None
maxNumLocation = None
for x in range(i, len(data)):
if minNum == None:
minNum = data[x]
maxNumLocation = x
if data[x] < minNum:
minNum = data[x]
maxNumLocation = x
if minNum == None:
raise AssertionError("没有选出最小值")
del data[maxNumLocation]
data.insert(i, minNum)
print(data)
chooseSort(data)
print(data)
冒泡排序
冒泡排序思路, 进行n次交换, 每一轮交换意味着待排序数组中的最大值已经被交换到最顶端.
def bubblingSort(data=[]):
if data == [] or not isinstance(data, list):
return None
for x in range(len(data)):
for y in range(len(data)-x-1):
if data[y] > data[y+1]:
data[y], data[y+1] = data[y+1], data[y]
print(data)
bubblingSort(data)
print(data)
希尔排序
希尔排序是基于一个事实, 类似分代收集法, 是基于越先创建的对象越不容易被销毁, 希尔排序是基于, 数组整体越接近有序, 则插入排序的效率就越高.
increment = [8,3,1] #增量序列
def shellSort(data=[]):
for x in increment:
location = 0
while(location*x < len(data)):
# val = data[location+1 * x]
array = list(range(0, len(data), x))
for y in range(0, len(data), x)[:-1]:
# 插排过程
if data[y+x] < data[y]:
# 此时需要将有序数组右移空出位置
val = data[y+x]
i = 1
sentry = y
while(sentry < y+x):
data[y+x] = data[y+x-(i*x)]
sentry = sentry+i*x
i = i+1
data[y] = val
location = location +1
print(data)
shellSort(data)
print(data)
快速排序
快速排序首先选出基准元素, 然后把数组按基准元素分为左右两侧, 左右两侧再分别选出基准元素, 再次分隔, 递归进行此过程 直到待分隔数组中只有一个元素为止.
def quickSort(data=[], start=0, end=0):
standard = data[start]
height = start + 1
standardLocation = start
if height >= end:
return
while(height < end):
if data[height] < standard:
val = data[height]
del data[height]
data.insert(standardLocation, val)
standardLocation = standardLocation + 1
height = height + 1
quickSort(data, start, standardLocation)
quickSort(data, standardLocation+1, end)
print(data)
quickSort(data, 0, len(data))
print(data)
归并排序
归并排序的核心思想是归并操作, 归并操作是指将两个有序数组合并为一个有序数组的过程, 先进行分隔, 分隔到最底层, 每个有序数组只有1个元素,两个元素之间归并自然有序, 这样依次进行归并操作.
def mergeSort(data=[], left=0, right=0):
if not isinstance(data, list):
return None
if left >= right:
return
mid = int((left+right)/2)
mergeSort(data, left, mid)
mergeSort(data, mid+1, right)
# 归并操作
temp = []
pointer0 = left
pointer1 = mid+1
i = 0
while(pointer0 <= mid and pointer1 <= right):
if data[pointer0] == data[pointer1]:
temp.append(data[pointer0])
temp.append(data[pointer1])
pointer0 = pointer0 + 1
pointer1 = pointer1 + 1
elif data[pointer0] < data[pointer1]:
temp.append(data[pointer0])
pointer0 = pointer0 + 1
# else:
elif data[pointer1] < data[pointer0]:
temp.append(data[pointer1])
pointer1 = pointer1 + 1
# 此时还有一种可能就是 二路归并的时候, 一路已经走完了. 上面的
# 循环 一路走完就break 此时如果一路长度大于另一路, 大一路中的剩余元素没有被添加到辅助temp空间中.
while(pointer0 <= mid):
temp.append(data[pointer0])
pointer0 = pointer0 + 1
while(pointer1 <= right):
temp.append(data[pointer1])
pointer1 = pointer1 + 1
x = 0
while(x < len(temp)):
data[left+x] = temp[x]
x = x + 1
print(data)
mergeSort(data, 0, len(data)-1)
print(data)
堆排序
堆排序就是利用二叉树进行排序, 构造二叉树, 根据升序, 降序, 选择大根堆, 小根堆, 将根节点和末尾界定啊交换, 输出, 再调整二叉树到大根堆(小根堆), 重复此过程.
小根堆的构造, 类似于冒泡排序的思想, 从第一个非叶子结点开始遍历二叉树判断它的两个叶子结点, 如果存在右孩子, 判断它与右孩子的大小, 做交换, 再判断它与做孩子的大小做交换, 如果不存在右孩子, 直接与做孩子比较做交换, 依次向上直到根节点, 交换完毕, 根节点就是当前树中的最小节点, 输出根, 将它与末尾结点做交换, 下一次遍历过程不遍历末尾已经输出的结点.
data = [22,2,2,88,8,985,47,12,5544,63,52,48,41,22,33,69,8,52,7,4,1,4,47,47,22,2]
def heapSort(data=[]):
if not isinstance(data, list):
raise AssertionError("传入参数类型必须为list")
result = []
x = 0
while (x < len(data)):
# 构造小根堆. 首先将数组看做是一个完全二叉树的存储结构. 对其进行改造
# 从第一个非叶子节点开始向根节点遍历. 此节点一定有左孩子不一定有右孩子.
for i in range(0, int((len(data)-x)/2))[::-1]:
temp = data[i] #当前节点
leftChild = data[i*2+1] #因为数组从0开始所以要+1
# 判断是否有右孩子.
if i*2+2 < len(data) - x:
# 有右孩子
if data[i*2+1] < data[i*2+2]:
if data[i*2+1] < temp:
data[i], data[i*2+1] = data[2*i+1], data[i]
else:
if data[i*2+2] < temp:
data[i], data[i*2+2] = data[2*i+2], data[i]
else:
if leftChild < temp:
data[i], data[i*2+1] = data[2*i+1], data[i]
# 堆构造完毕
result.append(data[0])
data[0], data[len(data)-x-1] = data[len(data)-x-1], data[0]
x = x+1
return result
# md最后还是没忍住 操作了data, 由于每次和最后一个元素交换, 所以data 是逆序的.
print(data)
print(heapSort(data))
print(data)
基数排序
也叫木桶排序, 首先计算各个数字的各位, 按照个位大小值分别放入不同的"桶"中, 再将桶中的数据按照桶的大小顺序, 顺序排列, 再计算10位的值, 再计算100位的值, 一次类推, 直到计算完最大数字的最大位, 最后得到的数组是有序的.
data = [22,2,2,88,8,985,47,12,5544,63,52,48,41,22,33,69,8,52,7,4,1,4,47,47,22,2]
def radixSort(data=[]):
if not isinstance(data, list):
raise AssertionError("出入参数必须为list类型")
# 待排序数组中最大数字的 数值量级(是10的多少次方的量级) 求出指数
# 我不愿意使用 数字转字符串的形式计算量级, 都使用数字的运算来搞定它吧.
exponent = 0
for i in data:
iexponent = 0
for e in range(0,100): #恐怕10**100 在python中int已经溢出了. 先不管它.
if i / (10**e) > 1:
iexponent = e
if iexponent > exponent:
exponent = iexponent
#量级计算完毕 创建"桶" 基数排序? 木桶排序?
bucket = []
for i in range(10):
ibucket = []
bucket.append(ibucket)
for i in range(0, exponent+2):
dividend = 10**i
for x in data:
val = x % dividend
val = int(val / (dividend / 10))
bucket[val].append(x)
# 分配完毕将 木桶中的数字重新放入数组中
data.clear()
for x in bucket:
for y in x:
data.append(y)
# 按照某个次方数 排序完毕 清理木桶空间
for x in bucket:
x.clear()
print(data)
radixSort(data)
print(data)
二叉树的最大结点
在二叉树中寻找值最大的节点并返回。
遍历二叉树即可, 此处仅考虑二叉树的链式存储结构, 不考虑顺序存储结构.
import queue
class TreeNode():
val = None
leftNode = None
rightNode = None
def __init__(self, val, left, right):
self.val = val
self.leftNode = left
self.rightNode = right
data = [3,4,6,234,5,66,4,98,1002,8990,456,65]
# 使用队列做辅助, 层序构建二叉树.
def createTree(data=[]):
que = queue.Queue()
root = TreeNode(data[0],None, None)
que.put(root)
i = 1
while(i < len(data)):
if not que.empty():
node = que.get()
if node.leftNode == None:
nNode = TreeNode(data[i], None, None)
node.leftNode = nNode
que.put(nNode)
i = i+1
if (i) < len(data) and node.rightNode == None:
nNode = TreeNode(data[i], None, None)
node.rightNode = nNode
que.put(nNode)
i = i+1
else:
return root
return root
root = createTree(data)
class traverse():
maxNode = None
def beforeTraverse(self, root):
if not isinstance(root, TreeNode):
raise AssertionError("传入参数必须是二叉树的根节点")
if self.maxNode == None:
self.maxNode = root
if root.val != None and self.maxNode.val != None and self.maxNode.val < root.val:
self.maxNode = root
if root.leftNode != None:
self.beforeTraverse(root.leftNode)
if root.rightNode != None:
self.beforeTraverse(root.rightNode)
return self.maxNode
def middleTraverse(self, root):
if not isinstance(root, TreeNode):
raise AssertionError("传入参数必须是二叉树的根节点")
if self.maxNode == None:
self.maxNode = root
if root.leftNode != None:
self.middleTraverse(root.leftNode)
print(root.val)
if root.val != None and self.maxNode.val != None and self.maxNode.val < root.val:
self.maxNode = root
if root.rightNode != None:
self.middleTraverse(root.rightNode)
return self.maxNode
def backTraverse(self, root):
if not isinstance(root, TreeNode):
raise AssertionError("传入参数必须为二叉树的根节点")
if self.maxNode == None:
self.maxNode = root
if root.leftNode != None:
self.backTraverse(root.leftNode)
if root.rightNode != None:
self.backTraverse(root.rightNode)
print(root.val)
if root.val != None and self.maxNode.val != None and self.maxNode.val < root.val:
self.maxNode = root
return self.maxNode
obj = traverse()
print(obj.backTraverse(root).val)
翻转二叉树
递归法
def invertBinaryTree(root):
if root == None:
return
root.leftNode, root.rightNode = root.rightNode, root.leftNode
invertBinaryTree(root.leftNode)
invertBinaryTree(root.rightNode)
invertBinaryTree(root)
栈辅助
def invertTree(root):
stack = [root]
while len(stack) > 0:
node = stack.pop()
if node != None:
continue
# 维持先序的二叉树遍历过程
root.leftNode, root.rightNode = root.rightNode, root.leftNode
if root.rightNode:
stack.append(root.rightNode)
if root.leftNode:
stack.append(root.leftNode)
invertTree(root)
队列辅助
def queueInvertTree(root):
que=queue.Queue()
que.put(root)
while(not que.empty()):
# 交换, 然后子结点入队列, 其实和栈是一样的.
root = que.get()
root.leftNode, root.rightNode = root.rightNode, root.leftNode
if root.leftNode:
que.put(root.leftNode)
if root.rightNode:
que.put(root.rightNode)
queueInvertTree(root)