twitter online 数组中找集合的问题

此处已经给出了三种解法:勇幸|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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值