本篇讲解几道java基础题目
博客主页:KC老衲爱尼姑的博客主页 博主的github,平常所写代码皆在于此 共勉:talk is cheap, show me the code 作者是爪哇岛的新手,水平很有限,如果发现错误,一定要及时告知作者哦!感谢感谢!
小题目,大道理。
素数求解
什么是素数?
定义: 质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数(规定1既不是质数也不是合数)。
题目一:判断一个数否是素数
分析:根据素数的定义可知,素数是除了1和自身以外不能被其它整除,所以我们可以通过枚举2到我们判断的数之间的数是否存在可以被我们要判断的数整除,如果有则不是素数,反之则是素数。
法一
代码语言:javascript复制import java.util.Scanner;
public class Demo9 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int i = 2;
for (; i < n; i ) {
if(n%i==0){
System.out.println("不是素数");//2~n之间是否有数字能整除n
break;
}
}
if(i==n){//i==n说明没有,所以必然是素数
System.out.println("是素数");
}
}
}
法一是通过枚举出2~n-1之间所有的数,而实际只需要有一个数能把n整除即可,所以我们可以试图来缩小枚举的范围。我们都知道任意一个数可以写成n=ab,比如16可以写成,16=1 * 16 ,或者16=44,或者16=2 * 8。通过这三个式子,我们可以发现a和b中一定有小于定于2/n,我们可以直接除以2/n,这样就可以将要除的数缩小一半,效率自然也上来。
法二
代码语言:javascript复制import java.util.Scanner;
public class Demo10 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int i = 2;
for (; i <=n/2; i ) {
if(n%i==0){
System.out.println("不是素数");
break;
}
}
if(i>n/2){
System.out.println("是素数");
}
}
}
我们还可以将枚举的范围在缩小一半,因为a和b一定有一个数会小于等于根号16,如此又将范围砍一半,效率杠杆的上来了。
法三
代码语言:javascript复制import java.util.Scanner;
public class Demo11 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int i = 2;
for (; i <=Math.sqrt(n); i ) {
if(n%i==0){
System.out.println("不是素数");
break;
}
}
if(i>Math.sqrt(n)){
System.out.println("是素数");
}
}
}
测试代码的运行时间的方法
代码语言:javascript复制long startTime = System.currentTimeMillis();
// 要获取运行时间的代码片
long endTime = System.currentTimeMillis();
System.out.println("程序运行时间:" (double) (endTime - startTime) / 1000 "s");//单位是秒
感兴趣的朋友可以用以上代码对求素数的三种方法进行测试。
自幂数
定义:如果在一个固定的进制中,一个n位自然数等于自身各个数位上数字的n次幂之和,则称此数为自幂数。
求1~n范围内的自幂数
分析:首先我们需要判断这个数是几位数,其次需要拿到该数的每一位数,最后进行判断自然数是否等于自身各个数位上数字的n次幂之和。
代码
代码语言:javascript复制public class Demo14 {
public static void main(String[] args) {
for (int i = 1; i < 999; i ) {
int tmp = i;
int count = 0;
while (tmp != 0) {
count ;//计算位数
tmp = tmp / 10;
}
tmp=i;
int sum=0;
while (tmp != 0) {
sum = Math.pow(tmp % 10, count);
tmp = tmp / 10;//得到每一位数
}
if (sum == i) {
System.out.print(i " ");
}
}
}
}
注意:Math.pow()范围值的类型为douoble,使用 =赋值给sum,会发生强制类型转换,但是数值的损失是可以接受的。(小数点后面的数)
统计二进制位中的1的个数
分析:利用任何一个数按位于1之后结果还是1,基于此结论我们可以将一个数的32个比特位与1按位于之后判断结果是否为1,再将该数右移,在次重复上述的计算.而我们只需定义一个计算器去统计一个数按位于1之后结果还是1的真结果即可。
法一
代码语言:javascript复制public class Demo16 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n=sc.nextInt();
int count=0;
for(int i=0;i<32;i ){
if((n&(1<<i))!=0){
count ;
}
}
System.out.println(count);
}
}
上述代码对于数字7来说并不友好,因为7的最后4位二进制为0111,按照上述多移了29次,在时间上有所浪费,为了节约时间所以我们可以将n每移一位数后重新赋值即n=n>>1,循环条件为n不等于0.
法二
代码语言:javascript复制public class Demo17 {
public static void main(String[] args) {
Scanner sc= new Scanner(System.in);
int n=sc.nextInt();
int count=0;
while (n!=0){
if((n&1)!=0){
count ;
}
n=n>>>1;
}
System.out.println(count);
}
}
注意:如果该数为负数并且是简单的右移,会造成死循环,因为负数右移后补符号位即1,所以为了解决这个问题我们使用无符号右移。
法三
巧用n=n&(n-1)
化抽象为具体一图解疑惑
由图可以,可以发现7的二进制序列每次按位与之后都少了1,我们只需每次按位与之后用计算器统计即可。
代码
代码语言:javascript复制public class Demo18 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int count = 0;
while (n!=0) {
n=n&(n-1);
count ;
}
System.out.println(count);
}
}
总结
题目虽然不难,但是想出最优解才是最难的,每一题目都不容忽视,都值得深思就像做数学题要做到一题多解,要做到更快,用更的办法解出,相信秉持钉子精神,咋们迟早刷爆力扣,hhhh!
最后的话
各位看官如果觉得文章写得不错,点赞评论关注走一波!谢谢啦!