1.[编程题]抛小球
小东和三个朋友一起在楼上抛小球,他们站在楼房的不同层,假设小东站的楼层距离地面N米,球从他手里自由落下,每次落地后反跳回上次下落高度的一半,并以此类推知道全部落到地面不跳,求4个小球一共经过了多少米?(数字都为整数)
给定四个整数A,B,C,D,请返回所求结果。
100,90,80,70
返回:1020
设整数为x,得到公式:
sn = x + x * (1 + 1/2 + 1/4 + ... + (1/2)^m)
sn = x + x * (1- (1/2)^m) / (1-1/2)
(1/2)^m 无限接近于0
sn = x + x * 2;
sn = 3x;
所以答案为 3*(A+B+C+D)
import java.util.*;
public class Balls {
public int calcDistance(int A, int B, int C, int D) {
return 3*(A+B+C+D);
}
}
递归应该也行,每次只算掉下去,再上来到一半的那部分,注意,double和(int)的强制转换
import java.util.*;
public class Balls {
double distance(double n){
if(n==0)
return 0;
return n+n/2+distance(n/2);
}
public int calcDistance(int A, int B, int C, int D) {
return (int)(distance(A)+distance(B)+distance(C)+distance(D));
}
}
2. [编程题] 小东分苹果
果园里有一堆苹果,一共n头(n大于1小于9)熊来分,第一头为小东,它把苹果均分n份后,多出了一个,它扔掉了这一个,拿走了自己的一份苹果,接着第二头熊重复这一过程,即先均分n份,扔掉一个然后拿走一份,以此类推直到最后一头熊都是这样(最后一头熊扔掉后可以拿走0个,也算是n份均分)。问最初这堆苹果最少有多少个。
给定一个整数n,表示熊的个数,返回最初的苹果数。保证有解。
2
返回:3
解题思路:
无法从后往前推,那就从n+1开始遍历,肯定会有n+1个苹果,中间判断减1后能否整除n,不符合的直接break跳出这一轮,直到最后一个熊领走
import java.util.*;
public class Apples {
public int getInitial(int n) {
for(int i=n+1;;i++){
int temp=i;
int bear=n;
while(bear>0){
if(temp%n==1){
temp=temp-(temp-1)/n-1;
bear--;
}else{
break;
}
}
if(bear==0){
return i;
}
}
}
}
3. [编程题]上台阶
有一楼梯共m级,刚开始时你在第一级,若每次只能跨上一级或者二级,要走上m级,共有多少走法?注:规定从一级到一级有0种走法。
给定一个正整数int n,请返回一个数,代表上楼的方式数。保证n小于等于100。为了防止溢出,请返回结果Mod 1000000007的值。
3
返回:2
解题思路:
很常见的的一个题,注意这里防止溢出那部分!!!!!所有数都要mod
不能只mod结果
import java.util.*;
public class GoUpstairs {
public int countWays(int n) {
if(n<=3){
return n-1;
}
int temp=0;
int res=2;
int pre=1;
for(int i=4;i<=n;i++){
temp=res%1000000007;
res=(res+pre)%1000000007;
pre=temp%1000000007;
}
return res%1000000007;
}
}
4. . 孩子们的游戏(圆圈中最后剩下的数)
解析:
约瑟夫环,可以找规律,但感觉通过数组或链表来模拟环还是很方便的
<span style="font-family:Microsoft YaHei;font-size:14px;">public class Solution {
public int LastRemaining_Solution(int n, int m) {
if(n<1||m<1)//先判断这个
return -1;
int count=n;//现在还剩下的人数
int step=0;//每轮走的步数!
int i=-1;//指针,跟着绕,保证环的特征
int[] a=new int[n];
//因为要求出最后剩下的那个的编号,所以不能在删除倒数第二个点的时候就退出,
//要接着去删最后一个点,就可以得到位置了
while(count>0){
i++;//指向数组中的数
if(i>=n)//记住这是一个环,通过i来保持环的特征,编号为0~n-1,所以i变为n时就要清回0了
i=0;
if(a[i]==-1)
continue;//删除点的时候将值变为-1.看到-1,就结束本次循环,直接下次循环
step++;
if(step==m){
a[i]=-1;
step=0;
count--;
}
}
return i;
}
}</span>
5.二维数组打印
有一个二维数组(n*n),写程序实现从右上角到左下角沿主对角线方向打印。
给定一个二位数组arr及题目中的参数n,请返回结果数组。
[[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]],4
返回:[4,3,8,2,7,12,1,6,11,16,5,10,15,9,14,13]
一个正方形矩阵,找到规律遍历的时候可以只遍历右上半部分,左下半部分是对应的,用n-1去减横纵就行
主要是找到上半部分的规律
单独把p放出来,自己控制它的++
打印完每个斜排后p++
每个斜排的行是由当前列来决定的,放在列的循环里面
import java.util.*;
public class Printer {
public int[] arrayPrint(int[][] arr, int n) {
// write code here
int[] a=new int[n*n];
int p=0;
for(int i=n-1;i>=0;i--){
for(int j=0;j<n-i;j++){
a[p]=arr[j][i+j];
a[n*n-1-p]=arr[n-1-j][n-1-i-j];
p++;
}
}
return a;
}
}
6.[编程题]棋子翻转
在4x4的棋盘上摆满了黑白棋子,黑白两色的位置和数目随机其中左上角坐标为(1,1),右下角坐标为(4,4),现在依次有一些翻转操作,要对一些给定支点坐标为中心的上下左右四个棋子的颜色进行翻转,请计算出翻转后的棋盘颜色。
给定两个数组A和f,分别为初始棋盘和翻转位置。其中翻转位置共有3个。请返回翻转后的棋盘。
[[0,0,1,1],[1,0,1,0],[0,1,1,0],[0,0,1,0]],[[2,2],[3,3],[4,4]]
返回:[[0,1,1,1],[0,0,1,0],[0,1,1,0],[0,0,1,0]]
解析:
一开始以为边界要处理,后来发现,超出边界的部分不用管,所以分四个方向单独完成就行
import java.util.*;
public class Flip {
public int[][] flipChess(int[][] A, int[][] f) {
// write code here
for(int i=0;i<f.length;i++){
int row=f[i][0]-1;
int col=f[i][1]-1;
if(row-1>=0){
A[row-1][col]=(A[row-1][col])==1?0:1;
}
if(row+1<=3){
A[row+1][col]=(A[row+1][col])==1?0:1;
}
if(col-1>=0){
A[row][col-1]=(A[row][col-1])==1?0:1;
}
if(col+1<=3){
A[row][col+1]=(A[row][col+1])==1?0:1;
}
}
return A;
}
}
7. [编程题]平均年龄
从今年3月末开始,请实现一个算法,可以计算出第N年后公司员工的平均年龄。(结果向上取整)。
输入描述:
输入W Y x N
输出描述:
输出第N年后的平均年龄
输入例子:
5 5 0.2 3
输出例子:
15
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
while(sc.hasNext()){
int w=sc.nextInt();
double y=sc.nextDouble();
double x=sc.nextDouble();
int n=sc.nextInt();
while(n>0){
n--;
y= 21 * x + (1 - x) * (y + 1);//老员工要加一岁
}
System.out.println((int)Math.ceil(y));//记得向上取整,还要变成int
}
}
}
8. 小易是一个数论爱好者,并且对于一个数的奇数约数十分感兴趣。一天小易遇到这样一个问题: 定义函数f(x)为x最大的奇数约数,x为正整数。 例如:f(44) = 11.
现在给出一个N,需要求出 f(1) + f(2) + f(3).......f(N)
例如: N = 7
f(1) + f(2) + f(3) + f(4) + f(5) + f(6) + f(7) = 1 + 1 + 3 + 1 + 5 + 3 + 7 = 21
小易计算这个问题遇到了困难,需要你来设计一个算法帮助他。
解析:
奇数的最大奇约数就是它自己
偶数的最大奇约数是它自己不停除以2,得到的那个奇数
如果n=10,f(1) + f(2) + f(3) + f(4) + f(5) + f(6) + f(7) + f(8) + f(9) + f(10)=1+3+5+7+9+ f(2) + f(4) + f(6) + f(8) + f(10)
而f(2) + f(4) + f(6) + f(8) + f(10)刚好等于f(1) + f(2) + f(3) + f(4) + f(5)
依此类推,这些数的最大奇约数和是 奇数的和+n/2后所有数的最大奇约数和
等差数列求和:(a1+an)*n/2
所以这里n=偶数时,sum+=(n/2)*(1+n-1)/2,这是1~n中奇数的和
n=奇数时,sum+=((n+1)/2)*(1+n)/2,这也是1~n中奇数的和
求完奇数的和之后记得n=n/2,继续向下求
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
while(sc.hasNext()){
long n=sc.nextInt();
long sum=0;
while(n>0){
if(n%2==1){
sum+=(n+1)*(n+1)/4;
}else{
sum+=n*n/4;
}
n=n/2;
}
System.out.println(sum);
}
}
}
9.[编程题]钓鱼比赛
输入描述:
第一行五个整数n,m,x,y,t(1≤n,m,t≤1000,1≤x≤n,1≤y≤m); 接下来为一个n*m的矩阵,每行m个一位小数,共n行,第i行第j个数代表坐标为(i,j)的格子钓到鱼的概率为p(0≤p≤1)
输出描述:
输出两行。第一行为概率大的人的名字(cc/ss/equal),第二行为这个概率(保留2位小数)
输入例子:
2 2 1 1 1 0.2 0.1 0.1 0.4
输出例子:
equal 0.20
解析:
因为是随机选取,所以ss选到所有的池子概率是相等的,所以ss可以调到鱼的概率等于所有池子加起来/池子的数量
t分钟至少钓一条鱼,用对立事件 1-(1-s)^t
这道题要注意的一个地方是,从控制台读数据,如果一个一个读可能会超时,要一行一行读
import java.util.*;
public class Main {
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
while(sc.hasNext()){
int n=sc.nextInt();
int m=sc.nextInt();
int x=sc.nextInt();
int y=sc.nextInt();
int t=sc.nextInt();
sc.nextLine();//这个地方是在换行
double[][] map=new double[n][m];
double sum=0;
for(int i=0;i<n;i++){
String[] s=sc.nextLine().split(" ");
for(int j=0;j<m;j++){
map[i][j]=Double.parseDouble(s[j]);
sum+=map[i][j];
}
}
double c=map[x-1][y-1];
double s=sum/(n*m);
fish(t,c,s);
}
}
public static void fish(int t,double c,double s){
if(c>s){
System.out.println("cc");
System.out.println(String.format("%.2f", 1-Math.pow(1-c, t)));
}else if(s>c){
System.out.println("ss");
System.out.println(String.format("%.2f", 1-Math.pow(1-s, t)));
}else {
System.out.println("equal");
System.out.println(String.format("%.2f", 1-Math.pow(1-c, t)));
}
}
}