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)次方
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import java.util.*; public class Ants { public double antsCollision(int n) { // write code here return (1 - Math.pow(0.5, n - 1)); } }
3.给定直角坐标系上的两条线,确定这两条线会不会相交。
思路:两条线若不平行则必相交。因此,要检查两条线相交与否,只需检查两者的斜率是否相同或是否为同一条直线。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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; } }
注意:不要假设斜率和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的值。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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; } }
注意:要小心假设。不要假设所有数都是正数,也不该假设a会比b大。
5.在二维平面上,有两个正方形,请找出一条直线,能够将这两个正方形对半分。假定正方形的上下两条边与x轴平行。
6.在二维平面上,有一些点,请找出经过点数最多的那条线。
7.有些数的素因子只有3、5、7,请设计一个算法,找出其中第k个数。
解法:《九章算法》chapter eight 丑数I II
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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); } }