该题目指定用单个字符来进行日期的判断,而单个字符是可以当int型使用的,所以在此处用switch…case较为方便,示例代码如下:
private static String judgeWeek(char[] weeks){
String week="";
switch(weeks[0]){
case 'M':
case 'm':
week="Monday";
break;
case 'T':
case 't':
if(weeks[1]=='u'||weeks[1]=='U')
week="Tuesday";
else if(weeks[1]=='h'||weeks[1]=='H')
week="Thursday";
break;
case 'W':
case 'w':
week="Wednesday";
break;
case 'F':
case 'f':
week="Friday";
break;
case 'S':
case 's':
if(weeks[1]=='a'||weeks[1]=='A')
week="Saturday";
else if(weeks[1]=='s'||weeks[1]=='U')
week="Sunday";
break;
}
return week;
}
该题目的逻辑并不复杂,之前的题目中也有类似的,双层for循环,外层被除数,内层除数,遍历相除,输出筛选出来的值即可。此处说一下可能会采的坑。初版代码如下:
private static void printNum(int num){
boolean isPrint=true;
for(int i=3;i<num;i++){
for(int j=2;j<=(int)Math.sqrt(i);j++){
if(i%j==0){
isPrint=false;
break;
}
}
if(isPrint)
System.out.println(i);
}
}
该代码粗看,好像没什么问题,但运行一下,发现输出的值只有一个"3"。这明显是不对的。细看才发现,该代码中有个问题:isPrint变量被赋值一次false后,就一直是false,导致后续不会再输出素数。所以需要将代码改一版:
private static void printNum(int num){
boolean isPrint=true;
for(int i=3;i<num;i++){
for(int j=2;j<=(int)Math.sqrt(i);j++){
if(i%j==0){
isPrint=false;
break;
}else{
isPrint=true;
}
}
if(isPrint)
System.out.println(i);
}
}
这版代码加入了每次循环时对isPrint变量的重新赋值,运行结果也是正确的。但是还不是最优的,外层for循环选取的初始值是3,是个奇数,这是个伏笔,每次不用自增1,自增2就行,因为偶数肯定不是素数,这样,循环次数就会减少一半。示例代码如下:
private static void printNum(int num){
boolean isPrint=true;
for(int i=3;i<num;i=i+2){
for(int j=2;j<=(int)Math.sqrt(i);j++){
if(i%j==0){
isPrint=false;
break;
}else{
isPrint=true;
}
}
if(isPrint)
System.out.println(i);
}
}
关于各种常用的排序算法,在《算法》分类中有详细的介绍,此处以冒泡排序来简单说下排序。冒泡排序的步骤是比较固定的:
1>比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2>每趟从第一对相邻元素开始,对每一对相邻元素作同样的工作,直到最后一对。
3>针对所有的元素重复以上的步骤,除了已排序过的元素(每趟排序后的最后一个元素),直到没有任何一对数字需要比较。
具体落实到代码上,也是需要两层for循环,一个表示要比较的数中前面的那个,一个表示后面的那个。每次比较,都会将序列汇总的一个最值放到末端,进行n-1趟比较、移动即可完成排序过程。示例代码如下:
private static void sort(int[] array){
/*外循环为排序趟数,array.length个数进行array.length-1趟 */
for(int i=0;i<array.length-1;i++){
/*内循环为每趟比较的次数,第i趟比较array.length-i次 */
for(int j=0;j<array.length-1-i;j++){
/*相邻元素比较,若满足条件则交换(升序为左大于右,降序反之) */
if(array[j]>array[j+1]){
int temp=array[j];
array[j]=array[j+1];
array[j+1]=temp;
}
}
}
}
矩阵的叫法显得有些高级,此处可以理解为求一个二维数组的对角线元素之和。对于该题,把从左上角到右下角和从左下角到右上角的原色累加一下就行,落实到代码依然是双层for循环。本题难的是如何挑选出两列元素。规则有两个(二维数组的行列下标分别为i、j):
1>i == j,挑选出来的从左上角到右下角的元素。
2>i == (array[0].length-j-1),挑选出来的是左下角到右上角的元素。
示例代码如下:
private static int sum(int[][] array){
int sum=0;
for(int i=0;i<array.length;i++){
for(int j=0;j<array[0].length;j++){
/*此处有两个判断条件:
* 1、i==j,挑选出来的从左上角到右下角的元素
* 2、i==(array[0].length-j-1),挑选出来的是左下角到右上角的元素
* 两者会挑选出重复的元素,但是用的是||运算,该元素智慧选取一次*/
if((i==j) || (i==(array[0].length-j-1)))
sum=sum+array[i][j];
}
}
return sum;
}
该题目的逻辑还是比较复杂的,可以通过下面的步骤来进行:
1>判断是升序还是降序,因为不同序列的最大值和最小值在不同的位置。
2>判断是不是可以直接插在首部或尾部。如果可以插入首部,所有元素往后移一位;如果可以插在尾部,在新的数组中拷贝原数组的所有元素,然后在最后一位插入新元素即可。
3>如果要在中间位置插入,就要遍历,寻找要插入的位置,然后先拷贝插入位置之前的元素,再插入新元素,再拷贝插入位置之后的元素。
示例代码如下:
private static int[] insert(int[] array,int num){
int[] newArray=new int[array.length+1];
/*默认升序*/
boolean isSscending=true;
/*假如第一个元素大于最后一个元素,为降序,此处不考虑整个序列中元素都相等的极端情况*/
if(array[0]>array[array.length-1]){
isSscending=false;
}
/*升序数组*/
if(isSscending){
/*要插入的元素小于等于最小值,插入到首部*/
if(num<=array[0]){
System.arraycopy(array, 0, newArray, 1, array.length);
newArray[0]=num;
/*要插入的元素大于等于最大值,插入到尾部*/
}else if(num>=array[array.length-1]){
System.arraycopy(array, 0, newArray, 0, array.length);
newArray[newArray.length-1]=num;
}else{
int insertPosition=0;
/*寻找要插入的位置*/
for(int i=0;i<array.length;i++){
if(num<array[i]){
insertPosition=i;
break;
}
}
System.out.println("insertPosition:"+insertPosition);
/*拷贝插入位置前的元素*/
System.arraycopy(array, 0, newArray, 0, insertPosition);
/*插入新元素*/
newArray[insertPosition]=num;
/*拷贝插入位置后的元素*/
System.arraycopy(array, insertPosition, newArray, insertPosition+1,array.length-insertPosition);
}
/*降序数组*/
}else{
/*要插入的元素小于等于最小值,插入到末尾*/
if(num<=array[array.length-1]){
System.arraycopy(array, 0, newArray, 0, array.length);
newArray[newArray.length-1]=num;
/*要插入的元素大于等于最大值,插入到首部*/
}else if(num>=array[0]){
System.arraycopy(array, 0, newArray, 1, array.length);
newArray[0]=num;
}else{
int insertPosition=0;
/*寻找要插入的位置*/
for(int i=0;i<array.length;i++){
if(num>array[i]){
insertPosition=i;
break;
}
}
System.out.println("insertPosition:"+insertPosition);
/*拷贝插入位置前的元素*/
System.arraycopy(array, 0, newArray, 0, insertPosition);
/*插入新元素*/
newArray[insertPosition]=num;
/*拷贝插入位置后的元素*/
System.arraycopy(array, insertPosition, newArray, insertPosition+1,array.length-insertPosition);
}
}
return newArray;
}
这个题考对数组下标的使用,在每次的for循环中,怎么拿到和循环次数i相反位置的元素。示例代码如下:
private static void print(int[] arr){
for(int i=0;i<arr.length;i++){
System.out.println(arr[arr.length-1-i]);
}
for(int i=arr.length-1;i>=0;i--){
System.out.println(arr[i]);
}
}
因为不知道这个数字有多少位,如果用数字的运算符来计算的话,可能实现难度稍大,可以还采用之前简单的转换为char数组的方式来实现。示例代码如下:
private static void printFour(int num){
char[] chars=String.valueOf(num).toCharArray();
for(int i=0;i<4;i++){
System.out.print(chars[chars.length-1-i]+" ");
}
}
该题目和之前的输出菱形*的题有些相似,增加的难度在于要计算输出的非空格元素的值,所以此题哟分为两步:先计算,再输出,步骤如下:
1>先计算山坡两边,也就是山表面值的值,都是1,然后再计算山里面元素的值,该位置的值都等于上层两个相邻元素之和。
2>输出元素,其实创建了一个[10][10]的数组之后,我们在第一步中只是给这个二维数组的左下角元素赋了值,但是要输出山坡的形状,就要在每层元素前面输出不同的空格,来控制整体的输出形状。
示例代码如下:
private static void printTriangle(int num){
int[][] arr = new int[num][num];
/*给“山坡”的左右两边元素赋值*/
for(int i=0; i<num; i++) {
arr[i][i] = 1;
arr[i][0] = 1;
}
/*给“山坡”内部元素赋值,每个元素等于上层两个相邻元素之和*/
for(int i=2; i<num; i++) {
for(int j=1; j<i; j++) {
arr[i][j] = arr[i-1][j-1] + arr[i-1][j];
}
}
/*以山坡形状,输出所有元素*/
for(int i=0; i<10; i++) {
for(int k=0; k<num-i; k++) {
System.out.print(" ");
}
for(int j=0; j<=i; j++) {
System.out.print(arr[i][j]+" ");
}
System.out.println();
}
}
这道题考的内容也不多,即元素的比较和交换,示例代码如下:
/*arr:将要排序的数字放入数组中,isSscending:是否升序排列*/
private static void printThreeNum(int[] array,boolean isSscending){
for(int i=0;i<array.length-1;i++){
for(int j=0;j<array.length-1-i;j++){
/*升序*/
if(isSscending){
if(array[j]>array[j+1]){
int temp=array[j];
array[j]=array[j+1];
array[j+1]=temp;
}
/*降序*/
}else{
if(array[j]<array[j+1]){
int temp=array[j];
array[j]=array[j+1];
array[j+1]=temp;
}
}
}
}
for(int i=0;i<array.length;i++){
System.out.print(array[i]+" ");
}
}
其实题目中的做法就是冒泡排序的优化方式,就是在一趟比较中同时找出两个最值,放到序列两端。就这个题而言,可以分为两步:找最大元素与最小元素的索引,然后再分别于数组首尾元素交换即可。示例代码如下:
private static void swapAndPrint(int[] arr){
int maxIndex=0;
int minIndex=0;
for(int i=0;i<arr.length;i++){
/*找到最小元素索引*/
if(arr[minIndex]>arr[i]){
minIndex=i;
}
/*找到最大元素索引*/
if(arr[maxIndex]<arr[i]){
maxIndex=i;
}
}
int temp=0;
/*最大元素与数组首元素交换*/
temp=arr[0];
arr[0]=arr[maxIndex];
arr[maxIndex]=temp;
/*最小元素与数组尾元素交换*/
temp=arr[arr.length-1];
arr[arr.length-1]=arr[minIndex];
arr[minIndex]=temp;
for(int i=0;i<arr.length;i++)
System.out.print(arr[i]+" ");
}
要解决此题,需要创建一个大小为m的临时数组,用以临时存放元素,然后将m个元素之前的元素往后移,临时数组中存放的元素放在前m个位置。示例代码如下:
private static void move(int[] arr,int position){
if(position>=arr.length){
/*输入参数不合法*/
return;
}
/*将要移动的后m个元素存到临时数组中*/
int[] tempArr=new int[position];
for(int i=0;i<tempArr.length;i++){
tempArr[i]=arr[arr.length-position+i];
}
/*将最后的m个元素之外的元素往后移*/
for(int i=0;i<arr.length-position;i++){
arr[i+position]=arr[i];
}
/*将临时数组中的m个元素放回原数组的前m个位置*/
for(int i=0;i<tempArr.length;i++){
arr[i]=tempArr[i];
}
for(int i=0;i<arr.length;i++)
System.out.print(arr[i]+" ");
}
运行后却发现,输出结果不正确,在元素往后移的过程中,可能存在着重复赋值的过程。比如假设arr中有5个元素,要移动的元素个数为2,则存在如下错误:将arr[1]的值赋给arr[3],又赋给arr[5],造成了arr[3]和arr[5]位置上都是arr[3]的值,arr[5]值丢失。正确的做法是将该步骤的由前向后改成由后向前赋值即可。完整正确代码示例如下:
private static void move(int[] arr,int position){
if(position>=arr.length){
/*输入参数不合法*/
return;
}
/*将要移动的后m个元素存到临时数组中*/
int[] tempArr=new int[position];
for(int i=0;i<tempArr.length;i++){
tempArr[i]=arr[arr.length-position+i];
}
/*将最后的m个元素之外的元素往后移*/
for(int i=arr.length-position-1;i>=0;i--){
arr[i+position]=arr[i];
}
/*将临时数组中的m个元素放回原数组的前m个位置*/
for(int i=0;i<tempArr.length;i++){
arr[i]=tempArr[i];
}
for(int i=0;i<arr.length;i++)
System.out.print(arr[i]+" ");
}
该问题相对复杂,先不想具体的解题步骤,假设要解这道题,需要怎样的变量。首先需要一个数组或链表之类的数据结构,来存放n个数据。这n个数据要存什么呢?可以放一个boolean型或int型变量,用来标识是否已经退出。此外,还需要一个变量,来统计报到的数字(即1、2、3)。
万事俱备,现在要写东风(具体的步骤)了。首先要有一个最外层的循环,当还没淘汰的人数大于1时,就继续进行下去。然后判断当前报数人是否被淘汰,因为被淘汰的人是不继续报数的,然后判断是否报到了3,如果报到了3,将当前任淘汰,总数-1,报的数字从0开始。同时,要注意的事情是:当报数到最后一个人时,索引从0开始,即达到一个循环报数的效果。
示例代码如下:
private static int stay(int n){
boolean[] arr = new boolean[n];
for(int i=0; i<arr.length; i++) {
arr[i] = true;
}
/*在统计范围内的总人数*/
int leftCount = n;
/*当前报的数字*/
int countNum = 0;
/*当前报数人的索引*/
int index = 0;
/*当要统计的总人数>1时,继续游戏*/
while(leftCount > 1) {
/*只统计未淘汰的人*/
if(arr[index] == true) {
countNum++;
if(countNum == 3) {
/*当数到3时,从0开始,当前索引置为false,总人数-1*/
countNum =0;
arr[index] = false;
leftCount --;
}
}
/*报数+1时,对应的人的索引也要+1*/
index ++;
/*如果报数到了最后一个人时,循环计数*/
if(index == n) {
index = 0;
}
}
for(int i=0; i<n; i++) {
if(arr[i] == true) {
return i+1;
}
}
return 0;
}
这题目大概是要考对length这个词的使用,length有两个地方常常会用到,若不熟悉的话,可能会混淆:
1>在数组中,array.length是一个数组对象的属性。
2>在字符串中,string.length()是一个方法。
示例代码如下:
private static int length(String str){
return str.length();
}
这类题目在之前已经遇到过好几次了,这道题无非多了一个奇偶数的判断,剩下的就是每次求出一个符合一定规律的数,再求所有数的积或和。示例代码如下:
private static double sum(int n){
double sum=0.0;
if(n%2==0){
for(int i=2;i<=n;i=i+2){
double temp=(double)1/i;
sum=sum+temp;
}
}else{
for(int i=1;i<=n;i=i+2){
double temp=(double)1/i;
sum=sum+temp;
}
}
return sum;
}
该题目和比较一系列的数字实质上是一类问题,不过数字的比较换成了String的比较而已。进行String的比较时,可以将String拆分成char数组,对数组中的元素进行逐个比较。如果两个char数组在可以比较的范围(较小的数组长度)内均相同,那么就以较长的那个数组为较大的字符串。示例代码如下:
private static void stringSort(String[] strs){
for(int i=0;i<strs.length-1;i++){
for(int j=0;j<strs.length-1-i;j++){
/*比较规则:将string转换为char数组,然后再逐个比较char数组中的元素*/
if(compare(strs[i],strs[j])){
String temp=strs[j];
strs[j]=strs[j+1];
strs[j+1]=temp;
}
}
}
}
private static boolean compare(String str1,String str2){
boolean flag=false;
for(int i=0;i<str1.length()&&i<str2.length();i++){
if(str1.charAt(i)<str2.charAt(i)){
flag=true;
return flag;
}
}
if(str1.length()<str2.length())
flag=true;
return flag;
}
这种题目在之前的例子也出现了多次,就是一个不断重复某种操作,来求初始值或末尾值的过程,本题多的无非是未明确最后的值。本题末尾是求最小值,所以可假设最后剩余了一个桃子,来反推最初始的值,可以用递归的方式实现。示例代码如下:
private static int sum(int endNum){
int sum=0;
int cnt=0;
for(int i=endNum;i<10000;i++){
sum=i;
cnt=0;
for(int j=0;j<5;j++){
if(sum%5==1){
sum=sum-((sum/5)+1);
cnt++;
if(cnt==5){
return i;
}
}else{
break;
}
}
}
return 0;
}
这个就是常见的一个在一定范围内求值的问题,搞懂题意,就好实现。本题的意思其实是:求一个两位数,这个两位数:乘以8小于100,乘以9大于等于100.示例代码如下:
private static int num(){
for(int i=10;i<13;i++){
if(8*i<100&&9*i>=100){
return i;
}
}
return 0;
}
该题目最简单的实现方法是暴力计算。实现代码如下:
private static int num(){
int count=0;
for(int i=1;i<76543210;i++) {
if(i%2!=0) {
count++;
}
}
return count;
}
该题可以转换为在2到制定的偶数之间求两个素数的过程,不过两个素数之和恰好等于该偶数。示例代码如下:
private static void printTwoPrime(int num){
if(num%2!=0){
System.out.println("不是偶数");
return;
}
int primeA=0;
int primeB=0;
for(int i=2;i<num;i++){
if(isPrime(i)){
primeA=i;
}
if(isPrime(num-i)){
primeB=num-i;
System.out.println(num+"可以是素数"+primeA+"与"+primeB+"之和");
break;
}
}
}
private static boolean isPrime(int n){
for(int i=2;i<=(int)Math.sqrt(n);i++){
if(n==2)
return true;
else if(n%i==0)
return false;
}
return true;
}
该题考运算符和循环的使用,该题条件比较简单,用while循环就行。示例代码如下:
private static int count(int num){
int result=0;
while(num%9==0){
num=num/9;
result++;
}
return result;
}
关于字符串拼接的实及性能分析,有很多的内容需要了解,有机会的话在后续文章中进行简单介绍,在本题中,直接拼接两个字符串就行。示例代码如下:
private static String add(String str1,String str2){
return str1+str2;
}
该题主要考如何运用一个序列中的值,所以在这7个值的赋值上,此处做简化处理,直接赋值到一个数组中。示例代码如下:
private static void printStar(int[] arr){
for(int i=0;i<arr.length;i++){
for(int j=1;j<=arr[i];j++){
System.out.print("*");
}
System.out.println();
}
}
该提主要考的是如何计算出一个大数字不同位数上的数字,剩余的都是一些简单的计算。示例代码如下:
private static int encryption(int num){
int result=0;
/*以下四个数字分别表示个十百千位*/
int part1=num%10;
int part2=num%100/10;
int part3=num/100%10;
int part4=num/1000;
/*接下来要对每个位数上的数字进行重复操作,所以在此处将各个数字存储到一个数组中,以便使用循环进行重复操作*/
int[] arr=new int[4];
arr[0]=part1;
arr[1]=part2;
arr[2]=part3;
arr[3]=part4;
for(int i=0;i<arr.length;i++){
arr[i]+=5;
arr[i]=arr[i]%10;
}
swap(arr[0],arr[3]);
swap(arr[1],arr[2]);
result=arr[3]*1000+arr[2]*100+arr[1]*10+arr[0];
return result;
}
private static void swap(int a,int b){
int temp=a;
a=b;
b=temp;
}
字符串匹配也是一类常见的题目,在本题中,可以先不考虑性能等因素,直接暴力匹配就行。在本题中,可以将两个字符串拆分成两个char数组,然后对子字符串转换成的char数组逐个比较,匹配成功,次数+1,直到总的字符串比较完成。示例代码如下:
private static int count(String str1,String str2){
int count=0;
int tempCnt=0;
for(int i=0;i<str1.length();i++){
for(int j=0;j<str2.length();j++){
if(str1.charAt(i)==str1.charAt(j)){
tempCnt++;
if(tempCnt==str2.length()){
count++;
tempCnt=0;
break;
}
}
}
}
return count;
}
此题考的内容有点多,文件创建于读写此处省略,简单理解为求平均值。本题简化为创建一个二维数组,分别存不同学生的成绩,我们只要求学生成绩的平均值。示例代码如下:
private static double[] average(int[][] grades){
double[] result=new double[grades.length];
int sum=0;
for(int i=0;i<result.length;i++){
sum=0;
for(int j=0;j<grades[i].length;j++){
sum=sum+grades[i][j];
result[i]=(double)sum/3;
}
}
return result;
}