Python算法(蓝桥杯备赛)

文章介绍了如何用Python实现回文数判断、数字和计算、杨辉三角生成与查找、阶乘计算、树结构、哈夫曼树、拓扑排序、DFS搜索、消除三角形边和质数检测,以及闰年的判断方法。
摘要由CSDN通过智能技术生成
一、回文数

1、判断是否是回文数

*思路:

  • 对称字符比较
  • x[i]取到某个下标的字符
  • 遍历时range取0~len(str)
#若是回文数则返回1,否则返回0
def reverse(x):
    #x=0则是回文数
    if x == 0:
        return 1
    #x<0则按相反数判断是否是回文数
    if x < 0:
        return reverse(-x)
    #x>0则判断
    if x > 0:
        print(x)
        x = str(x)
        l = len(x)
        sta = 0
        end = l - 1
        for k in range(l):
            if sta <= end:
                if x[sta] == x[end]:
                    sta+=1
                    end-=1
                    continue
                return 0
            return 1
   

2、求各位数字的和

*思路:字符按下标一个个取到并强转为int类型相加

def sumd(x):
    if x < 0:
        return -sumd(-x)
    if x > 0:
        x = str(x)
        sums = 0
        for k in range(len(x)):
            sums += int(x[k])
        return sums
二、杨辉三角

1、生成杨辉三角 

*思路:

  • 第一二行固定,放入一个数组中triangle = [[1], [1, 1]],之后使用triangle.append添加每行
  • 每一行的首尾为1
  • 行数=个数,第n行需要算n-2个数,对应range(n-1)
# 前两行固定
triangle = [[1], [1, 1]]
# c为行
c = 1
while (1):
    c = c + 1
    pre = triangle[c - 1]  # 取上一行
    this = [1]  # 定义每行第一个元素
    for j in range(c - 1):  # 第c行有c个数字,首个定义了是1,最后一个也是1,则还需要计算c-2个元素
        y = pre[j] + pre[j + 1]
        if y == x:
            return count
         # 第0个=0+1;第1个等于1+2
        this.append(y)  # 每个数字等于上一行的左右两个数字之和。
    this.append(1)  # 添加每行最后一个元素
    triangle.append(this)  # 把该行添加到三角里

2、 求杨辉三角第一次出现n是第几个数字:

思路1:只要pre不要triangle,减少内存,但当n很大时运行超时

def adjust():
    x = int(input())
    if x == 1:
        return 1
    else:
        # 前两行固定
        pre = [1, 1]
        c=1
        count=3
        while (1):
            c = c + 1
            this = [1]  # 定义每行第一个元素
            count+=1
            for j in range(c - 1):  # 第c行有c个数字,首个定义了是1,最后一个也是1,则还需要计算c-2个元素
                y = pre[j] + pre[j + 1]
                count += 1
                if y == x:
                    return count
                 # 第0个=0+1;第1个等于1+2
                this.append(y)  # 每个数字等于上一行的左右两个数字之和。
            this.append(1)  # 添加每行最后一个元素
            count += 1
            pre=this  # 把该行变为pre

if __name__ == '__main__':
    n=adjust()
    print(n)

 思路2:如下图,每条斜线的起始n为2、4、6、8,为c上面数字的两倍,而斜线越靠后找到的数字越早,所以对于一个数字x,找到大于等于某个c(n/2,n),小于下一个c((n+1)/2,n+1)的n,在这一斜线上找,找到大于x但没有等于x时换前一条斜线找,直到找到。

此时的x为第(1+n/2)*n/2/2+n

import math
def adjust():
    x=int(input())
    if x==1:
        return 1
    n=0
    while(1):
        # n为上
        n+=1
        y=math.factorial(2*n)//(math.factorial(n)*math.factorial(2*n-n))
        if y==x:
            return (1+2*n)*n+n+1
        if y>x:
            n=n-1
            break
    while(n>0):
        k=2*n
        while(1):
            k=k+1
            y = math.factorial(k) // (math.factorial(n) * math.factorial(k - n))
            if y == x:
                return (1+k) * k/2+n+1
            if y>x:
                n = n - 1
                break

if __name__ == '__main__':
    n=adjust()
    print(int(n))

3、输出杨辉三角前n行

n=int(input())
if n==1:
    print(1)
elif n==2:
    print(1)
    print('1 1')
else:
    print(1)
    print('1 1')
    pre=[1,1]
    row=2
    while(1):
        row+=1
        new=[1]
        for i in range(row-2):
            new.append(pre[i]+pre[i+1])
        new.append(1)
        for i in range(len(new)):
            print(new[i],end=' ')
        print()
        pre=new
        if n==row:
            break
三、阶乘计算

输入一个正整数n,输出n!的值。

1、思路:递归,但问题出在递归深度不能超过1000,所以n大小有限制

def fund(x,y):
    if x > 1:
        y = y * x
        y=fund(x-1, y)
    return y

if __name__=='__main__':
    n = int(input())
    y = fund(n, 1)
    print(y)

2、思路:循环

n = int(input())
y=1
for i in range(2,n+1):
   y=y*i
print(y)
 四、树

1、定义

def BinaryTree(r):
    return [r, [], []]

r为根节点,后面的第一个[]为r的左子树,第二个[]为r的右子树 

 五、哈夫曼树

哈夫曼树是一种用于无损数据压缩的熵编码(权编码)算法,变长编码表是通过一种评估符号出现机率的方法得到的,出现机率高的字母使用较短的编码,反之出现机率低的则使用较长的编码,这便使编码之后的字符串的平均长度、期望值降低,从而达到无损压缩数据的目的。——摘自维基百科

对于A,B,C,D,E五个字符出现的出现的频率(即权值)为数列{pi}={5, 3, 8, 2, 9},Huffman树的构造思路为:每次取两个最小权值作为左右子树构造一个新树,最终构成的树如下:

可见C和E权值较高,编码也就较短,若左0右1,则其编码分别为10和11,而权值较低的D和B编码较长,为000和001。

1、求总费用

n=int(input())
p=list(map(int,input().split(' ')))
# print(p)
sum=0
while(len(p)>=2):
    min1=min(p)
    p.remove(min1)
    min2=min(p)
    p.remove(min2)
    new=min1+min2
    p.append(new)
    sum+=new
print(sum)
六、拓扑排序

拓扑排序是一个有向无环图的所有顶点的线性序列。且该序列满足下面两个条件:

  • 每个顶点出现且只出现一次。
  • 若存在一条从顶点 A 到顶点 B 的路径,那么在序列中顶点 A 出现在顶点 B 的前面。

每次去掉入度为0的顶点及其边,一个有向无环图可以有一个或多个拓扑排序序列,如下图的拓扑排序为12435。

参考拓扑排序(Topological Sorting)-CSDN博客 

所以,若为有向有环图,将会在最后有一些结点入度均不为0(为1),无法排序。 

类比到无向图,若为无向无环图,不分出度入度,统一以度来衡量。从度为1的结点开始遍历,可以完成全部结点的排序,但若为无向有环图,将会在最后有一些结点度均不为1(为2),无法排序。

1、对于题目如下: 

N=int(input())
# tree[i]存放结点i的相邻结点
tree=[[]]
# d[i]存放结点i的度
d=[0]
# cun存放所有结点
cun=[]
for i in range(N):
  tree.append([])
  d.append(0)
  cun.append(i+1)
#将每个结点的相邻结点写入
for i in range(N):
  a,b=map(int,input().split(' '))
  tree[a].append(b)
  tree[b].append(a)
  d[a]+=1
  d[b]+=1
#flag为1结束运行
flag=0
#当还有结点未被去掉
while(len(cun)>0):
  flag1=0
  #遍历每个结点
  for i in range(1,N+1):
    #如果该结点的度为1,则去掉该结点,该结点度-1,与该结点相邻的结点度-1并在tree中去掉该删除的结点
    if d[i]==1:
      flag1=1    
      cun.remove(i)
      d[i]-=1
      d[tree[i][0]]-=1
      tree[tree[i][0]].remove(i)
      continue
    #如果本次对剩余结点的遍历发现度全部不为1,则剩下的组成环,输出
    if i==N and flag1==0:
      for j in range(len(cun)):
        print(cun[j],end=' ')
      flag=1
  if flag==1:
      break
七、dfs

dfs是深度优先搜索(Depth-First Search)的缩写,它是一种图遍历算法。该算法从图的某一顶点开始,沿着图的边不断向下探索,直到不能再继续为止,然后回溯到上一个节点,继续探索其他分支。DFS 通常用于解决图和树的遍历问题,以及与搜索连通性有关的问题。

【蓝桥杯4124】分糖果(dfs&&java)_蓝桥杯分糖果问题dfs思想-CSDN博客

DFS 的递归实现:

题目:输入几个点、几条边,输出删除哪些边可以保证图中没有三角形 

class aa():
  co_list=[]

  def dfs(self,co,i):
    now=tree[i-1]
    for j in range(len(now)):
      if len(co)==3 and now[j]==co[0]:
        if len(self.co_list)==0:
          self.co_list.append(co)
        for n in range(len(self.co_list)):
          if set(co)==set(self.co_list[n]):
            break
          if n==len(self.co_list)-1:
            self.co_list.append(co)
      if now[j] not in co and len(co)<3:
        self.dfs(co+[now[j]],now[j])

a,b=map(int,input().split(' '))
cun=[]
aa=aa()
tree=[]
for i in range(a):
  tree.append([])
for i in range(b):
  x,y=map(int,input().split(' '))
  cun.append([x,y])
  tree[x-1].append(y)
  tree[y-1].append(x)
# print(tree)
for i in range(a):
  co=[i+1]
  aa.dfs(co,i+1)
# print(aa.co_list)
if len(aa.co_list)==0:
  print(b)
  for i in range(b):
    print(i+1,end=' ')
if len(aa.co_list)==1:
  print(3)
  for j in range(len(cun)):
    if set(cun[j])<set(aa.co_list[0]):
      print(j+1,end=' ')
if len(aa.co_list)==2:
  end=set(aa.co_list[0]) & set(aa.co_list[1])
  print(1)
  for j in range(len(cun)):
    if set(cun[j])==end:
      print(j+1)
八、质数
zs=[2,3,5,7,11]
for i in range(12,n):
    for j in range(len(zs)): 
        if i%zs[j]==0:
            # 有可以除尽的,不是质数
            flag=1
            break
    if flag==0:
        zs.append(i)
九、有关日期

闰年:(y % 4 == 0 and y % 100 != 0)  or  (y % 400 == 0)

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值