【leetcode】Count Primes

【題目】

Description:

Count the number of prime numbers less than a non-negative number, n.

Credits:
Special thanks to @mithmatt for adding this problem and creating all test cases.

Hint:

Let's start with a isPrime function. To determine if a number is prime, we need to check if it is not divisible by any number less than n. The runtime complexity of isPrime function would be O(n) and hence counting the total prime numbers up to n would be O(n2). Could we do better?


【思路】

素數不能被比它小的整數整除, 建一個boolean 數組, 從2開始, 把其倍數小於N的都刪掉.

注意 inner loop從i開始, 比i小的會在以前就被check過.


【代碼】

O(n):Count the number of prime numbers less than a non-negative number, n

public class Solution {
    public int countPrimes(int n) {
        int res = 0;   //用來記錄prime的個數
        boolean[] used = new boolean[n]; //創建n大小的數組,用來記錄數字有沒有被標記的情況。
        for (int i = 2; i <= Math.sqrt(n); i++) {  // i 從2 開始,到 Square(n)
         if (!used[i]) { //只要i 這個地方仍舊是false:那麼刪除是這個數倍數 的 一切相關數字。
            for( int j = i ; i *j <n;j++){
                  used[i*j] = true;  //該數的倍數,都進行設置。
              }
           }
        }

//遍歷一遍,數prime的個數。
        for (int i = 2; i < n; i++) { 
        if (!used[i - 1]) {
            res++;
        }
        }
        return res;
    }
}

另一個種方法:

bitset不知道是個什麼鬼

public int countPrimes(int n) {
    BitSet bs = new BitSet(n);
    bs.set(0); bs.set(1);
    int ind = 0, count = 0;
    while(ind < n){
        ind = bs.nextClearBit(ind + 1);
        if(ind >= n)
            return count;
        count++;
        for(int i = 2 * ind; i < n; i += ind)
            bs.set(i);
    }
    return count;
}

(1)BitSet類
    大小可動態改變, 取值爲true或false的位集合。用於表示一組布爾標誌。   

此類實現了一個按需增長的位向量。位 set 的每個組件都有一個 boolean 值。用非負的整數將 BitSet 的位編入索引。可以對每個編入索引的位進行測試、設置或者清除。通過邏輯與、邏輯或和邏輯異或操作,可以使用一個 BitSet 修改另一個 BitSet 的內容。

默認情況下,set 中所有位的初始值都是 false。

  每個位 set 都有一個當前大小,也就是該位 set 當前所用空間的位數。注意,這個大小與位 set 的實現有關,所以它可能隨實現的不同而更改。位 set 的長度與位 set 的邏輯長度有關,並且是與實現無關而定義的。

   除非另行說明,否則將 null 參數傳遞給 BitSet 中的任何方法都將導致 NullPointerException。 在沒有外部同步的情況下,多個線程操作一個 BitSet 是不安全的。

(2) 構造函數: BitSet() or BitSet(int nbits)

(3) 一些方法 
public void set(int pos): 位置pos的字位設置爲true。 
public void set(int bitIndex, boolean value) 將指定索引處的位設置爲指定的值。 
public void clear(int pos): 位置pos的字位設置爲false。
public void clear() : 將此 BitSet 中的所有位設置爲 false。 
public int cardinality() 返回此 BitSet 中設置爲 true 的位數。 
public boolean get(int pos): 返回位置是pos的字位值。 
public void and(BitSet other): other同該字位集進行與操作,結果作爲該字位集的新值。 
public void or(BitSet other): other同該字位集進行或操作,結果作爲該字位集的新值。 
public void xor(BitSet other): other同該字位集進行異或操作,結果作爲該字位集的新值。
public void andNot(BitSet set) 清除此 BitSet 中所有的位,set - 用來屏蔽此 BitSet 的 BitSet
public int size(): 返回此 BitSet 表示位值時實際使用空間的位數。
public int length() 返回此 BitSet 的“邏輯大小”:BitSet 中最高設置位的索引加 1。 
public int hashCode(): 返回該集合Hash 碼, 這個碼同集合中的字位值有關。 
public boolean equals(Object other): 如果other中的字位同集合中的字位相同,返回true。 
public Object clone() 克隆此 BitSet,生成一個與之相等的新 BitSet。 
public String toString() 返回此位 set 的字符串表示形式。

例1:標明一個字符串中用了哪些字符
import java.util.BitSet;
public class WhichChars{
   private BitSet used = new BitSet();
   public WhichChars(String str){
      for(int i=0;i< str.length();i++)
        used.set(str.charAt(i));  // set bit for char
   }
    public String toString(){
         String desc="[";
         int size=used.size();
          for(int i=0;i< size;i++){
             if(used.get(i))
                 desc+=(char)i;
            }
             return desc+"]";
         }
    public static void main(String args[]){
        WhichChars w=new WhichChars("How do you do");
        System.out.println(w);
    }
   }
運行:
C:\work>java WhichChars

[ Hdouwy]

2. java.util.BitSet 研究(存數海量數據時的一個途徑)

java.util.BitSet可以按位存儲。
計算機中一個字節(byte)佔8位(bit),我們java中數據至少按字節存儲的,
比如一個int佔4個字節。
如果遇到大的數據量,這樣必然會需要很大存儲空間和內存。
如何減少數據佔用存儲空間和內存可以用算法解決。
java.util.BitSet就提供了這樣的算法。
比如有一堆數字,需要存儲,source=[3,5,6,9]
用int就需要4*4個字節。
java.util.BitSet可以存true/false。
如果用java.util.BitSet,則會少很多,其原理是:
1,先找出數據中最大值maxvalue=9
2,聲明一個BitSet bs,它的size是maxvalue+1=10
3,遍歷數據source,bs[source[i]]設置成true.

最後的值是:
(0爲false;1爲true)
bs [0,0,0,1,0,1,1,0,0,1]
                3,   5,6,       9

這樣一個本來要int型需要佔4字節共32位的數字現在只用了1位!
比例32:1  

這樣就省下了很大空間。

 

 

看看測試例子

[html] view plaincopy
  1. package com;  
  2.   
  3. import java.util.BitSet;  
  4.   
  5. public class MainTestThree {  
  6.   
  7.     /**  
  8.      * @param args  
  9.      */  
  10.     public static void main(String[] args) {  
  11.         BitSet bm=new BitSet();  
  12.         System.out.println(bm.isEmpty()+"--"+bm.size());  
  13.         bm.set(0);  
  14.         System.out.println(bm.isEmpty()+"--"+bm.size());  
  15.         bm.set(1);  
  16.         System.out.println(bm.isEmpty()+"--"+bm.size());  
  17.         System.out.println(bm.get(65));  
  18.         System.out.println(bm.isEmpty()+"--"+bm.size());  
  19.         bm.set(65);  
  20.         System.out.println(bm.isEmpty()+"--"+bm.size());  
  21.     }  
  22.   
  23. }  

 輸出:
 true--64
false--64
false--64
false
false--64
false--128
 
說明默認的構造函數聲明一個64位的BitSet,值都是false。
如果你要用的位超過了默認size,它會再申請64位,而不是報錯。

[html] view plaincopy
  1. package com;  
  2.   
  3. import java.util.BitSet;  
  4.   
  5. public class MianTestFour {  
  6.   
  7.     /**  
  8.      * @param args  
  9.      */  
  10.     public static void main(String[] args) {  
  11.         BitSet bm1=new BitSet(7);  
  12.         System.out.println(bm1.isEmpty()+"--"+bm1.size());  
  13.           
  14.         BitSet bm2=new BitSet(63);  
  15.         System.out.println(bm2.isEmpty()+"--"+bm2.size());  
  16.           
  17.         BitSet bm3=new BitSet(65);  
  18.         System.out.println(bm3.isEmpty()+"--"+bm3.size());  
  19.           
  20.         BitSet bm4=new BitSet(111);  
  21.         System.out.println(bm4.isEmpty()+"--"+bm4.size());  
  22.     }  
  23.   
  24. }  


 

輸出:
true--64
true--64
true--128
true--128

說明你申請的位都是以64爲倍數的,就是說你申請不超過一個64的就按64算,超過一個不超過
2個的就按128算。

 

[html] view plaincopy
  1. package com;  
  2.   
  3. import java.util.BitSet;  
  4.   
  5. public class MainTestFive {  
  6.   
  7.     /**  
  8.      * @param args  
  9.      */  
  10.     public static void main(String[] args) {  
  11.         int[] shu={2,42,5,6,6,18,33,15,25,31,28,37};  
  12.         BitSet bm1=new BitSet(MainTestFive.getMaxValue(shu));  
  13.         System.out.println("bm1.size()--"+bm1.size());  
  14.           
  15.         MainTestFive.putValueIntoBitSet(shu, bm1);  
  16.         printBitSet(bm1);  
  17.     }  
  18.       
  19.     //初始全部爲false,這個你可以不用,因爲默認都是false  
  20.     public static void initBitSet(BitSet bs){  
  21.         for(int i=0;i<bs.size();i++){  
  22.             bs.set(i, false);  
  23.         }  
  24.     }  
  25.     //打印  
  26.     public static void printBitSet(BitSet bs){  
  27.         StringBuffer buf=new StringBuffer();  
  28.         buf.append("[\n");  
  29.         for(int i=0;i<bs.size();i++){  
  30.             if(i<bs.size()-1){  
  31.                 buf.append(MainTestFive.getBitTo10(bs.get(i))+",");  
  32.             }else{  
  33.                 buf.append(MainTestFive.getBitTo10(bs.get(i)));  
  34.             }  
  35.             if((i+1)%8==0&&i!=0){  
  36.                 buf.append("\n");  
  37.             }  
  38.         }  
  39.         buf.append("]");  
  40.         System.out.println(buf.toString());  
  41.     }  
  42.     //找出數據集合最大值  
  43.     public static int getMaxValue(int[] zu){  
  44.         int temp=0;  
  45.         temp=zu[0];  
  46.         for(int i=0;i<zu.length;i++){  
  47.             if(temp<zu[i]){  
  48.                 temp=zu[i];  
  49.             }  
  50.         }  
  51.         System.out.println("maxvalue:"+temp);  
  52.         return temp;  
  53.     }  
  54.     //放值  
  55.     public static void putValueIntoBitSet(int[] shu,BitSet bs){  
  56.         for(int i=0;i<shu.length;i++){  
  57.             bs.set(shu[i], true);  
  58.         }  
  59.     }  
  60.     //true,false換成1,0爲了好看  
  61.     public static String getBitTo10(boolean flag){  
  62.         String a="";  
  63.         if(flag==true){  
  64.             return "1";  
  65.         }else{  
  66.             return "0";  
  67.         }  
  68.     }  
  69.   
  70. }  


 


輸出:
maxvalue:42
bm1.size()--64
[
0,0,1,0,0,1,1,0,
0,0,0,0,0,0,0,1,
0,0,1,0,0,0,0,0,
0,1,0,0,1,0,0,1,
0,1,0,0,0,1,0,0,
0,0,1,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0
]

這樣便完成了存值和取值。
注意它會對重複的數字過濾,就是說,一個數字出現過超過2次的它都記成1.

出現的次數這個信息就丟了



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章