目录
笔记
一、算法分析 - 计算程序运行时间
long startTime = System.currentTimeMillis();
long endTime = System.currentTimeMillis();
System.out.println((endTime-startTime)/1000f + " seconds.");
二、递归三要素
1.明确这个函数的作用
以计算n的阶乘为例
public static int factoria(int n){
//传入n,传出n的阶乘
}
2.找到递归结束条件
递归,就是在函数内部中不断调用函数本身
如果没有结束条件,函数就会一直进行下去
找到一个能直接由参数确定的结果
public static int factoria(int n){
if(n == 1){
//1的阶乘为1
return 1;
}
}
3.找出函数的等价关系式
通过循环求阶乘的方法是 n = n * (n-1)
所以这里的等价关系式是 factoria(n) = n * factoria(n-1)
public static int factoria(int n){
if(n == 1)
return 1;
return n * factoria(n-1);
}
*4.限制
当递归次数过多时可能导致 StackOverflowError
在jvm运行时的数据区域中有一个java虚拟机栈,当执行java方法时会进行压栈弹栈的操作。在栈中会保存局部变量,操作数栈,方法出口等等。jvm规定了栈的最大深度,当执行时栈的深度大于了规定的深度,就会抛出StackOverflowError错误。
三、向上取整、向下取整与四舍五入
Math.ceil(double a); //向上取整 (ceili 天花板
//注意强制类型转换是向下取整
Math.floor(double b); //向下取整 (floor 地板
Math.round(3.14159); //四舍五入取整
//四舍五入的方式保留小数点后两位的方式
//方法一
DecimalFormat df = new java.text.DecimalFormat("#0.00");
df.format(3.14);
//方法二
System.out.printf("%.2f",3.1415);
//方法三 不推荐使用(depreciate)
new BigDecimal(3.14159).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
四、String和int相互转换
//String - int
Integer.parseInt(String str);
Integer.valueOf(my_str).intValue();
//int - String
String.valueOf(i);
Integer.toString(i);
"" + i;
五、常见特殊样例
- 极大值、极小值、0
- 一组、一个
题解
BASIC-02 序列求和
求1+2+3+…+n的值。
//刚学过递归,想当然地就用递归的方法写了
//忽略了数据规模(1 <= n <= 1,000,000,000)
//所以出现了StackOverflowError
//错误示范,仅供参考
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println(factorial(sc.nextInt()));
sc.close();
}
public static int factorial(int n) {
return n == 1 ? 1 : n + factorial(n - 1);
}
BASIC-03 圆的面积
给定圆的半径r,求圆的面积。
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int r=sc.nextInt();
//要求保留小数点后七位,并且四舍五入
DecimalFormat df=new DecimalFormat("#.0000000");
System.out.println(df.format(r*r*Math.PI));
sc.close();
}
BASIC-04 Fibonacci数列
Fibonacci数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1。
当n比较大时,Fn也非常大,现在我们想知道,Fn除以10007的余数是多少。
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//数据规模:[1 <= n <= 1,000,000],数组的长度要比最大多1
int[] a = new int[10000001];
a[1] = 1;
a[2] = 1;
int n = sc.nextInt();
for (int i=3; i<=n; i++){
a[i] = (a[i-1]+a[i-2])%10007;
}
System.out.println(a[n]);
sc.close();
}
BASIC-2 01字串
对于长度为5位的一个01串,每一位都可能是0或1,一共有32种可能。它们的前几个是:
00000
00001
00010
00011
00100
请按从小到大的顺序输出这32种01串。
//通过观察可以看出实际输出的是0-31的二进制数,所以只需要将十进制数转二进制再通过格式化输出即可。
for(int i=0;i<32;i++) {
int n = Integer.parseInt(Integer.toBinaryString(i));
System.out.printf("%05d", n);
System.out.println();
}
BASIC-3 字母图形
利用字母可以组成一些美丽的图形,下面给出了一个例子:
ABCDEFG
BABCDEF
CBABCDE
DCBABCD
EDCBABC
这是一个5行7列的图形,请找出这个图形的规律,并输出一个n行m列的图形。
//A:65 a:97 0:48
for (int i = 0; i < n ; i++)
for(int j = 0; j < m ; j++)
System.out.print((char)(Math.abs(i-j)+65));
System.out.println();
//65 66 67 68 65+0 65+1 65+2 65+3 j++
//66 65 66 67 65+1 65+0 65+1 65+2 i++
//67 66 65 66 65+2 65+1 65+0 65+1 i,j,abs -= abs(i-j)
//0-0 0-1 0-2 0-3
//1-0 1-1 1-2 1-3
//2-0 2-1 2-2 2-3
BASIC-4 数列特征
给出n个数,找出这n个数的最大值,最小值,和。
//忽略n=1的特殊情况
if (num > max)
max = num;
if (num < min)
min = num;
//方法一
if (num >= max || i==0)
max = num;
if (num <= min || i==0)
min = num;
//方法二
int max=-999999;
int min=999999;
BASIC-5 查找整数
给出一个包含n个整数的数列,问整数a在数列中的第一次出现是第几个。
int temp=arr.indexOf(sc.nextInt());
//因为实际位置要+1,而找不到返回的-1也会+1
//
if(temp==-1)
System.out.println(temp);
else
System.out.println(temp+1);
BASIC-6 杨辉三角形
杨辉三角形又称Pascal三角形,它的第i+1行是(a+b)i的展开式的系数。
它的一个重要性质是:三角形中的每个数字等于它两肩上的数字相加。
下面给出了杨辉三角形的前4行:
1
1 1
1 2 1
1 3 3 1
给出n,输出它的前n行。
//因为需要知道第n个数“肩上”的两个数,所以使用二维数组算出“肩上”位置
//创建二维数组
int[][] arr = new int[n][];
for (int i = 0; i < arr.length; i++) {
arr[i] = new int[i + 1];
}
//赋值
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
if (j == 0 || j == i)
arr[i][j] = 1;
System.out.print(arr[i][j]+" ");
else
arr[i][j] = arr[i - 1][j - 1] + arr[i - 1][j];
}
System.out.println();
}
BASIC-10~12 进制转换
十进制转十六进制
//直接使用自带函数即可
System.out.println(Integer.toHexString(n).toUpperCase());
十六进制转十进制
//int存不下,使用BigInteger
System.out.println(new BigInteger(str,16));
十六进制转八进制
思路
因为样例给的十六进制数很大(100000字符以内),long都放不下,所以只能自己写
每一个十六进制数字对应四个二进制数字
每一个八进制数字对应三个二进制数字
方法是先将十六进制转为二进制,再从二进制转为八进制
十六进制转为二进制后如果长度不是三的倍数要在前面补零(方便二进制转八进制)
二进制转为八进制后要将前面多余的零去掉(题目要求)
代码
public class Main {
public static void main(String[] args) {
// 接受十六进制数为字符串数组
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
String str;
String s;
for (int i = 0; i < n; i++) {
str = sc.next();
//十六进制转二进制
s = hexToBin(str);
//补零
s= hexTrim(s);
//二进制转十六进制
s = binToOct(s);
//去除多余的0
s= s.replaceFirst("^0*", "");
System.out.println(s);
}
sc.close();
}
public static String hexToBin(String str) {
char c = 0;
//String类对字符串的拼接效率到后面极慢,这里使用StringBuilder,也可以使用StringBuffer
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
c = str.charAt(i);
switch (c) {
case '0':
sb.append("0000");
break;
case '1':
sb.append("0001");
break;
case '2':
sb.append("0010");
break;
case '3':
sb.append("0011");
break;
case '4':
sb.append("0100");
break;
case '5':
sb.append("0101");
break;
case '6':
sb.append("0110");
break;
case '7':
sb.append("0111");
break;
case '8':
sb.append("1000");
break;
case '9':
sb.append("1001");
break;
case 'A':
sb.append("1010");
break;
case 'B':
sb.append("1011");
break;
case 'C':
sb.append("1100");
break;
case 'D':
sb.append("1101");
break;
case 'E':
sb.append("1110");
break;
case 'F':
sb.append("1111");
break;
default:
break;
}
}
return sb.toString();
}
public static String binToOct(String str) {
String c;
StringBuilder sb = new StringBuilder();
for (int j = 0; j < str.length(); j += 3) {
c = str.substring(j, j + 3);
switch (c) {
case "000":
sb.append('0');
break;
case "001":
sb.append('1');
break;
case "010":
sb.append('2');
break;
case "011":
sb.append('3');
break;
case "100":
sb.append('4');
break;
case "101":
sb.append('5');
break;
case "110":
sb.append('6');
break;
case "111":
sb.append('7');
break;
}
}
return sb.toString();
}
public static String hexTrim(String s) {
StringBuilder sb=new StringBuilder(s);
int len = sb.length();
if (len % 3 == 1) {
sb.insert(0, "00");
}
if (len % 3 == 2) {
sb.insert(0, "0");
}
return sb.toString();
}
}