JAVA基础语法以及一些常见的练习
无符号右移和右移的区别:
无符号右移:不管正负标志位为0还是1,将该数的二进制码整体右移,左边部分总是以0填充,右边部分舍弃。
右移:该数对应的二进制码整体右移,左边的用原有标志位补充,右边超出的部分舍弃。
1)求5!+4!+3!+2!+1!
int sum=0; for(int i=1;i<=5;i++){ int ret=1; for(int j=1;j<=i;j++){ ret=ret*j; } sum=sum+ret; } System.out.println(sum); }
注意while循环后面不能加分号
int a=10; while(a>=0){ if(a==9){ continue; } a--; }
break是结束所有循环,continue是结束本次循环,当你输入的数据有很多数据的时候,优先处理字符串
2)求一个整数中,二进制中1的个数
假设现在有一个数字7,变成二进制之后是111,那么我们可以将这个数字7变成二进制的每一位依次和001进行按位与操作,这个特点是都是1结果才是1
int count=0; for(int i=0;i<32;i++){ if(((n>>i)&1)==1){ count++; } } return count; } 不管是什么数字都必须是移动32次
输入-1的话,结果就是32个1,所以不管什么数字,都必须移动31次,负数的话没有影响,因为负数只移动了31次
我们还有第二种做法,那么就是说如果在移位的过程中是正数,发现移位的过程中变成0了,那么没有必要进行移位操作了
int n = -1; int count = 0; while (n != 0) { if ((n & 1) != 0) { count++; } n = n >>> 1;//这里面必须是无符号右移,因为如果是普通的右移的话况且如果是负数的话,那么这个代码就会会死循环 } System.out.println(count); }
第三种做法:我们如果说想要求二进制中1的个数,那么可以让N一直&N-1,每一次&的过程中,原有N的1的个数都会减少
第一次按位与操作: 7--->0111 6--->0110 --------------- 第二次按位与操作 6--->0110 5--->0101 ---------------- 第三次按位与操作 4--->0100 3--->0011 --------------- 0--->00000 我们最终发现,每进行一次按位与操作,原有数字的二进制的位数就少1
int n = -1; int count = 0; while (n != 0) { n=n&(n-1); count++; } System.out.println(count);
3)计算1-1/2+1/3-1/4.....+1/100
double sum=0; int flag=-1; for(int i=1;i<=100;i++){ if(i%2==1){ flag=1; }else{ flag=-1; } sum=sum+(1.0)/i*flag; } System.out.println(sum);
4)打印一个X图案,比如说输入数字5,那么两条反斜线相交都是5
* * * * * * * * * 我们进行定义横坐标是i,定义纵坐标是j,如果说最后i==j或者是i+j+1=5满足打印*号
Scanner scanner=new Scanner(System.in); int n=scanner.nextInt(); for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ if(i==j||i+j+1==n){ System.out.print("*"); }else{ System.out.print(" "); } } System.out.println(); }
5)打印99乘法表:
Scanner scanner=new Scanner(System.in); int n=scanner.nextInt(); for(int i=1;i<n;i++){ for(int j=1;j<=i;j++){ System.out.print(i+"*"+j+"="+i*j+" "); } System.out.println(); }
6)获取一个二进制序列的所有偶数位数和奇数位数,分别输出二进制序列
int n=7;//注意二进制的循环控制位数从0开始,但是实际上以1开始 for(int i=31;i>=1;i=i-2){ System.out.print((n>>i)&1); } System.out.println(); for(int i=30;i>=0;i=i-2){ System.out.print((n>>i)&1); }
7)判断一个数是否是素数
素数:只能被1和它本身能够整除的数:
Scanner scanner=new Scanner(System.in); int n=scanner.nextInt(); int i=0; for( i=2;i<n;i++){ if(n%i==0){ System.out.println("当前数字不是素数"); break; } } //当前循环跳出只能有一种情况是素数,就是说i==n,其他条件情况下跳出都不是素数 if(i==n){ System.out.println("当前数字是素数"); }
Scanner scanner=new Scanner(System.in); int n=scanner.nextInt(); int i=0; for( i=2;i<=n/2;i++){ if(n%i==0){ System.out.println("当前数字不是素数"); break; } } if(i>n/2){ System.out.println("当前数字是素数"); } }
Scanner scanner=new Scanner(System.in); int n=scanner.nextInt(); int i=0; for( i=2;i<=Math.sqrt(n);i++){ if(n%i==0){ System.out.println("当前数字不是素数"); break; } } if(i>Math.sqrt(n)){ System.out.println("当前数字是素数"); }
函数结束之后形参将会被系统回收
我们实际上要交换两个两个变量的值,是不能获取到栈上面的地址的,如果真正想要进行交换两个变量,就要把这两个变量放在堆上面
1)直接放在一个函数里面进行交换
2)new 一个数组对象,进行交换数组里面的值
3)也可以new 一个对象
重载:方法名称相同,参数列表不同(个数,类型,顺序),通过一个方法就知道调用谁了,不需要记住那么多的方法名了,降低很多的成本
8)创建方法求两个数的最大值max2,然后再写一个求三个数的最大值函数max3,要求在max3函数里面调用max2函数,从而实现3个数的最大值计算
public static int max(int a,int b){ return a>b?a:b; } public static int MaxDown(int a,int b,int c){ int max=max(a,b); return max>c?max:c; } public static void main(String[] args) throws InterruptedException { int max=MaxDown(12,67,89); System.out.println(max); }
练习题1:求斐波那契数列的第n项,1,1,2,3,5,8 ,13,21,34;
public static int fib1(int n)
{
if(n==1||n==2)
{
return 1;
}else{
return fib1(n-1)+fib1(n-2);
}
}
public static int SumFib(int n){
int f1=1;
int f2=1;
int f3=1;
for(int i=3;i<=n;i++){
f3=f1+f2;
f1=f2;
f2=f3;
}
return f3;
}
练习题2:青蛙跳台阶问题:1,2,3,5,8..........
练习题3:汉诺塔问题
public static void move(char pos1,char pos3)
{
System.out.println(pos1+"->"+pos3);
}
public static void hannuo(int n,char pos1,char pos2,char pos3)
{
if(n==1)
{
move(pos1,pos3);
return;
}else{
hannuo(n-1,pos1,pos3,pos2);
move(pos1,pos3);
hannuo(n-1,pos2,pos1,pos3);
}
}
_________________________________________________________
2.一维数组
1)创建数组
int[] arr1={1,2,3,4,5,6};
int[] array=new int[4];
int[] array1=new int[]{1,2,3,4,5,6};
2)遍历数组,for循环可以拿到数组的下标,但是foreach不行;
//1.for循环进行打印
for(int i=0;i<arr1.length;i++)
{
System.out.println(arr1[i]);
}
//2.通过foreach的方式来进行打印
for(int s:arr1)
{
System.out.println(s);
}
//3直接调用静态方法
System.out.println(Arrays.toString(arr1));
}
3)自己实现一个数组转化成字符串的例子
public static String toString(int [] arr1)
{
String ret="[";
for(int i=0;i<arr1.length;i++)
{
ret+=arr1[i];
if(i!=arr1.length-1)
{
ret+=", ";
}
}
ret+="]";
return ret;
}
public static void main(String[] args) {
int[] arr1 = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9};
System.out.println(toString(arr1));
}
数组转化成字符串
Arrays.toString(arr1)
int arr1[]=new int[]{1,2,3,4,5};
String str1=Arrays.toString(arr1);
System.out.println(str1);
4)数组的拷贝
1)返回值是一个新的数组=Arrays.CopyOf(一开始要拷贝的数组,要拷贝的数组的长度)
int arr1={1,2,3,4,5,6,7,8,9};
int[] ret=Arrays.CopyOf(arr1,arr1.length());
System.out.println(Arrays.toString(ret));
2)System.ArrayCopy(原数组,来时拷贝的原数组的位置,现在数组开始拷贝的位置,长度);
int array[]={1,2,3,4,5,6,7};
int ret=new int{array.length];
System.ArrayCopy(array,0,ret,0,array.length);
System.out.println(Arrays.toString(ret));
3)Object的克隆方法
int[] arr1={1,2,3,4,5,6,7};
int ret[]=arr1.clone();
4)数组的各个部分进行赋值
5) 数组中的其他常用方法
1)查找数组的元素
Array.binarySearch(原数组,开始查找的位置,最终查找到哪里,要查什么)
int arr1[]={1,2,3,4,5,6,7};
System.out.println(Arrays.binarySearch(arr1,2,5,4);
这个代码的语句是从二号位置到五号位置找4
2)拷贝数组的区间
int[] ret={1,2,3,4,5,6,7};
int[] arr1=Arrays.CopyOfRange(arr1,2,4);
3)判断两个数组是否相同
直接调用Arrays.equals(数组一,数组二);返回值是一个boolean类型
4)填充
int arr1[]=new int[10];
Arrays.fill(arr1,8);
是向arr1这个数组里面填充8里面的每一个元素都是8;
Arrays.fill(arr1,2,5,8);像这个数组的2到5位置填8;
5)检查一个数组是否有序
Arrays.sort(arr1);
6)数组转化成字符串
int arr1={1,2,3,4,5,6,7,8};
String html=Arrays.toString(arr1);
数组是在栈上,数组中的每一个元素在堆上
6)实现数组的二分查找和把所有的偶数都挪到奇数前面,并实现冒泡排序,以及数组的逆序
//1实现数组的二分查找
public static int binarysearch(int[] arr1,int key)
{
int left=0;
int right=arr1.length-1;
int mid=0;
while(left<=right)
{ mid=(right+left)/2;
if(arr1[mid]>key)
{
right=mid-1;
}else if(arr1[mid]<key)
{
left=mid+1;
}else{
return mid;
}
}
return -1;
}
//2实现数组的逆序
public static int[] resverse(int arr1[])
{
int left=0;
int right=arr1.length-1;
while(left<=right)
{
int temp=0;
temp=arr1[left];
arr1[left]=arr1[right];
arr1[right]=temp;
left++;
right--;
}
return arr1;
}
//3 实现所有偶数都移到奇数前面
public static void func(int[] arr1)
{
int left=0;
int right=arr1.length-1;
while(left<=right)
{
while (left<=right&&arr1[left]%2==0)
{
left++;//此时就可以保证left下标一定指向奇数
}
while(left<=right&&arr1[right]%2!=0)
{
right--;
}
int temp=arr1[left];
arr1[left]=arr1[right];
arr1[right]=temp;
}
}
//4 实现冒泡排序
public static void sort1(int[] arr1)
{
for(int i=0;i<arr1.length-1;i++)
{ boolean flag=false;
for(int j=0;j<arr1.length-1;j++)
{
if(arr1[j]>arr1[j+1])
{
int temp=arr1[j];
arr1[j]=arr1[j+1];
arr1[j+1]=temp;
flag=true;
}
}
if(flag==false)
{
return;
}
}
}
7)数组的循环右移,以及消失的数字,位运算习题
leetcode189题,旋转数组
public static void resverse(int [] arr1,int left,int right)
{
while(left<=right)
{
int temp=arr1[left];
arr1[left]=arr1[right];
arr1[right]=temp;
left++;
right--;
}
}
public static void reverseKey(int[] arr1,int n)
{ if(n>arr1.length-1)
{
n=n%arr1.length-1;
}
resverse(arr1,arr1.length-n,arr1.length-1);
resverse(arr1,0, arr1.length-1-n);
resverse(arr1,0, arr1.length-1);
}
public static void main(String[] args) {
int [] array={1,2,3,4,5,6,7,8,9};
reverseKey(array,3);
System.out.println(Arrays.toString(array));
}
leetcode
数组num中包含从0到n的所有整数,但是其中缺少了一个,找出缺失的整数,要求在O(N)时间内完成
思路:使用异或(相同为0,不相同为1)
2^3=1
00010
00011
相同的数异或之后就没了
让数组中的数依次和0-N的所有数进行异或,最后剩下的那个数字就是缺的那个数字
public static int func(int[] arr1)
{ int ret=0;
for(int i=0;i<arr1.length-1;i++)
{
ret=ret^arr1[i];
}
for(int j=0;j<arr1.length+1;j++)
{
ret=ret^j;
}
return ret;
}
8)判断一个数是否是素数
public static int isyear(int n)
{
for(int i=2;i<=Math.sqrt(n);i++)
{
if(n%i==0)
{
return 0;
}
}
return 1;
}
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int num=scanner.nextInt();
if(isyear(num)==1)
{
System.out.println(num+"是素数");
}else{
System.out.println(num+"不是素数");
}
}
9)判断一个数是否是水仙花数
水仙花数是指一个 3 位 数,它的每个位上的数字的 3次幂之和等于它本身。例如:1^3 + 5^3+ 3^3 = 153
思路:
1)先算是几位数
2)求每一位数字是几,位的次幂求出来进行求和
public static boolean isNum(int n)
{
//1 首先判断它是几位数
int num=n;
int s1=0;
int sum=0;
int count=0;
while(num!=0)
{
num=num/10;
count++;
}
num=n;
while(num!=0)
{
s1=num%10;
num=num/10;
sum=(int)(sum+Math.pow(s1,count));
}
if(sum==n)
{
return true;
}else{
return false;
}
}
10)求两个数的最大公约数
第一种方法: int min=0; if(num1>num2) { min=num2; }else{ min=num1; } while(min>0) { if(num1%min==0&&num2%min==0) { return min; }else{ min--; } } return min;
辗转相除法:求直到取模为0之后最近的那一个除数
以24和18来进行举例:
1)24%18=6
2)18%6=3
Scanner scanner=new Scanner(System.in); int m=scanner.nextInt(); int n=scanner.nextInt(); int model=m%n; while(model!=0){ m=n; n=model; model=m%n; } System.out.println("最大公约数是"+n); }
3)二维数组:他的本质上是一个一维数组,只不过二维数组中的每一个元素又是一维数组;
定义二维数组:分成规则的二维数组和不规则的二维数组
int array[][]={{1,2,3},{4,5,6}};
int arr2[][]=new int[][]{{1,2,3},{4,5,6}};//不需要写行数列数
int arr1[][]=new int[2][];//必须指定行
//1打印二维数组
for(int i=0;i<array.length;i++){
for(int j=0;j< array[i].length;j++){
System.out.print(array[i][j]+" ");
}
System.out.println();
}
//2以字符串的形式打印出来
System.out.println(Arrays.deepToString(array));
Arrays.toString(array);//这是打印出来的是两个地址
//3运用foreach进行循环打印
for(int[] temp:array)//这里面不可以用整形来接受
{
for(int x:temp)//因为二维数组中的每一个元素都是一维数组,我们先用temp数组来接受二维数组中的每一个元素,然后再进行循环打印
{
System.out.println(x);
}
}
在java中数组要指定行,列可以自己进行推导
int[][]array=new int[2][];
array[0]=new int[3]; {1,2,3}
array[1]=new int[2]; {4,5,6}
[]中写个数就不要写初始化,能够进行初始化就不要写个数