題目描述
令Pi表示第i個素數(shù)?,F(xiàn)任給兩個正整數(shù)M <= N <= 10000,請輸出PM到PN的所有素數(shù)。
輸入描述:
輸入在一行中給出M和N,其間以空格分隔。
輸出描述:
輸出從PM到PN的所有素數(shù),每10個數(shù)字占1行,其間以空格分隔,但行末不得有多余空格。
輸入例子:
5 27
輸出例子:
11 13 17 19 23 29 31 37 41 43
47 53 59 61 67 71 73 79 83 89
97 101 103
思路和知識點:
- 素數(shù):在大于1的整數(shù)中,只能被1和這個數(shù)本身整除的數(shù),如2、3、5、7、11。也叫質(zhì)數(shù)。(1不是素數(shù))
- Math.sqrt(): JAVA中實現(xiàn)求一個數(shù)的平方根
- 如何判斷一個數(shù)是否是素數(shù)?
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sann = new Scanner(System.in);
int left = sann.nextInt();
int right = sann.nextInt();
int times = 0;//用來計數(shù)
for(int i=1; ;i++){ //從1開始判斷每個數(shù)是否是素數(shù)
if(isPrime(i)==true){
times++;//如果是素數(shù),計數(shù)加一
if(times<right && times>=left){ //如果在要求的范圍內(nèi),則要十個一行輸出
if((times-left+1)%10 == 0 ){
System.out.print(i);
System.out.print("\n");//輸出該數(shù)并換行
}else{
System.out.printf("%d ",i);//輸出該數(shù)并空格
}
}
if(times == right){
System.out.printf("%d",i);
break; //跳出for循環(huán)
}
}//end if
}//end for;
}
// // 判斷一個數(shù)是否是素數(shù)的方法
public static boolean isPrime(int num){
boolean flag = true;
if(num==1){
flag = false;
}
if((num == 2 || num ==3)&& num!=1){
flag = true;
}else{
for(int i=2;i<=Math.sqrt(num);i++ ){
if(num%i==0){
flag = false;
break;
}
}
}
return flag;
}
}
哈哈哈哈哈哈,這道題實在折磨了我太長時間,網(wǎng)上找不到能編譯成功的算法,自己小白一個,從判斷素數(shù)的方法一句一句寫起來,中間各種報錯,還是使用java不熟練,很多語句都不太會寫,連數(shù)組的初始化都要百度ORZ··· 好在,經(jīng)過艱苦卓絕的頑強掙扎,終于把這道題解決了,相信以后寫算法的能力也能有所提升,畢竟這是嚴格意義上自己第一道獨立解決的算法題。
在此感謝LeetCode平臺,提供了算法在線編譯調(diào)試的平臺,讓我能一步步的嘗試運行,從而找到自己原始版本中的錯誤。
總結(jié)一下,這道題做不出來的主要錯誤在于邏輯錯誤,好幾個地方都是我的if語句的邏輯沒有弄明白,幾個if語句之間相互并列反而沒有了需要的效果。
再次,向掙扎在算法路上的自己致敬!要繼續(xù)勇敢的不放棄的走下去!

補充(以下僅是思路,沒有成功實現(xiàn),可以不看,特此提醒):
在掙扎這道題的過程中,有看到關于素數(shù)判斷的一些相關理論,包括孿生素數(shù),還有“素數(shù)都在六的倍數(shù)兩側(cè),但六的倍數(shù)兩側(cè)不一定都是素數(shù)?!弊鳛橐粋€嚴謹又充滿好奇心的喵嗚,我嘗試了一下以六為倍數(shù)增加的方法,第一次寫出來后在35這個數(shù)字這里卡住了,因為35的開平方是5,而我的for循環(huán)從7開始,所以35這個數(shù)字沒有進入for循環(huán)進行判斷,調(diào)整后將判斷素數(shù)函數(shù)寫作如下:
// // 判斷一個數(shù)是否是素數(shù)的方法
public static boolean isPrime(int num){
boolean flag = true;
if(num==1){
flag =false;
}
if((num == 2 || num ==3)&& num!=1){
flag =true;
}else{
if(num%6 != 1 && num%6!=5){
flag = false;
} else{
if(num<49){ //小于7的平方的話,就不開平了
for(int i = 7;i<num-5;i+=6){
if(num%i == 0){
flag = false;
break;
}
}
}else{
for(int i = 7;i<=Math.sqrt(num);i+=6){
if(num%i == 0){
flag = false;
break;
}
}
}//end else
}//end else
}//end else
return flag;
}// end isPrime
在調(diào)試運行后,又發(fā)現(xiàn)25不是素數(shù),但是根據(jù)我們的算法得到的是素數(shù),跟著邏輯走一邊,發(fā)現(xiàn)上述算法的確得到25時是true,說明上述算法有誤。
想了一下,素數(shù)分布在6的倍數(shù)的兩側(cè),不是在左側(cè)就是在右側(cè),也有可能左右兩側(cè)都是素數(shù)(6的倍數(shù)的左右兩側(cè)都是素數(shù)時,我們將這兩個素數(shù)稱作孿生素數(shù)),在我們上述算法中,根據(jù)上述思想進行了以6為步數(shù)的躍進,但是從7開始+6的躍進只遍歷了6的倍數(shù)的右側(cè),而忽略了6的左側(cè),而并不是每一個6的倍數(shù)的右側(cè)數(shù)字是素數(shù)的時候,左側(cè)也一定是素數(shù)(反之亦然)。所以這種算法在4*6=24的左側(cè)23(是素數(shù))、右側(cè)25(不是素數(shù))時,出現(xiàn)了判斷錯誤。
如何解決上述錯誤?那就只能左右兩側(cè)都進行判斷,可是這樣一來,算法是不是更加復雜?還不如原始算法??
走到這一步已經(jīng)耗盡我的腦細胞了,所以戛然止步。如果有過路的讀者有想法或者更好的意見,歡迎留言批評指正!
溜了溜了~~~