Java 程序实例笔记(下)

1. Java 有n个整数,使其前面各数顺序向后移 m 个位置,最后m个数变成最前面的m个数

用数组来存放这n个整数,但由于数组创建后大小是固定的,移动不了,因此一般选择新建一个数组来存放目标数组。
通过举例测验,发现了它的规律:

顺序后移之后的新数组由两部分组成,前一部分是原数组的  (n-m)~n 的元素,
                             后一部分是原数组的  0~(n-m) 的元素
import java.util.*;
public class Test {
	public static void main(String [] args){
	 System.out.print("请输入整数个数n:");
	 Scanner scan = new Scanner(System.in);
	 int n=scan.nextInt();
	    int array[]= new int [n];
	    int arr[]=new int[array.length];
	    for(int i=0;i<n;i++) {
	       array[i]=(int)(Math.random()*100); //随机生成一个由n个整数组成的一维数组
	       System.out.print(array[i]+" ");
	    }
	    System.out.println();
	    System.out.print("前面各数顺序后移m: ");
	    int m=scan.nextInt();
	    int a=0;
	    for(int i=n-m;i<n;i++) {//先把(n-m)~n的元素复制到新数组里
	   	 arr[a]=array[i];
	   	// arr[i]=array[(i+m)%n];//错误规律,不普遍适用
	   	 a++; 
	    }
	    for(int i=0;i<n-m;i++) {//再把0~(n-m)的元素复制到新数组里
	   	 arr[a]=array[i];
	   	 a++; 
	    } 
	    for(int i=0;i<n;i++) {
	    System.out.print(arr[i]+" ");	
	    }
	}
}

运行结果:
在这里插入图片描述
之后又了解到一个解决本题的方法,
是利用 冒泡排序 解决的,(不理解冒泡排序的,可以先去了解下 点击链接

具体代码如下:

public static void main(String[] args) {	
	int [] x= {1,2,3,4,5,6,7,8,9};   
	a(x,3);
	for (int i = 0; i < x.length; i++) {
		System.out.print(x[i]+",");
	}	
}
static void a(int [] x,int m) {
	//后移m位.要进行 x.length-m次冒泡
	for(int i=0;i<x.length-m;i++) { //外层循环控制冒泡的趟数
		for(int j=0;j<x.length-1;j++) { //内层循环控制一趟循环需要比较的次数
			int t=x[j];
			x[j]=x[j+1];
			x[j+1]=t;
		}
	}
}

这个方法从代码上来看比上一个方法简单多了,但是性能方面不怎么好,双重循环,时间复杂度是 O(n^2) ,但不可否认确实是一种新的解题思想。

2. 有一个数组,从中间选一个元素, 写一算法,把所有大于这个数的元素放到这个数后面,小于的放在这个数前面

{88,6,3,9,12,10,33,7,44}
话说,一开始看到这个题,我的想法是,第一个数是88,比12大,要放在12的后面,但是把88赋值给12的下一个元素的话就会把人家原来数组那个位置的元素覆盖掉,那我该怎么把88插入到10的后面呢?
数组大小固定,要插入一个数不就溢出了么?要不重新建一个数组存放?
自此,我的思想就崩向了远方…😳( ╯□╰ )
后来百思不得其解的我,问了同学,哦,比大小,直接输出就好了。

唉~本来简单的这个题被我复杂化,,
我还是 图样图森破了。。。惭愧啊。。

public class Test {
	public static void main(String[] args) {	
	//有一个数组,从中间选一个元素, 写一算法,把所有大于这个数的元素放到这个数后面,所以小于的放在这个数前面
	   int array[]={88,6,3,9,12,10,33,7,44};
	   System.out.println("自定义的数组为:");
	   for(int i=0;i<array.length;i++){
		   System.out.print(array[i]+" ");
	   		}
	   System.out.println();
	   int index=array[(array.length)/2]; //取一中间数
	   System.out.print("取到的中间数是:"+index);
	   System.out.println();
	   System.out.println("按规律排序的数组为:");
		for(int i=0;i<array.length;i++){
			if(array[i]<index){
				System.out.print(array[i]+" "); //比大小直接输出即可
			}
		}
		System.out.print(index+" ");
		for(int i=0;i<array.length;i++){
			if(array[i]>index){
				System.out.print(array[i]+" ");
			}
		}
	}
} //注意:本题只需要将比中间数小的放在前面,大的放在后面,无需排序。

运行结果:
在这里插入图片描述

3. 编写一个程序,生成0-9之间的100个随机整数并且显示每一个数的个数

一段比较简单的程序~

public class Test{
	public static void main(String[] args) {
		int array[]=new int[100];
		int m=0;//缓存数组元素个数
		System.out.println("随机生成的数组是:");
		for(int i=0;i<array.length;i++) {
			m++;
			array[i]=(int)(Math.random()*10);
			System.out.print(array[i]+" ");
			if(m%10==0) {
				System.out.println();//10个一行输出,方便查看
			}
		}
		int count=0;
		for(int i=0;i<=9;i++) {
			for(int j=0;j<array.length;j++) {
				if(array[j]==i) {
					count++;
				}
			}
			System.out.println(i+"有"+count+"个");
			count=0;//count清零,重新累加,也可以将count的初始化写在外循环里,就不用写这句了
		}
	}
}

运行结果:
在这里插入图片描述

4. 找出1000以内的所有完数

写的时候感觉挺简单,,写完后一运行,结果只有一句 :
1000以内的完数有:

那数呢?怎么没有数呢?
百思不得其解。。。😵😵
让别人帮我看了下,哈哈。找到了原因。
究其根本,是一个 变量的作用域 问题。我把它初始化在了循环体外,导致循环的时候,它不清零,一直累加,从而计算不出结果,,😳😳
糟心。
以下是完整代码:

//编程 找出1000以内的所有完数
//一个数如果恰好等于它的因子(除了本身之外的因数)之和,这个数就称为 "完数 "。例如6=1+2+3.
public class WanShu{
	public static void main(String[] args) {
		int n=2;//1不是完数,从2开始
		//int s=0;//缓存因子的和 s如果在这里初始化,在执行循环的时候就不会清零了,就会导致s一直累加,找不到要求的结果
		System.out.println("1000以内的完数有:");
		while(n<=1000) {
			int s=0;
			for(int i=1;i<n;i++) {
				if(n%i==0) { //除的开就是因子
					s+=i; //计算这个数的因子之和
				}
			}
			if(s==n) {
				System.out.print(n+" ");
			}
			n++;
		}
	}
}

运行结果:
在这里插入图片描述
谨记:写代码的时候,一定要注意变量的作用域问题!
不注意,会出人命的!!!
/(ㄒoㄒ)/~~

5. 求一个n*n矩阵对角线元素之和

比较简单的一段程序~~

import java.util.*;
//求一个n*n矩阵对角线元素之和
public class Test{
	public static void main(String[] args) {
		System.out.print("请输入n*n矩阵的n值:");
		Scanner scan =new Scanner(System.in);
		int n=scan.nextInt();
		int array[][]=new int[n][n];//用二维数组来缓存一个n*n矩阵
		int s=0;//缓存对角线元素之和
		for(int i=0;i<n;i++) { //遍历矩阵
			for(int j=0;j<n;j++) {
				array[i][j]=(int)(Math.random()*10);//随机生成n*n个元素,存放到数组里
				System.out.print(array[i][j]+" "); //打印数组
				if(i==j||i+j==n-1) {//判断主副对角线
					s+=array[i][j]; //求对角线元素之和
				}
			}
			System.out.println();
		}
		System.out.println(n+"*"+n+"矩阵对角线元素之和是"+s);
	}
}

运行结果:
在这里插入图片描述

6. 打印杨辉三角

经典问题
打印图形,最重要的是要找到规律。
具体规律详见注释。

public class YangHuiSanJiao{
	public static void main(String[] args) {
		int array[][]=new int [10][10];
		for(int i=0;i<10;i++){
			array[i][i]=1;//对角线全是1
			array[i][0]=1;//第一列全是1
		}
		for(int i=2;i<10;i++) {//从第三行开始
			for(int j=1;j<=i-1;j++) {//每行从第二列开始
				array[i][j]=array[i-1][j-1]+array[i-1][j];
				//第i行j列的值 = 第i-1行j-1列的值 + 第i-1行j列的值
			}
		}
		for(int i=0;i<10;i++) {
			for(int j =9; j >= i; j --){
                System.out.print("  ");//打印空格,没有该循环,将是一个直角三角形,如下图运行结果
            }
			for(int j=0;j<=i;j++) {
				System.out.print(+array[i][j]+"   ");//打印杨辉三角
			}
			System.out.println(	);
		}
	}
}

运行结果:

1   
1   1   
1   2   1   
1   3   3   1   
1   4   6   4   1   
1   5   10   10   5   1   
1   6   15   20   15   6   1   
1   7   21   35   35   21   7   1   
1   8   28   56   70   56   28   8   1   
1   9   36   84   126   126   84   36   9   1   

                    1   
                  1   1   
                1   2   1   
              1   3   3   1   
            1   4   6   4   1   
          1   5   10   10   5   1   
        1   6   15   20   15   6   1   
      1   7   21   35   35   21   7   1   
    1   8   28   56   70   56   28   8   1   
  1   9   36   84   126   126   84   36   9   1   

7. 有一个数组由0和其他数字组成, 其中如果是0的话,必须是连续5个以上的0才算合法, 编写程序,把程序中 非法出现的 (就是连续个数少于5个) 的0 全挑出来,打印其数组开始位置索引,结束位置索引

例: int [] x={0,0,3,4,5,0,3,0,0,0,1,0,0,0,0,0,9};

输出:
   非法序列: 从索引:0 到 1有 2个0
   非法序列: 从索引:5 到 5有 1个0
   非法序列: 从索引:7 到 9有 3个0

按题要求,第一次设计代码。

public class Test{
	public static void main(String[] args) {
	   int [] x={0,0,3,4,5,0,3,0,0,0,1,0,0,0,0,0,9};	  
	   int count=0; //缓存零的个数
	   int last=0; //缓存连续0的最后一个0的索引
	   for(int i=0;i<x.length;i++) {  
		   if(x[i]==0) {
			  count++; 
			   }
		   else {
			   last=i-1; //元素不是0的时候执行else语句,此时的i为连续零的下一个非零元素的索引
			   if(count>0&&count<5) {
				   System.out.println("非法序列:从索引 "+(last-count+1)+" 到 "+last+" 有 "+count+" 个0");
			   }                                //连续零的第一个零的索引 = 最后一个零的索引 - (count-1)
			   count=0;//清零,重新累加
	       } 
	   }  
	}	
}

运行结果:
在这里插入图片描述
第一次完成这个代码的时候,觉得思想挺正确。
运行结果也莫得问题~~
符合原题输出要求~

But,在老师的提示下,测试了下边界值,,发现我 终究 还是 草率了。。😳( ╯□╰ )
我修改了原数组,在最后加了4个0,

int [] x={0,0,3,4,5,0,3,0,0,0,1,0,0,0,0,0,9,0,0,0,0};

运行结果,发现,嗯,怎么肥四??怎么结果和原来的一样内???😵
又检查了一遍思路,感觉 莫得问题啊。。。
实在不行了,我去问了朋友,啊,找到原因了~~o( ̄▽ ̄)ブ
在这里插入图片描述
看完原因第一想法,我把输出语句放出去应该就可以了把。。
如下图代码。

 else {
			   last=i-1; //元素不是0的时候执行else语句,此时的i为连续零的下一个非零元素的索引
			   count=0;//清零,重新累加
	       } 
		   if(count>0&&count<5) {
			   System.out.println("非法序列:从索引 "+(last-count+1)+" 到 "+last+" 有 "+count+" 个0");
		   }                                //连续零的第一个零的索引 = 最后一个零的索引 - (count-1)
		   

结果与我想像的有点不一样。。
在这里插入图片描述
改了好久,试了好多次,发现原来是我算法的问题。
因为我算法的思路就是,当他遍历到不是 0 的时候,利用连续零后的第一个非零元素取得的 连续零的最后一个零的索引

如果在后面加一个非零元素,

int [] x={0,0,3,4,5,0,3,0,0,0,1,0,0,0,0,0,9,0,0,0,0,9};

运行结果:
在这里插入图片描述
那我这个算法就不是很灵活,就有限制。
分享一下另一个成功的代码,它主要是利用连续零的第一个元素来取值的

public class Test{
	public static void main(String[] args) {
		int [] x={0,0,3,4,0,0,0,0,3,0,0,0,1,0,0,0,0};
		for(int i=0;i<x.length;i++) {
			if(x[i]!=0) {
				continue;
			}
			int count=0; //连续的0的个数
			int begin=i;  //0开始的索引位置
			//取连续为0的序列
			while(x[i]==0) {
				i++;
				count++;
				if(i==x.length) {
					break;
				}
			}
			if(count<5) {
				System.out.println("非法序列:从索引 "+begin+" 到 "+(begin+count-1)+" 有 "+count+" 个0");
			}
		}

	}
}

这样一看,感觉我之前那个应该也可以,只不过我语句的位置写错了,照上面的代码模板走一遍也可以。

通过本例代码,证明 测试边界值是非常有必要的!!!
这个问题要好好注意一下了。

8. 未完待续

java学习ing.jpg 😊o( ̄▽ ̄)ブ

有其他见解,评论区留言或者私信,一起讨论,纠正。

关注我,努力鸭~和我一起学习鸭~

另外,转载文章请记得附上原文链接哦

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力鸭~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值