python算法基础

这篇博客主要介绍了Python的基础算法,包括反转列表和字符串、合并有序列表、排序(如快速排序、冒泡排序)、二分查找以及二叉树的概念。还探讨了不同排序算法的实现和时间复杂度,如插入排序、冒泡排序、快速排序和归并排序,并提到了堆排序。此外,还讲解了二叉树的深度、遍历方式和二分查找的原理。
摘要由CSDN通过智能技术生成

反转链表

合并有序列表

排序(快排 冒泡)

二分查找排序

反转列表 / 字符串

list.reverse()
print(list)
list[::-1]
print(list)

str='abcd'
str[::-1]
print(str)

合并有序列表

给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。

说明:

初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。
你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。

  • 注意:另外题目中也说明了,数组1的空间是足够的,它可以完全容纳下数组1的m个元素和数组2的n个元素。
class Solution(object):
    def merge(self, nums1, m, nums2, n):
        # two get pointers for nums1 and nums2
        p1 = m - 1
        p2 = n - 1
        # set pointer for nums1
        p = m + n - 1
        
        # while there are still elements to compare
        while p1 >= 0 and p2 >= 0:
            if nums1[p1] < nums2[p2]:
                nums1[p] = nums2[p2]
                p2 -= 1
            else:
                nums1[p] =  nums1[p1]
                p1 -= 1
            p -= 1
        
        # add missing elements from nums2
        nums1[:p2 + 1] = nums2[:p2 + 1]


l1 = [1,2,3,0,0,0,0]
l2 = [1,3,5,7]
s=Solution()
s.merge(l1,3,l2,4)

l1

排序

python中sort()的底层是怎么实现的 https://www.cnblogs.com/clement-jiao/p/9243066.html

python经典排序实现 https://blog.csdn.net/sinat_22594309/article/details/79898428

#test
test = [1,7,2,2,4,5,9]

字典排序

dict = {'a':1,'b':2,'c':0}
dict1 = sorted(dict.items(), key=lambda x:x[1])
dict2 = sorted(dict.items(), key=lambda x:x[0])
dict3 = sorted(dict.keys(),key=lambda x:x[0])
dict4 = sorted(dict.values()) #dict4 = sorted(dict.values(),key=lambda x:x)
print(dict1)
print(dict2)
print(dict3)
print(dict4)

列表排序

l = [1,2,3,0,0.5]
l.sort()
print(l)

插入排序

第一个数自然有序不用动,从第二个位置开始,依次向前扫描,如果前面一个数大于该数则交换两者位置,直到首尾置或者前面一个数小于该数,这样有序数组的长度不断增长,直到最后一个位置排序就完成了。

对于插入排序,除了首尾置每个位置要扫描一次,每次扫描的平均长度n/2,所以整体算法的平均复杂度O(n2),假如数组本来就有序,那么只需要n-1次比较即可。由于是两两之间进行比较,不会产生新的逆序,算法是稳定的。

def insert_sort(lst):
    for i in range(1,len(lst)):
        j=i
        num=lst[j]
        while j>0 and lst[j-1]>num:
            lst[j]=lst[j-1]
            j-=1
        lst[j]=num

test = [1,7,2,2,4,5,9]
insert_sort(test)
test

冒泡排序

冒泡排序就是从第一个元素开始,如果其大于下一个元素则交换两个元素的位置,这样一遍扫描下来就将最大的元素移动到了数组的尾部,第二趟忽略第一次找到的那个最大的再从头开始扫描,再次找到最大的将其沉到当前的尾部,如此反复进行下去就可以完成排序。

如果依照上面的算法,冒泡排序每次都需要扫描n趟,每趟扫描的元素数量从n开始递减。整体复杂度是O(n2)。当然还可以做一些优化,比如某一趟扫描中没有发现任何一个逆序那就可以直接终止扫描,数组已经有序了,比如一个已经排好序的数组,只需要一趟扫描,n次比较就可以完成。

def bubble_sort(lst):
    flag=True
    for i in range(len(lst)-1):
        for j in range(1,len(lst)-i):
            if lst[j-1]>lst[j]:
                lst[j],lst[j-1]=lst[j-1],lst[j]
                flag=False
        if flag:
            break

test = [1,7,2,2,4,5,9]
bubble_sort(test)
test

快排

然后将数组中比它小的元素移动到它的左边去,比它大的则移动到右边,然后再分别对左边和右边的数组递归使用快排。这里最主要的一个问题就是如何将数组中的小于标准的移动到左边,大于标准的移动到右边。

  • 通常我们选取首元素作为标准,那么相当于首尾置就空了,先末位置开始往前扫描找到第一个小于标准的数将其移动到首尾置,这下后面又剩下一个空位置,我们再从第二个元素开始往后扫描找到第一个大于标准的数将其移动到后面的空位置上,就这样反复进行,直到这两个位置相交,再将标准移动到小于标准元素的最后一个位置。

  • 当然我们也可以采用另一种简单一点的方式,分别用两个坐标表示小于标准元素和大于标准元素的最后一个位置,然后从标准后的元素开始扫描,如果该元素小于标准,则小于标准元素的最后位置坐标+1,交换那个位置和当前位置的元素,扫描到数组尾部,再交换标准元素和小于标准元素的最后一个位置。

快排的效率和元素划分的关系很大,如果每次都是划分成相等的两段那么复杂度大概在O(nlog(n)),如果每次划分只是将标准划分出去,那么需要的复杂度就是O(n2)。但是抽象地看,快排这种划分其实就是二叉树,其平均高度应该是O(og(n)),那么整体的平均复杂度应该是O(nlog(n))。快排明显是不稳定的,因为在依据标准划分成两部分的时候很有可能产生新的逆序,所以对于快排而言即使原序列非常接近有序也不会使其变得更加高效。

def quick_sort1(lst,l,r):  # l=0,r=len(lst)-1
    if l>=r:
        return
    i=l #设置两个指针i,j指向数组的左右两边
    j=r
    pivot=lst[i] #选择最右作为标准元素
    while i<j:
        while i<j and lst[j]>=pivot:
            j-=1
        if i<j:
            lst[i],lst[j]=lst[j],lst[i]
            i+=1
        while i<j and lst[i]<=pivot:
            i+=1
        if i<j:
            lst[i],lst[j]=lst[j],lst[i]
            j-=1
        lst[i]=pivot
        quick_sort1(lst,l,i-1)
        quick_sort1(lst,i+1,r)
            
            
def quick_sort2(lst,start,end): #start=0,end=len(lst)-1
    if start>=end:
        return
    pivot=lst[start]
    i=start
    for j in range(start+1,end+1):
        if lst[j]<pivot:
            i+=1 #i标注最后一个小于pivot的元素位置
            lst[i],lst[j]=lst[j],lst[i] # 交换后 lst[i]<pivot lst[j]>pivot
    lst[start],lst[i]=lst[i],lst[start]
    quick_sort2(lst,start,i-1)
    quick_sort2(lst,i+1,end)
            

test = [9,1,0,7,2,2,4,5,9]
quick_sort2(test,0,8)
test

二叉树

二叉树遍历(含非递归)  https://blog.csdn.net/feishicheng/article/details/81565933

class Node():
    def __init__(self,x):
        self.val=x
        self.left=None
        self.right=None

深度

def depth(root):
    if root is None:
        return 0
    else:
        return 1 + max(depth(root.left),depth(root.right))

先序遍历

构造一个二叉树的总体路线为根节点->左子树->右子树

def pre_order(root):
    if root is None:
        return
    else:
        print(root.val)
        pre_order(root.left)
        pre_order(root.right)

#非递归 用堆栈--先进后出
def pre_order_none_recur(root):
    if not root:
        return
    stack = [root]
    while stack:
        cur = stack.pop()
        print(cur.val)
        if cur.right:
            stack.append(cur.right<
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值