1.1.1 给出以下表达式的值:
a. ( 0 + 15 ) / 2
b. 2.0e-6 * 100000000.1
c. true && false || true && true
答案:
a.7
b.200.0000002
c.ture
1.1.2 给出以下表达式的类型和值:
a. (1 + 2.236)/2
b. 1 + 2 + 3 + 4.0
c. 4.1 >= 4
d. 1 + 2 + "3"
答案:
a.1.618
b. 10.0
c.true
d.33
1.1.3 编写一个程序,从命令行得到三个整数参数。如果它们都相等则打印equal,否则打印not equal。
答案:
public class Test {
public static void main(String[] args) {
System.out.println("请输入要比较的整数参数:");
Scanner in = new Scanner(System.in);
int a = in.nextInt();
int b = in.nextInt();
int c = in.nextInt();
if (a==b&&b==c){
System.out.println("equal");
}else{
System.out.println("not equal");
}
}
}
1.1.4 下列语句各有什么问题(如果有的话)?
a. if (a > b) then c = 0;
b. if a > b { c = 0; }
c. if (a > b) c = 0;
d. if (a > b) c = 0 else b = 0;
答案:
a错,没有then关键字
b错,if后面的判断语句要用() 比如if(a>b)
c对
d对
1.1.5 编写一段程序,如果double 类型的变量x 和y 都严格位于0 和1 之间则打印true,否则打印false。
答案:
public class Test {
public int comp(double x){
if (x>0.0&&x<1.0){
return 1;
}else
return 0;
}
public static void main(String[] args) {
Test test = new Test();
System.out.println("请输入double类型的参数:");
Scanner in = new Scanner(System.in);
double x = in.nextDouble();
double y = in.nextDouble();
if (test.comp(x)==1&&test.comp(y)==1){
System.out.println("true");
}else
System.out.println("false");
}
}
1.1.6 下面这段程序会打印出什么?
int f = 0;
int g = 1;
for (int i = 0; i <= 15; i++)
{
StdOut.println(f);
f = f + g;
g = f - g;
}
答案:
0
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
1.1.7 分别给出以下代码段打印出的值:
a. double t = 9.0;
while (Math.abs(t - 9.0/t) > .001)
t = (9.0/t + t) / 2.0;
StdOut.printf("%.5f\n", t);
b. int sum = 0;
for (int i = 1; i < 1000; i++)
for (int j = 0; j < i; j++)
sum++;
StdOut.println(sum);
c. int sum = 0;
for (int i = 1; i < 1000; i *= 2)
for (int j = 0; j < 1000; j++)
sum++;
StdOut.println(sum);
答案:
a.3.00009
b.499500
c.10000
1.1.8 下列语句会打印出什么结果?给出解释。
a. System.out.println('b');
b. System.out.println('b' + 'c');
c. System.out.println((char) ('a' + 4));
答案:
a.b
b.197
c.e
1.1.9 编写一段代码,将一个正整数N 用二进制表示并转换为一个String 类型的值s。
解答:Java 有一个内置方法Integer.toBinaryString(N) 专门完成这个任务,但该题的目的就是给出这个方法的其他实现方法。
下面就是一个特别简洁的答案:
String s = "";
for (int n = N; n > 0; n /= 2)
s = (n % 2) + s;
答案:
public class Test {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("请输入整数:");
int N = in.nextInt();
String s = "";
for (int n = N; n > 0; n /= 2)
s = (n % 2) + s;
System.out.println(s);
}
}
1.1.10 下面这段代码有什么问题?
int[] a;
for (int i = 0; i < 10; i++)
a[i] = i * i;
答案:
没有用new为a[]分配内存,会报错,Variable 'a' might not have been initialized
1.1.11 编写一段代码,打印出一个二维布尔数组的内容。其中,使用* 表示真,空格表示假。打印出行号和列号。
答案:
public class Test {
public static void main(String[] args) {
boolean[][] a = new boolean[10][10];//新建二维数组
a=RandomInitial(a);//随机初始化
TestPrint(a);//打印数组
}
public static void TestPrint(boolean [][] a)
{
for(int i=0;i<a.length;i++)//打印行号
System.out.print(" "+i);
System.out.println(" "); //会得到 0 1 2 3 4 5 6 7 8 9
for(int i=0;i<10;i++)
{
System.out.print(i); //每一列开头的数字
for(int j=0;j<10;j++)
{
if(a[i][j])
System.out.print("*"+" ");
else
System.out.print(" "+" ");
}
System.out.println(" "); //生成列的模样
}
}
public static boolean[][] RandomInitial( boolean [][] a)
{
for(int i=0;i<a.length;i++) //行
{
for(int j=0;j<a.length;j++) //列
{
if(Math.random()>0.5) //因为Math.random()范围是0-1
a[i][j]=true;
else
a[i][j]=false;
}
}
return a;
}
}
1.1.12 以下代码段会打印出什么结果?
int[] a = new int[10];
for (int i = 0; i < 10; i++)
a[i] = 9 - i;
for (int i = 0; i < 10; i++)
a[i] = a[a[i]];
for (int i = 0; i < 10; i++)
System.out.println(i);
答案:
0
1
2
3
4
5
6
7
8
9
1.1.13 编写一段代码,打印出一个M 行N 列的二维数组的转置(交换行和列)。
答案:
public class Test {
public int[][] randm(int m,int n){ //生成1-10的随机数
int[][] a= new int[m][n];
for (int i =0;i<m;i++)
for (int j =0;j<n;j++){
a[i][j]=(int)(Math.random()*10);
}
return a;
}
public void outarr(int[][] a){ //打印二维数组
for (int i=0;i<a.length;i++){
for (int j =0;j<a[i].length;j++){
System.out.print(a[i][j]+" ");
}
System.out.println();
}
}
public int[][] outmig(int m,int n,int[][] a){ //进行转置
int[][] b = new int[n][m];
for (int i=0;i<b.length;i++) {
for (int j = 0; j < b[i].length; j++) {
b[i][j] = a[j][i];
}
}
return b; //获取转置后的数组b
}
public static void main(String[] args) {
int m=4,n=3; //原数组4行3列,转置后3行4列
Test test = new Test();
int[][] a =test.randm(m,n);
System.out.println("原来的二维数组:");
test.outarr(a);
System.out.println("转置后的二维数组:");
int[][] b =test.outmig(m,n,a);
test.outarr(b);
}
}
1.1.14 编写一个静态方法lg(),接受一个整型参数N,返回不大于log2N 的最大整数。不要使用Math 库。
答案:
public class Test {
public static int lg(int N){
int m=1;
int flag=0; //返回的值
for (int i=0;m<N;i++){
m=m*2;
flag++;
}
return flag;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("请输入N的值:");
int N = in.nextInt();
System.out.println(lg(N));
}
}
1.1.15 编写一个静态方法histogram(),接受一个整型数组a[] 和一个整数M 为参数并返回一个大小为M的数组,其中第i个元素的值为整数i在参数数组中出现的次数。如果a[]中的值均在0到M-1之间,返回数组中所有元素之和应该和a.length 相等。
答案:
public static int[] histogram(int [] a,int M)
{
int[] b= new int [M];
int n=0;
int m=0;
for(int i=0;i<M;i++)
{
for(int j=0;j<a.length;j++)
{
if(i==a[j])
{
n++;
}
b[i]=n;
}
n=0;
}
for(int i=0;i<M;i++)
{
m=m+b[i];
}
return b;
}
1.1.16 给出exR1(6) 的返回值:
public static String exR1(int n)
{
if (n <= 0) return "";
return exR1(n-3) + n + exR1(n-2) + n;
}
答案:
311361142246
1.1.17 找出以下递归函数的问题:
public static String exR2(int n)
{
String s = exR2(n-3) + n + exR2(n-2) + n;
if (n <= 0) return "";
return s;
}
答案:
这段代码中的基础情况永远不会被访问。调用exR2(3) 会产生调用exR2(0)、exR2(-3) 和exR2(-6),循环往复直到发生StackOverflowError。可以修改为:
public static String exR2(int n)
{
if (n <= 0) return "";
String s = exR2(n-3) + n + exR2(n-2) + n;
return s;
}
就和上题类似
1.1.18 请看以下递归函数:
public static int mystery(int a, int b)
{
if (b == 0) return 0;
if (b % 2 == 0) return mystery(a+a, b/2);
return mystery(a+a, b/2) + a;
}
mystery(2, 25) 和mystery(3, 11) 的返回值是多少?给定正整数a 和b,mystery(a,b)
计算的结果是什么?将代码中的+ 替换为* 并将return 0 改为return 1,然后回答相同
的问题。
答案:
50
33
2^55
3^11
1.1.19 在计算机上运行以下程序:
public class Fibonacci{
public static long F(int N)
{
if (N == 0) return 0;
if (N == 1) return 1;
return F(N-1) + F(N-2);
}
public static void main(String[] args)
{
for (int N = 0; N < 100; N++)
StdOut.println(N + " " + F(N));
}
}
计算机用这段程序在一个小时之内能够得到F(N) 结果的最大N 值是多少?开发F(N) 的一个更好的实现,用数组保存已经计算过的值。
答:
//最大的N值不知道,不过算到45-50左右速度就很慢了
//原因是没有中间值,一直从头算起
修改后的程序:
public class Test {
public static long[] aa(int N) { //进行计算 返回结果数组a
long[] a = new long[N];
a[0] = 0;
a[1] = 1;
for (int i = 2; i < N; i++) {
a[i] = a[i - 1] + a[i - 2];
}
return a;
}
public static void main(String[] args) {
long[] b = aa(100);
for (int i = 0; i < 100; i++) { //遍历结果数组b
System.out.println(i + " : " + b[i]);
}
}
}
//修改后用数组来承接,就有了中间值,1秒就算完了
1.1.20 编写一个递归的静态方法计算ln(N!) 的值。
答案:
public class Test {
public static double logg(int N){
if (N>1)
return Math.log(N)+logg(N-1);
else
return 0;
}
public static void main(String[] args) {
System.out.println(logg(3));
}
}
1.1.21 编写一段程序,从标准输入按行读取数据,其中每行都包含一个名字和两个整数。然后用printf() 打印一张表格,每行的若干列数据包括名字、两个整数和第一个整数除以第二个整数的结果,精确到小数点后三位。可以用这种程序将棒球球手的击球命中率或者学生的考试分数制成表格。
答案:
public class Test {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("请按顺序输入姓名 第一个整个 第二个整数,以空格隔开:");
String a = in.nextLine();
String[] strings = a.split(" ");//以空格隔开存入数组strings中
double a1=Double.parseDouble(strings[1]);
double a2=Double.parseDouble(strings[2]);
System.out.printf("姓名:"+strings[0]+",第一个数:"+a1+",第二个数:"+a2+",结果:");
System.out.printf("%.3f",a1/a2);
}
}
1.1.22 使用1.1.6.4 节中的rank() 递归方法重新实现BinarySearch 并跟踪该方法的调用。每当该方法被调用时,打印出它的参数lo 和hi 并按照递归的深度缩进。提示:为递归方法添加一个参数来保存递归的深度。
答案:
public class Test {
public static int rank(int key,int[] a,int depth){
return rank(key,a,0,a.length-1,depth);
}
public static int rank(int key,int[] a,int lo,int hi,int depth){
System.out.println("depth = " + depth + ", lo = " + lo + ", hi = " + hi); //depth深度,lo和hi是数组的下标
if (lo>hi)
return -1;
int mid=lo+(hi-lo)/2;
if (key<a[mid]){
depth++;
return rank(key,a,lo,mid-1,depth);
}
else if (key>a[mid]) {
depth++;
return rank(key, a, mid + 1, hi, depth);
}
else
return mid;
}
public static void main(String[] args) {
int[] a={10,11,12,16,18,23,29,33,48,54,57,68,77,84,98};
rank(23,a,0);//深度从0开始
}
}
1.1.23 为BinarySearch 的测试用例添加一个参数:+ 打印出标准输入中不在白名单上的值;-,则打印出标准输入中在白名单上的值。
答案:
public static int rank(int key, int[] a,char c) {
int lo = 0;
int hi = a.length - 1;
if(c=='+')
{
while (lo <= hi) {
// Key is in a[lo..hi] or not present.
int mid = lo + (hi - lo) / 2;
if (key < a[mid]) hi = mid - 1;
else if (key > a[mid]) lo = mid + 1;
else
return mid;
}
return -1;
}
if(c=='-')
{
while (lo <= hi) {
// Key is in a[lo..hi] or not present.
int mid = lo + (hi - lo) / 2;
if (key < a[mid]) hi = mid - 1;
else if (key > a[mid]) lo = mid + 1;
else
return -1;
}
return 0;
}
else
return -1;
}
1.1.24 给出使用欧几里德算法计算105 和24 的最大公约数的过程中得到的一系列p 和q 的值。扩展该算法中的代码得到一个程序Euclid,从命令行接受两个参数,计算它们的最大公约数并打印出每次调用递归方法时的两个参数。使用你的程序计算1 111 111 和1 234 567 的最大公约数。
答案:
//网上的答案
public class Test {
public static int CommomDivisor(int x,int y)
{
if(x==1||y==1)
{
System.out.println("x="+x+"y="+y);
return 1;}
if(x<y)
{
int temp=x;
x=y;
y=temp;
}
System.out.println("x="+x+"y="+y);
if(x%y==0)
{
return y;
}
else
{
x=x%y;
System.out.println("x="+x);
return CommomDivisor( x,y);
}
}
public static void main(String[] args) {
CommomDivisor(1111111,1234567);
}
}
1.1.25 使用数学归纳法证明欧几里德算法能够计算任意一对非负整数p 和q 的最大公约数。
答案:
//不会。。。
1.1.26 将三个数字排序。假设a、b、c 和t 都是同一种原始数字类型的变量。证明以下代码能够将a、b、c 按照升序排列:
if (a > b) { t = a; a = b; b = t; }
if (a > c) { t = a; a = c; c = t; }
if (b > c) { t = b; b = c; c = t; }
答案:
用t来当中间值,if语句进行判断,大的数字往前移动。