2012-05-09 9 views
5

bir tamsayı için açıktır:Hangi biraz Java (ikili temsil varsa) bir tamsayı üzerinde hangi bitleri kontrol etmek için bu kodu yazdım Java

public static List<String> list(int val) 
{ 
    List<String> dummyList = new ArrayList<String>(); 

    int bit = 1; 
    int x; 

    for(int i=0; i<32; i++) 
    { 
     x = bit; 
     if((x&val)!=0) 
      dummyList.add(String.valueOf(i+1)); 
     bit = bit << 1; 
    } 

    return dummyList; 
} 

yukarıda yazılı kod çalışıyor. Ama 32 kez çalışan bir döngü vardır (Java tamsayı 32 bit uzunluğundadır). Bu karmaşıklığı en aza indirmek istiyorum. Lütfen daha iyi çözümü paylaşın. Şimdiden teşekkürler.

+4

Bu listede ne yapıyorsunuz? Bunun aslında size sorun çıkardığına dair bir işaretiniz var mı? –

+2

iyi, "val" kullanarak döngü sayısını sınırlamak? Eğer int – keyser

+2

biliyorsanız sınırı biliyorsunuz 32 kez döngü yapmak yanlış nedir? 32 bit olduğu için, her bit kontrol etmek için 32 kez dönmelisiniz oldukça mantıklı buluyorum. –

cevap

0

Karmaşıklık O (1) 'dir, bu yüzden orada "en aza indirecek" çok şey yoktur.

Sizin kodunuz tamam .. burada biraz geri yüklenir.

public static List<String> list(int val) { 
    List<String> dummyList = new ArrayList<String>(); 
    for (int i = 0; i < 32; i++) 
     if ((1 << i & val) != 0) 
      dummyList.add("" + (i+1)); 
    return dummyList; 
} 

Btw, bir BitSet kullanarak kabul var?

+0

Kod pasajı için teşekkürler. BitSet'i düşünmedim. BitSet'in kullanımı nedir? – Comet

+1

API belgelerinden daha iyi açıklayamam ;-) – aioobe

+0

Sorun yok. Belgelere bakacak. :) – Comet

0

32 döngü bu uygulama için iyi geliyor. Rakamları daha hızlı toplamak istiyorsanız, Listenin yerine StringBuffer kullanabilirsiniz.

public static String list(int val) 
{ 
    StringBuffer dummyList = new StringBuffer(); 

    int bit = 1; 
    int x; 

    for(int i=0; i<32; i++) 
    { 
     x = bit; 
     dummyList.append((x&val) ? '1' : '0'); 
     bit = bit << 1; 
    } 

    return dummyList.toString(); 
} 
+0

Kod pasajı için ve StringBuffer'ı kullanmanız için öneriniz için teşekkürler. Fakat daha fazla işlem için, daha önce List sınıfında tanımlanan yöntemleri kullanmam gerekiyordu, bu yüzden List'i <> kullanmıştım. – Comet

+0

Algoritmik karmaşıklığı veya duvar saati süresini azaltmaya mı çalışıyorsunuz? Eğer bazı testler yaparsanız, daha hızlı olanla ilgili varsayımlarınızın yanlış olduğunu görebilirsiniz. İşinizin çıkış formatının ne olmasını istediğinize bağlıdır. Belki de dosya tanıtıcılarını bir Haritaya koymaya çalışıyorsunuzdur, bu durumda dosya tanıtıcınızı özel bir hashCode ile genişletmek ve bir HashMap kullanmak daha iyi bir fikir olabilir. Ne yapmaya çalıştığınız ve neden yaptığınız hakkında daha fazla bilgi verin :) – alexg

+0

Her satırda ~ 3000 değer içeren bir dosyam var (X demek). Bu değerleri içeren 2000'den fazla dosya var (Y'ler). Uygulamam için iki dosya arasında hangi değerlerin ortak olduğunu bulmam gerekiyor. Değer kümesi büyük olduğundan, tek tek kontrol etmek uygun değildir. Bu yüzden ön işlem yaptım. İlk olarak 1'den 3000'e kadar X dosyasındaki değerleri indeksledim. Daha sonra 30 değerden oluşan gruplar yaptım (örneğin 0-29, grup 1, 30-59 grup 2 ve benzeri). Daha sonra Y’lerde değerler yazmak yerine, () biçiminde yazdım. – Comet

0

O(1) kodu iyileştirilmesi önemsiz görünüyor ama bu kod biraz ilerleme kaydetmiş durumda:

public static List<String> list(int val) { 
    List<String> dummyList = new ArrayList<String>(); 
    for (int i=0; val!=0 && i<32; ++i){ 
     if ((1 << i & val) != 0) { 
      dummyList.add("" + (i+1)); 
      val &= val -1; // unset the last set bit (current bit) 
     }     // causes loop to end early when all bits are counted 
    } 
    return dummyList; 

Aksine sonra tüm 32 bitlik karşılaştırmalar yaparak

bu kod en kısa sürede son bit sayılır edildiği gibi sona erecektir. 1 s ile seyrek olarak doldurulmuş ve yüksek oranda doldurulmuş olan tamsayılar için daha az verimli olmayan tamsayılar için çok daha verimlidir.

0

Tamsayı uzunluğunu bildiğiniz için, bunun yerine bir bool[] kullanmanızı öneririm. Karmaşıklıkla ilgili yapabileceğiniz çok şey yok. Olabildiğince hızlı ve JIT muhtemelen bu kodun döngüsünü yine de açacak.

public static bool[] list(int val) 
{ 
    bool[] a = new bool[32]; 
    for(int i=0; i<32; i++) 
    { 
     a[i] = ((1 << i) & val) != 0; 
    } 
    return a; 
} 
1

Döngüden geçen süreleri azaltmaya çalışmak için bir bit maskesi kullanabilirsiniz. Birkaç işlemleri eklemek ama potansiyel yarım döngü yapmak.

public static List<String> list(int val) { 
    List<String> dummyList = new ArrayList<String>(); 
    int loop = 32; 

    // Mask the 16 MSB if all are zero only loop on the 16 LSB 
    if((val & 0xFFFF0000) == 0){ 
     loop = 16; 
    } 

    int bit = 1; 
    int x; 

    for (int i = 0; i < loop; i++) { 
     x = bit; 
     if ((x & val) != 0) { 
      dummyList.add(String.valueOf(i + 1)); 
     } 
     bit <<= 1; 
    } 

    return dummyList; 
} 

Bu durum potansiyel olarak veri geliyor bağlı süresini artıracak

Ayrıca aynı anda iki biti yaparak yarısında döngü azaltabilir:

public static List<String> list(int val) { 
    List<String> dummyList = new ArrayList<String>(); 

    int bit = 3; 
    int x; 

    for (int i = 0; i < 32; i += 2) { 
     x = (bit & val); 
     switch (x) { 
      case 1: 
       dummyList.add(String.valueOf(i + 1)); 
       break; 
      case 2: 
       dummyList.add(String.valueOf(i+2)); 
       break; 
      case 3: 
       dummyList.add(String.valueOf(i+1)); 
       dummyList.add(String.valueOf(i+2)); 
       break; 
      default: 
     } 
     val >>= 2; 
    } 

    return dummyList; 
} 
İlgili konular