小朋友崇拜圈&&修改数组

题目

班里 N 个小朋友,每个人都有自己最崇拜的一个小朋友(也可以是自己)。

在一个游戏中,需要小朋友坐一个圈,每个小朋友都有自己最崇拜的小朋友在他的右手边。

求满足条件的圈最大多少人?

小朋友编号为 1,2,3,⋯N。

思路

将每个小朋友都作为一个起点,来依次向下进行遍历,同时对已经遍历过的小朋友进行标记,当下一个小朋友是已经遍历过的时候,就表示此时的path中已经有了一个圈了。将栈中的数据一个一个往外pop,来获得这个圈的长度。最后将长度最大的圈进行输出。

我这个还是太暴力了,有两个用例运行超时了。

代码

import os
import sys

# 请在此输入您的代码
sys.setrecursionlimit(1000000) #设置最大递归深度
N = int(input())
a = list(map(int, input().split()))
person = {} #每个小朋友右手边的人以字典进行储存
for i in range(1, N+1):
  person[i] = a[i-1]


def find(x):
  if vist[x] == 1: #该小朋友已被访问过 即形成了一个圈
    now_x  = path.pop()
    rel_path = [] #存储圈中所包含的人
    count = 1
    while now_x != x:
      rel_path.append(now_x)
      count += 1
      now_x = path.pop()
    return count, rel_path

  path.append(x)
  vist[x] = 1
  return find(person[x]) #这里也要有return 不然只有if中的return 返回的是这里调用递归算法的地方 而不是主函数 这样就会返回none

cle = [] #记录形成的圈里面的点
out = [] #记录以每个点为起点可以形成圈的长度
# vist = [0 for i in range(N+1)]
for i in range(1, N+1):
  if i in cle : # 这些点就不用遍历了,因为这些点都在圈里面 不用再遍历一遍
    continue
  global vist #标记每个人是否已在当前圈里面
  vist = [0 for i in range(N+1)]
  global path # 记录以当前点位起点的圈
  path = []
  out_1, cle_1 = find(i)
  out.append(out_1)
  cle.append(x for x in cle_1)

print(max(out))

后面再写了一次

import os
import sys
sys.setrecursionlimit(1000000) #设置最大递归深度
# 请在此输入您的代码
def dfs(x):
  global cir_len
  if point[person[x]] == 1: # 当前小朋友崇拜的小朋友被访问过 形成一个圈 结束条件
    temp = len(path) - path.index(person[x]) #计算圈的长度 整个路径的长度-闭合的另一个点在path中的位置 如5的崇拜对象为3 即在路径中3的位置 进行相减
    cir_len.append(temp)
    return True

  if point[person[x]] == 0: #当前小朋友崇拜的小朋友 没有被访问过
    point[person[x]] = 1
    path.append(person[x])
    dfs(person[x]) #这里没有去撤销 就是因为每个起点单独拥有一个point path矩阵
  #   point[person[x]] = 0 #如果全局只有一个point 则遍历完后需要撤销已访问操作

  # point[x] = 0 #如果全局只有一个point 则遍历完后需要撤销已访问操作

  return 

N = int(input())
a = list(map(int, input().split()))
person = {} #每个小朋友右手边的人以字典进行储存
for i in range(1, N+1):
  person[i] = a[i-1]

cir_len = [] #保存每个圈的长度
# point = [0 for i in range(N+1)] 全局只有一个point矩阵
for i in range(1, N+1):
  point = [0 for i in range(N+1)]
  path = [i] #记录每个圈中的结点
  point[i] = 1 #初始化起点已被访问
  dfs(i)

print(max(cir_len))

Tips:递归调用的时候,要注意return,调用的最外层也需要return函数,这样才是返回到主函数中。 

题目

给定一个长度为 N 的数组A=[A1​,A2​,⋅⋅⋅,AN​],数组中有可能有重复出现的整数。

现在小明要按以下方法将其修改为没有重复整数的数组。小明会依次修改A2​,A3​,⋅⋅⋅,AN​。

当修改Ai​ 时,小明会检查Ai​ 是否在A1​ ∼Ai​−1 中出现过。如果出现过,则小明会给Ai​ 加上 1 ;如果新的Ai​ 仍在之前出现过,小明会持续给Ai​ 加 1 ,直 到 Ai​ 没有在 A1​ ∼ Ai​−1 中出现过。

当 AN​ 也经过上述修改之后,显然 A 数组中就没有重复的整数了。

现在给定初始的A 数组,请你计算出最终的A 数组。

思路

只会暴力,呜呜呜!查并集这个东西我都没听过,通过测试用例4个。 

代码 

import os
import sys

# 请在此输入您的代码

N = int(input())
datas = list(map(int, input().split()))
flag = [0 for i in range(10000000)] #标记该数字是否已存在
j = 0
for i in datas:
  if flag[i] == 0: #该数第一次出现 
    flag[i] = 1 #标记后进入下一次循环
    j += 1 #记录当前下标 用于修改当前值
    continue
  while flag[i] == 1: #该数第二次出现 则一直+到没有出现的数
    i += 1
  flag[i] = 1
  datas[j] = i #修改当前值
  j += 1

for i in datas:
  print(i , end = ' ')

 别人的代码(半懂不懂的 应该是引入数组fa表示本位置插入元素后,下一个等值元素应该插入的位置):

import os
import sys

# 请在此输入您的代码

N = int(input())
A = list(map(int, input().split()))

def find(x):
    global fa
    if fa[x] != x:  # 只有当前fa[x] = x 表示才能将x放在当前位置 否则就要一层层去找可以放的位置
        fa[x] = find(fa[x])
    return fa[x]

# 首先创建数组大小的并查集序列 fa[i]表示,i=x产生冲突时应该将冲突的第二个x值放入的位置
fa = [i for i in range(1000001)]

for i in range(N):
    A[i] = find(A[i])
    fa[A[i]] = find(A[i] + 1)  # 该元素放好好,要更新fa表 将该元素的fa更新为它后一个位置冲突后的插入位置
    #print("i =" + str(A[i]) + ":" + str(fa)) 将当前fa打印出来 更好理解一点

for i in A:
  print(i, end=' ')

絮絮叨:300复300,300何其多啊!感觉这次真打水漂了! 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值