此处已经给出了三种解法:勇幸|Thinking 点击打开链接
但是我还是想记录一下。
题目:
A zero-indexed array A consisting of N different integers is given. The array contains all integers in the range [0..N−1]. Sets S[K] for 0 ≤ K < N are defined as follows:S[K] = { A[K], A[A[K]], A[A[A[K]]], ... }. Sets S[K] are finite for each K.
Write a function:
class Solution { public int solution(int[] A); }
that, given an array A consisting of N integers, returns the size of the largest set S[K] for this array. The function should return 0 if the array is empty.
注意:
1) 数组为空,元素为负数
2)A[A[i]]越界
3)环路的发现和终止
4)数组中的所有数字各不相同
实例: a =[1,2,3,9,6,5,8,7,4,11,-1]
环路a[4]=6,a[6]=8,a[8]=4; a[5]= 5;a[7]=7
暴力解法:
a = [1,2,3,9,6,5,8,7,4,11,-1]
flag = []
n = len(a)
def bfcounter(n):
maxv = 0
j = 0
for k in xrange(n):
count = 0
j = k
while j <n and j >=0 and a[j]!=j and flag[j]==False:
count+=1
flag[j]=True
j =a[j]
if j<n and j >=0 and a[j]==j:
count+=1
if count >maxv:
maxv = count
return maxv
for k in xrange(n):
flag.append(False)
maxv = bfcounter(n)
print "max is ",maxv
使用flag标记是否已经被计算过,防止陷入环路中。
另外一种解法是递归的方法,减少重复计算。总的是基于 count(i)=1+count(a[i]),递归计算的同时也要防止陷入环路中。
python 代码:
#!/usr/bin/python
import os
import sys
a = [1,2,3,9,6,5,8,7,4,11,-1]
n =len(a)
flag = []
def countSet(i,M,n):
count =1
j=a[i]
flag[i]=True
if j >=n or j <0 or j ==i:
M[i]=1
return count
if j < n and j >=0 :
if M[j]==0 and flag[j]==False:# not counted and not being computed.
count = 1+countSet(j,M,n)
elif M[j]==0 and flag[j]:
# runs into a cycle,then stop
count =1
M[j]=1
return count
else:
return count
count = 1+M[j]
M[i]=count
return count
return count
def main():
M = []
for k in xrange(n):
M.append(0)
flag.append(False)
maxv = 0
for k in xrange(n):
if M[k]==0:
tmp = countSet(k,M,n)
if tmp >maxv:
maxv = tmp
M[k]=tmp
print "M:",M
print "max set size is ",maxv
if __name__=="__main__":
main()
注意:计算完成后,M中某些对应项的统计量不一定是最终的结果。例如对4,6,8的这个环而言,M[8]=1,M[6]=2,M[4]=3 。这是由于flag的作用。。。。(我说的是不是太白痴了……)
but!反正不影响结果,我们只要最大的嘛~
并查集的解法:
虽然不是第一次看到并查集的讲解,但是却是第一次抄写相关的代码……
python 代码
a = [1,2,3,9,6,5,8,7,4,11,-1] parent =[] n=len(a) num =[] maxv = 0 def findset(x):#x is index?? while (x >=0 and x<n) and x != parent[x]: x=parent[x] if x <0 or x>=n: return -1 return parent[x] def unionset(i,j):#i is index ,j = a[i]?? global maxv x = findset(i) if x <0: return if j <0 or j >=n: num[x]+=1 return y = findset(j) if x ==y: return parent[x]=y num[y]+=num[x] num[x]=num[y] if maxv< num[x]: maxv=num[x] for i in xrange(n): num.append(1) parent.append(i) for i in xrange(n): unionset(i,a[i]) print "num ",num print "maxv ",maxv