1. 正整数A和正整数B 的最小公倍数是指 能被A和B整除的最小的正整数值,设计一个算法,求输入A和B的最小公倍数。
输入描述:输入两个正整数A和B。
输出描述:输出A和B的最小公倍数。
示例:
输入:5 7
输出:35
参考代码:
import java.util.Scanner;
//最小公倍数 = 两数之积除以最大公约数,这里使用碾转相除法进行最大公约数的求解:即a与b的最大公约数可以转化为a、b之间的余数为两者之间最小的数之间的公约数。
// 所以对于输入的两个数进行连续求余,直到余数为0,求余的分母即为结果。
public class Main {
public static int MaxCommonDivisor(int m,int n){
if(m<n){
int temp = m;
m = n;
n = temp;
}
int k;
while(n!=0){
k = m%n;
m = n;
n = k;
}
return m;
}
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
while(scanner.hasNext()){
int m = scanner.nextInt();
int n = scanner.nextInt();
System.out.println( m*n / MaxCommonDivisor(m,n));
}
}
}
2. 有一个数组a[N]顺序存放0~N-1,要求每隔两个数删掉一个数,到末尾时循环至开头继续进行,求最后一个被删掉的数的原始下标位置。以8个数(N=7)为例: {0,1, 2, 3, 4, 5, 6, 7},0->1->2(删除)->3->4->5<(删除)->6->7->0(删除),如此循环直到最后一个数被删除。
输入描述:每组数据为一行一个整数n(小于等于1000),为数组成员数,如果大于1000,则对a[999]进行计算。
输出描述:一行输出最后一个被删掉的数的原始下标位置。
示例:
输入:8
输出:6
参考代码:
//首先将数组里面的元素全部放到队列中,在队列长度不等于1的前提下进行循环操作:
//定义一个计数器count,每一次把队首元素添加到队尾,出一次,count++ 一下,当count为2时,直接将队首元素出队即可。
//最后剩下的一个元素就是最后删除的一个元素。
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
int n = scanner.nextInt();
int[] arr = new int[n];
for (int i = 0; i < arr.length; i++) {
arr[i] = i;
}
System.out.println(delete(arr));
}
scanner.close();
}
public static int delete (int[] arr) {
Queue<Integer> queue = new LinkedList<>();
for (int i = 0; i < arr.length; i++) {
queue.add(arr[i]);
}
while (queue.size() != 1) {
int count = 0;
while (count != 2) {
queue.add(queue.peek());
queue.poll();
count++;
}
queue.poll();
}
return queue.element();
}
}
3. 找出n个数里最小的k个。
输入描述:每个测试输入包含空格分隔的n+1个整数,最后一个整数位k值,n不超过100。
输出描述:输出n个整数里最小的k个数。升序输出。
示例:
输入:3 9 6 8 -10 7 -11 19 30 12 23 5
输出:-11 -10 3 6 7
参考代码:
import java.util.Arrays;
import java.util.Scanner;
public class FindKthMiniNumber {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while(scanner.hasNext()){
String str = scanner.nextLine();
String[] strs = str.split(" ");
int len = strs.length;
int[] arr = new int[len-1];
for (int i = 0; i < arr.length; i++) {
arr[i] = Integer.valueOf(strs[i]);
}
int k = Integer.valueOf(strs[len-1]);
Arrays.sort(arr);
for (int i = 0; i < k; i++) {
System.out.print(arr[i]+" ");
}
}
}
}
4. 输入一个正整数n,求n!(即阶乘)末尾有多少个0?比如: n = 10; n! = 3628800,所以答案为2。
输入描述:输入为一行,n(1 ≤ n ≤ 1000)。
输出描述:输出一个整数,即题目所求。
示例:
输入:10
输出:2
参考代码:
分析:n的阶乘:n!=1×2×3×…×n那么我们在计算n的阶乘时,实际上就是把所有小于等于n的正整数分解成质因数,然后再将其乘到一起,那么末尾0的个数实际上就是(2 * 5)的个数,而2的个数明显是很多很多的(但凡是偶数就可以分解除2),所以问题就转化成了5的个数, 而只有5的倍数才能分解出因数5,所以,问题就进一步简化为小于等于n的数中有多少个数是5的倍数,当然25的倍数,125的倍数,625还要单独考虑,比如拿25来说,25=5*5 ,里面有2个5,提供2个0。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int count = 0;
for(int i = n; i>=5; i--) {
int tmp = i;
while(tmp%5==0) {
count++;
tmp/=5;
}
}
System.out.println(count);
}
}
5. ibonacci数列是这样定义的:F[0] = 0,F[1] = 1,for each i ≥ 2: F[i] = F[i-1] + F[i-2]。因此,Fibonacci数列就形如:0, 1, 1, 2, 3, 5, 8, 13, …,在Fibonacci数列中的数我们称为Fibonacci数。给你一个N,你想让其变为一个Fibonacci数,每一步你可以把当前数字X变为X-1或者X+1,现在给你一个数N求最少需要多少步可以变为Fibonacci数?
输入描述:输入为一个正整数N(1 ≤ N ≤ 1,000,000)。
输出描述:输出一个最小的步数变为Fibonacci数。
示例:
输入:15
输出:2
参考代码:
//思路:首先,找到第一个大于等于数n的Fibonacci数x,进而得到前一个Fibonacci数y
//最后比较|x-n|和|y-n|,较小值则是最终要走的步数.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
int N=input.nextInt();
for(int i=0;;i<N;i++){
if(fib(i)>=N){ //找到第一个大于等于N的Fibonacci数
break;
}
}
int p=Math.abs(fib(i)-N);
int q=Math.abs(fib(i-1)-N);
if(p>q){
System.out.println(q);
}
else{
System.out.println(p);
}
}
private static int fib(int n){
if(n==0){
return 0;
}
if(n==1||n==2){
return 1;
}
return fib(n-1)+fib(n-2);
}
}
6. 在一个m*n的网格的左上角有一个机器人,机器人在任何时候只能向下或者向右移动,机器人试图到达网格的右下角,有多少可能的路径?
分析: 对于本题,我们采用动态规划的思想。对于网格中的每一个格子,若该格子位于第一行,则只能由左边的格子到达;若格子位于第一列,只能由上面的格子到达;网格中的其他格子可以由左边的格子到达,也可以由上面的格子到达。因此到达每一个格子的方法数都由左边的或者上面的格子所决定。我们依次从网格的左上角遍历到右下角,则到达右下角格子的方法数便是最终的结果了。
/*
状态:
子状态:从(0,0)到达(1,0),(1,1),(2,1),...(m-1,n-1)的路径数,
F(i,j): 从(0,0)到达F(i,j)的路径数
状态递推:F(i,j) = F(i-1,j) + F(i,j-1)
初始化:特殊情况:第0行和第0列,F(0,i) = 1, F(i,0) = 1
返回结果:F(m-1,n-1)
*/
public int SumOfPaths(int m, int n) {
int[][] pathNum = new int[m][n];
for (int i=0;i<n;i++){
pathNum[0][i]=1;
}
for (int i=0;i<m;i++){
pathNum[i][0]=1;
}
for (int i=1;i<m;i++){
for (int j=1;j<n;j++){
pathNum[i][j] = pathNum[i][j-1] + pathNum[i-1][j];
}
}
return pathNum[m-1][n-1];
}
7. 有一棵无穷大的满二叉树,其结点按根结点一层一层地从左往右依次编号,根结点编号为1。现在有两个结点a,b。请设计一个算法,求出a和b点的最近公共祖先的编号。
参考代码:
//循环比较a和b,取较大的值/2得到其父亲结点,直到a=b即找到公共祖先.
import java.util.*;
public class LCA {
public int getLCA(int a, int b) {
while (a != b){
if (a > b)
a /= 2;
else
b /= 2;
}
return a;
}
}
8. 求一个byte数字对应的二进制数字中1的最大连续数,例如3的二进制为00000011,最大连续2个1。
输入描述:输入一个byte数字。
输出描述:输出转成二进制之后连续1的个数。
示例:
输入:3
输出:2
参考代码:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while(scanner.hasNext()){
int n = scanner.nextInt();
int count = 0;
int modcount = 0;
while(n != 0){
if ((n&1) == 1){
count++;
modcount = Math.max(count,modcount);
}else {
count=0;
}
n >>= 1; //让n左移一位继续判断
}
System.out.println(modcount);
}
}
}
9. 有两个32位整数n和m,请编写算法将m的二进制数位插入到n的二进制的第j到第i位,其中二进制的位数从低位数到高位且以0开始。
给定两个数int n和int m,同时给定int j和int i,意义如题所述,请返回操作后的数,保证n的第j到第i位均为零,且m的二进制位数小于等于i-j+1。
示例:
输入:1024,19,2,6
输出:1100
参考代码:
class BinInsert {
public int binInsert(int n, int m, int j, int i) {
// write code here
m <<= j; //把m左移j位
return n | m;
}
}
10. 任意一个偶数(大于2)都可以由2个素数组成,组成偶数的2个素数有很多种情况,本题目要求输出组成指定偶数的两个素数差值最小的素数对。
输入描述:输入一个偶数。
输出描述:输出两个素数。
示例:
输入:20
输出:7 13
参考代码:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while(scanner.hasNext()){
int n = scanner.nextInt();
int half = n/2;
for (int i=half;i>0;i--){
if (isPrime(i) && isPrime(n-i)){
System.out.println(n-i +" "+ i);
break;
}
}
}
}
public static boolean isPrime(int m){
for (int i=2;i*i<=m;i++){
if (m%i == 0){
return false;
}
}
return true;
}
}