1.有个篮球框,下面两种玩法可任选一种。玩法1:一次出手机会,投篮命中得分。玩法2:三次出手机会,必须投中两次。如果p是某次投篮命中的概率,则p的值为多少时,才会选择玩法1或玩法2?

解法:假设投中概率是p,p1 = p;  p2 = 3 * p * p * (p - 1);  算什么情况下选玩法一:p1 > p2.求得p < 0.5的时候。p > 0.5选第二种。但是p = 0, 1, 0.5两种都是一样的。

2.三角形的三个顶点上各有一只蚂蚁。如果蚂蚁开始沿着三角形的边爬行,两只或三只蚂蚁撞在一起的概率有多大?假定每只蚂蚁会随机选一个方向,每个方向被选到的几率相等,而且三只蚂蚁的爬行速度相同。

解法:当其中两只蚂蚁互相朝着对方而行,就会发生碰撞。因此,蚂蚁不发生碰撞的前提是,它们都朝着同一方向爬行(顺时针或逆时针)。

P(顺时针)=P(逆时针)=(1/2)的三次方=1/8  P(同方向)=1/4   P(碰撞)= 1 - P(同方向)=3/4 

类似问题:在n个顶点的多边形上有n只蚂蚁,求出这些蚂蚁发生碰撞的概率。

P(碰撞)= 1 - P(同方向)= 1 - (1/2)的(n-1)次方

import java.util.*;

public class Ants {
    public double antsCollision(int n) {
        // write code here
        return (1 - Math.pow(0.5, n - 1));
    }
}
View Code

3.给定直角坐标系上的两条线,确定这两条线会不会相交。

思路:两条线若不平行则必相交。因此,要检查两条线相交与否,只需检查两者的斜率是否相同或是否为同一条直线。

public class Line {
    static double epsilon = 0.000001;
    static double slope;//斜率
    static double yintercept;//y轴截距
    public Line(double s, double y) {
        slope = s;
        yintercept = y;
    }
    public boolean intersect(Line line2) {
        //两条线斜率不相同或者y轴截距相同一定会相交
        return Math.abs(slope - line2.slope) > epsilon ||
               Math.abs(yintercept - line2.yintercept) < epsilon;
    }
}
View Code

注意:不要假设斜率和y轴截距就是整数。切记不要用==检查浮点数是否相等,而是应该检查两者差值是否小于某个极小值(如上面代码中的epsilon值)。

4.编写方法,实现整数的乘法、减法和除法运算。只允许使用加号。

思路:对于每个子问题,深入思考这些运算的本质,或者如何其他运算表示(加法或已实现的运算)。

1.减法:a-b=a+(-1)*b。但是不能使用乘号,必须实现一个取反(negate)运算。要对数值+k(-k)取反,只需将-1(+1)连加k次。

2.乘法。a乘以b就是将a连加b次。要注意如果b为负数,需要将sum值取反,即multiply(a, b)=abs(b)*a*(-1 if b <0)

3.除法。计算x=a/b中的x。好好利用等式a=xb,将b与它自身连加直至得到a,就能算出x。b与自身连加的次数等于x的值。

public class AddSubstitution {
    //减法
    //取反操作
    public static int negate(int a) {
        int neg = 0;
        int d = a < 0 ? 1 : -1;
        while (a != 0) {
            neg += d;
            a += d;
        }
        return neg;
    }
    //两数相减相当于对b取反,然后将两数相加
    public static int minus(int a, int b) {
        return a + negate(b);
    }
    //乘法
    //将a连加b次,实现a乘b
    public static int multiply(int a, int b) {
        if (a < b) {
            return multiply(b, a);//若b < a,算法会比较快
        }
        int sum = 0;
        for (int i = abs(b); i > 0; i--) {
            sum +=a;
        }
        if (b < 0) {
            sum = negate(sum);
        }
        return sum;
    }
    //返回绝对值
    public static int abs(int a) {
        if (a < 0) {
            return negate(a);
        } else {
            return a;
        }
    }
    //除法
     public static int divide(int a, int b) {
        if (b > a) {
            return 0;
        }
        int count = 0;
        int a1 = abs(a);
        int b1 = abs(b);
        int sum = b1;
        while (sum <= a1) {
            count++;
            sum += b1;
        }
        if (a > 0 && b < 0 || a < 0 && b > 0) {
            count = negate(count);
        }
        return count;
    }
}
View Code

注意:要小心假设。不要假设所有数都是正数,也不该假设a会比b大。

5.在二维平面上,有两个正方形,请找出一条直线,能够将这两个正方形对半分。假定正方形的上下两条边与x轴平行。

6.在二维平面上,有一些点,请找出经过点数最多的那条线。

7.有些数的素因子只有3、5、7,请设计一个算法,找出其中第k个数。

解法:《九章算法》chapter eight 丑数I II

import java.util.ArrayList;

public class getNthNumber {
    public int nthUglyNumber(int n) {
        // Write your code here
        ArrayList<Integer> uglys = new ArrayList<Integer>();
        uglys.add(1);
        int p3 = 0;
        int p5 = 0;
        int p7 = 0;
        for (int i = 1; i < n; i++) {
            int lastNumber = uglys.get(i - 1);
            while (uglys.get(p3) * 3 <= lastNumber) {
                p3++;
            }
            while (uglys.get(p5) * 5 <= lastNumber) {
                p5++;
            }
            while (uglys.get(p7) * 7 <= lastNumber) {
                p7++;
            }
            uglys.add(Math.min(
                Math.min(uglys.get(p3) * 3, uglys.get(p5) * 5),
                uglys.get(p7) * 7
            ));
        }
        return uglys.get(n - 1);
    }
}
View Code