编程题练习2

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;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值