基础练习 - 笔记和题解

这篇博客详细介绍了算法分析中的计算程序运行时间,探讨了递归的三个核心要素,并举例说明如何正确实现递归函数。此外,还涵盖了向上取整、向下取整和四舍五入的方法,以及String和int之间的转换。博主通过实例讲解了特殊样例的处理,包括数列求和、圆的面积、Fibonacci数列、字串和字母图形等,同时涉及大数处理和进制转换问题,如十进制、十六进制和八进制的相互转换。
摘要由CSDN通过智能技术生成

笔记

一、算法分析 - 计算程序运行时间

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();
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值