简单算法 (二分查找、冒泡排序、快速排序,斐波那契数列。。。等)
二分查找
普通
def BinarySearch(nums,x):
'''
nums: 列表数组
x: 目标数字
'''
left,right = 0,len(nums)-1
while left <= right:
mid = (left+right)//2
if nums[mid] == x:
return mid
if nums[mid] < x:
left = mid+1
else:
right = mid-1
#如果不存在返回-1
return -1
递归方式
# 如果目标数字在集合中返回下标,否则返回-1
def numsearch(arr, x, start=0, end=None):
end = len(arr)-1 if end == None else end
if start <= end:
mid = start + (end - start) // 2
if arr[mid] == x:
return mid
elif arr[mid] > x:
return numsearch(arr, x, start=start, end=mid - 1)
else:
return numsearch(arr, x, start=mid + 1, end=end)
else:
return -1
arr = [11,22,44,33,55,66]
result = numsearch(arr,44)
print(result)
冒泡排序
原理:比较两个相邻的元素,将值大的元素交换到右边,第一轮比完后最后一个数一定是最大值,最后一个数无需再进行比较,第二轮过后倒数第二个数一定是第二大的值,无需再进行比较,以此类推
def sort(arr):
num = len(arr)
for i in range(num):
for j in range(num-1-i):
if arr[j]>arr[j+1]:
arr[j],arr[j+1]=arr[j+1],arr[j]
return arr
选择排序
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
重复第二步,直到所有元素均排序完毕。
def selectionSort(arr):
for i in range(len(arr) - 1):
# 记录最小数的索引
minIndex = i
for j in range(i + 1, len(arr)):
if arr[j] < arr[minIndex]:
minIndex = j
# i 不是最小数时,将 i 和最小数进行交换
if i != minIndex:
arr[i], arr[minIndex] = arr[minIndex], arr[i]
return arr
快速排序
1、
def quick_sort(b):
"""快速排序"""
if len(b) < 2:
return arr
# 选取基准,随便选哪个都可以,选中间的便于理解
mid = arr[len(b) // 2]
# 定义基准值左右两个数列
left, right = [], []
# 从原始数组中移除基准值
b.remove(mid)
for item in b:
# 大于基准值放右边
if item >= mid:
right.append(item)
else:
# 小于基准值放左边
left.append(item)
# 使用迭代进行比较
return quick_sort(left) + [mid] + quick_sort(right)
2、
def partition(arr,low,high):
i = ( low-1 ) # 最小元素索引
pivot = arr[high]
for j in range(low , high):
# 当前元素小于或等于 pivot
if arr[j] <= pivot:
i = i+1
arr[i],arr[j] = arr[j],arr[i]
arr[i+1],arr[high] = arr[high],arr[i+1]
return ( i+1 )
# arr[] --> 排序数组
# low --> 起始索引
# high --> 结束索引
# 快速排序函数
def quickSort(arr,low,high):
if low < high:
pi = partition(arr,low,high)
quickSort(arr, low, pi-1)
quickSort(arr, pi+1, high)
arr = [10, 7, 8, 9, 1, 5]
n = len(arr)
quickSort(arr,0,n-1)
print ("排序后的数组:")
for i in range(n):
print ("%d" %arr[i])
堆排序
堆(定义):(二叉)堆数据结构是一个数组对象,可以视为一棵完全二叉树。如果根结点的值大于(小于)其它所有结点,并且它的左右子树也满足这样的性质,那么这个堆就是大(小)根堆。
斐波那契数列
在数学上,斐波那契数列以如下被以递推的方法定义:F(0)=0,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*)
def recur_fibo(n):
"""递归函数
输出斐波那契数列"""
if n <= 1:
return n
else:
return recur_fibo(n-1) + recur_fibo(n-2)
平衡点
假如一个数组中的元素,其前面的部分等于后面的部分,那么这个点的位序就是平衡点.
比如一个列表 numbers = [1,3,5,7,8,25,4,20],25前面的总和为24,25后面的总和也是24,25这个点就是平衡点;
思路:平衡点两边的数求和相等,也就是sum(lsit)减去这个数之后再除以2等于这个数某一边的数求和,可以用一个变量来累加这个数左边的那一部分序列。
numbers = [2,1,8,4,10,30,55,25,25,5]
def cal(arr):
num = sum(arr)
my_num = 0
for i in arr:
if my_num ==(num-i)/2:
return i
else:
my_num+=i
return -1
rr = cal(numbers)
print(rr)
反转单向链表
# 递归方法
class ListNode(object):
def __init__(self, val):
self.val = val
self.next = None
def nodeRe(head):
if not head or not head.next:
return head
newhead = nodeRe(head.next)
head.next.next = head
head.next = None
return newhead
a = ListNode(1)
a.next = ListNode(2)
a.next.next = ListNode(3)
a.next.next.next = ListNode(4)
s = nodeRe(a)
print(s)
print(s.val, s.next.val, s.next.next.val)
# 双指针迭代,循环
# 我们可以申请两个指针,第一个指针叫 pre,最初是指向 null 的。
# 第二个指针 cur 指向 head,然后不断遍历 cur。
# 每次迭代到 cur,都将 cur 的 next 指向 pre,然后 pre 和 cur 前进一位。
# 都迭代完了(cur 变成 null 了),pre 就是最后一个节点了。
class Solution(object):
def reverseList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
# 申请两个节点,pre和 cur,pre指向None
pre = None
cur = head
# 遍历链表,while循环里面的内容其实可以写成一行
# 这里只做演示,就不搞那么骚气的写法了
while cur:
# 记录当前节点的下一个节点
tmp = cur.next
# 然后将当前节点指向pre
cur.next = pre
# pre和cur节点都前进一位
pre = cur
cur = tmp
return pre