一、冒泡排序的思想
冒泡排序的过程,就好像咱们喝汽水时,那些小气泡一点一点从下往上的冒,最后到了最顶部。
这只是一种形象的类比,用实际的例子来说明一下。假如有一个列表,其中的数字是无序排列的,
通过冒泡要实现的结果就是将列表中的数字从小到大排序。
那么怎么实现呢?我们可以将列表中左侧第一个和第二个数字先进行比较,将较小的排在左侧;
然后再比较第二个和第三个数字,较小的排在左侧,再比较第三个和第四个......将列表中的数字第一轮比较完之后,
最大的数,排在了列表的最尾端。然后重复上面的步骤,但是尾端最大的数不再参与比较,一轮一轮的比较完之后,
实现将列表中的数字从小到大排序后的效果。这样是不是最小的数一点一点从后往前冒了呢?
冒泡的最优时间复杂度为O(n),最坏时间复杂度为O(n^2)。空间复杂度为O(1)。
那么下面使用代码实现一个冒泡排序:
list1 = [3, 7, 5, 1, 6, 2]
n = len(list1)
for x in range(n-1):
  for y in range(n-1-x):
    if list1[y] > list1[y+1]:
      list1[y], list1[y+1] = list1[y+1], list1[y]
print(list1)

二、快速排序的思想
快速排序的方法和冒泡排序类似,也属于交换排序。也就是通过不断的比较元素之间的大小,
同时不断的交换元素的位置,实现排序的效果。那么它为什么叫快速排序呢?因为它快啊!(......很欠揍的样子)
我们简单的了解一下快速排序。快速排序就是先找到一个基准(一般来说拿列表中的第一个元素先做为基准),
然后利用这个基准,将列表中的元素分为两部分。一部分(这部分中的元素每一个都要比基准大)放在基准的右侧;
另一部分(这一部分中的元素都比基准小)放在基准左侧。第一轮划分完毕,第二轮会将左部分和右部分再次进行第一轮的步骤。
然后不断的划分啊划分啊划分啊......直到最后列表中的元素变成了有序,就结束排序。
看到了上面的步骤是不是发现一个问题?这不就是我们的递归思想吗?对的,稍后我们就利用递归的方法实现一个快速排序。
快速排序的最优时间复杂度为O(nlogn),最坏时间复杂度为O(n^2),空间复杂度为O(logn)。它是不稳定的。
下面使用代码实现一个快速排序:

def quick_sort(list1, left, right):
  if left >= right:
    return None
  n = left
  m = right
  base = list1[n]
  while n < m:
    # 从右边往左边找一个比base小的
    while list1[m] >= base and n < m:
      m -= 1
    if n == m:
      list1[n] = base
    else:
      # 拿小的值填前面的坑
      list1[n] = list1[m]

    # 从左边往右边找一个比base大的
    while list1[n] <= base and n < m:
      n += 1
    if n == m:
      list1[n] = base
    else:
    list1[m] = list1[n]

  # 对左边的进行快排
  quick_sort(list1, left, n-1)
  # 对右边的进行快排
  quick_sort(list1, n+1, right)


if __name__ == '__main__':
  list1 = [3, 7, 5, 1, 6, 2]
  quick_sort(list1, 0, len(list1)-1)
  print(list1)

三、插入排序
插入排序是一种简单直观的排序方法,我想说一句废话(插入排序就是通过插入来实现排序),想了想还是忍住了。
插入排序的思路是什么样的呢?下面且听我慢慢道来。
有一个无序列表,让我们将其中的元素从小到大进行排序。使用插入排序,首先将从左到右的第一个元素所在的区域叫做有序区,
其他的元素在的区域叫做无序区。然后将无序区中的元素从左到右开始取,取出来一个元素就将其放在有序区的合适位置
(比如无序区取了一个3,有序区有两个数字1和4,那么我们就将3放到1和4之间)。不断的从无序区取,向有序区合适位置插,
直到最后无序区没有值了,列表也就变成了有序列表。
最优时间复杂度为O(n),最坏时间复杂度为O(n^2),具有稳定性。
那么用代码实现一个插入排序:

def insert_Sort(arr):
  for i in range(1, len(arr)):
    key = arr[i]
    j = i - 1
    while j >= 0 and key < arr[j]:
      arr[j + 1] = arr[j]
      j -= 1
    arr[j + 1] = key
   print(arr)


if __name__ == '__main__':
  arr = [12, 11, 13, 5, 6, 1]
  insert_Sort(arr)

 

四、二分查找法:

def binary_find(list1, key, m, n):
  while m <= n:
    # 先找到中间的值
    mid = (m+n)//2
    # 拿key和中间值进行比较
    # 如果key比中间值小,则说明key可能在左半部分
    if key < list1[mid]:
      # 左下标不动 右下标n = mid -1
      n = mid - 1
      # 对左半部分就行二分查找
      return binary_find(list1, key, m, n)
    # 如果key比中间值大,则说明key可能在右半部分
    elif key > list1[mid]:
      # 右下标不动, 左下标 m = mid + 1
      m = mid + 1
      # 对右半部分进行二分查找
      return binary_find(list1, key, m, n)
    else:
      return mid
  return -1

if __name__ == "__main__":
  list1 = [2, 4, 6, 8, 10, 12, 14, 16, 18]
  while True:
    key = int(input("请输入需要查找的数字:"))

    index = binary_find(list1, key, 0, len(list1)-1)
    print(index)

 

五、约瑟夫环


list1 = [1, 2, 3, 4, 5, 6, 7, 8]

n = 1
x = 0
while True:
  if x == len(list1):
    x = 0
  while x < len(list1):
    if n % 3 == 0:
      list1.pop(x)
      n += 1
      print(list1)
      break
    else:
      n += 1
      x += 1
  if len(list1) == 1:
    break

 

'''1.韩信点兵:韩信有一队兵,他想知道有多少人,
便让士兵排队报数:按从1至5报数,最末一个士兵报的数为1;
按从1至6报数,最末一个士兵报的数为5;
按从1至7报数,最末一个士兵报的数为4,
请问士兵有多少
'''
# for x in range(1, 1000):
#    if x % 5 == 1 and x % 6 == 4 and x % 7 == 4:
#      print(x)

'''
2、相传韩信才智过人,从不直接清点自己的军队的人数,
只要让士兵先后以三人一排、五人一排、七人一排变换队形,
便知道队伍的总人数,设队尾人数分别为输入的三个非负整数a,b,c(a<3,b<5,c<7),
输出总人数(或无解),总人数为10~100人。
'''
# a = int(input("输入一个数:"))
# b = int(input("输入一个数:"))
# c = int(input("输入一个数:"))
# for x in range(10, 100):
#   if 0 < a < 3 and 0 < b < 5 and 0 < c < 7:
#      if x % 3 == a and x % 5 == b and x % 7 == c:
#        print(x)
#        break
# else:
#    print("无解")

'''
3、尼科彻斯定理:一个整数的立方都可以写成一串连续奇数的和.例如:
1的立方=1
2的立方=3+5
3的立方=7+9+11
4的立方=13+15+17+19
请编程验证该定理(在键盘上输入任意一个数字都能够表示成一串连续奇数的和,
并且将这一串奇数打印出来)
'''
# n = int(input("输入一个整数:"))
# #创建一个列表存储每一项
# list = []
# #第一项
# a = n ** 2 - (n - 1)
# #第二项比第一项大2,最后一项a +(n -1)*2
# for i in range(a, a + n*2, 2):
#   list.append(i)
# print(list)

'''
4、幼儿园老师将糖果分成若干等份,让学生按任意次序领取
,第1个领取的,得到1份加上剩余糖果的1/10;
第2个领取的,得到2份加上剩余糖果的1/10;
第3个领取的,得到3份加上剩余糖果的1/10,........依次类推。
问共有多少个学生?老师将糖果分成了多少等份?
'''
# n = 11
# while True:
#    s1 = (n+9)/10
#    s2 = (9*n+171)/100
#    if s1 == s2:
#     break
#   else:
#      n += 1
# # print("糖果的份数", n)
# # print("学生的数目", int(n/s1))
# print("糖果份数为:", n, "学生数为:", int(n/s1))


'''
5、如果整数A的全部因子(包括1,不包括A本身)之和等于B;
且整数B的全部因子(包括1,不包括B本身)之和等于A,
则将整数A和B称为亲密数。求3000以内的全部亲密数。
'''
#将A的全部因子和 赋值给B, 如果B的所有因子和等于A 说明A和B就是亲密数
# for A in range(1, 3000):
#    B = 0
#    sum = 0
#    for x in range(1, A):
#     if A % x == 0:
#       B += x
#    for y in range(1, B):
#      if B % y == 0:
#        sum += y
#       if sum == A and A <= B:
#          print(A, B)

 

'''
1.一个数如果恰好等于它的因子之和,这个数就称为“完数”。
例如6=1+2+3.编程找出1000以内的所有完数
'''
# for i in range(2, 1000):
#    l1 = []
#    for j in range(1, i):
#     if i % j == 0:
#        l1.append(j)
#        num = sum(l1)
#        if num == i:
#         print(i)
'''
2、在键盘输入一个5位数,判断它是不是回文数。
即12321是回文数,个位与万位相同,十位与千位相同。
'''
# def huiwen():
#   x = int(input("输入一个五位数:"))
#   a = x // 10000
#   b = x // 1000 % 10
#   c = x // 10 % 10
#   d = x % 10
#   if a == d and b == c:
#     print('yes')
#   else:
#     print('no')
# if __name__ == "__main__":
#   huiwen()

 


'''
3.在键盘上输入个坐标x,y,再输入一个半径r,
请打印出以(x,y)作为圆心,半径为r的圆内的所有的点的坐标

 

4.从键盘上输入若干个单词,单词和单词之间用空格隔开,
编程统计单词的个数

空格数加一就是单词个数
'''
src = "h12lo wabld abc abc"
cnt = 0
flag = 1 #默认是单词
blank = 1 # 假设是空格
for x in range(len(src)):
  # 判断一个字符不是字母
  if src[x] < 'A' or src[x] > 'z' or (src[x] > 'Z' and src[x] < 'a'):
    # if src[x]>='A' and src[x] <= 'Z' or src[x]>='a' and src[x] <= 'z':
    # 并且不是空格
    if src[x] != ' ':
      flag = 0 #不是个单词
      blank = 0
    else: # 当前字符是个空格
      # 如果是连续的空格,直接遍历下一个字符
      if blank == 1:
        continue
       #前面的组合是个单词
      if flag == 1:
        cnt += 1
      #假设后面的组合是单词
      flag = 1
      blank = 1
  else: # 当前字符是字母
     blank = 0 # 当前字符不是空格
#如果最后一个元素不是空格 并且flag == 1
if blank == 0 and flag == 1:
  cnt += 1
print(cnt)

 

'''
5、猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,
还不瘾,又多吃了一个第二天早上又将剩下的桃子吃掉一半,
又多吃了一个。以后每天早上都吃了前一天剩下
的一半零一个。到第10天早上想再吃时,见只剩下一个桃子了。
求第一天共摘了多少。
'''
# def fun(n):
#    if n == 1:
#      return 1
#   return (fun(n-1)+1)*2
#
# if __name__ == "__main__":
#    print(fun(10))