1、计算糖果
A,B,C三个人是好朋友,每个人手里都有一些糖果,我们不知道他们每个人手上具体有多少个糖果,但是我们知道以下的信息:
A - B, B - C, A + B, B + C. 这四个数值.每个字母代表每个人所拥有的糖果数.
现在需要通过这四个数值计算出每个人手里有多少个糖果,即A,B,C。这里保证最多只有一组整数A,B,C满足所有题设条件。
输入:输入为一行,一共4个整数,分别为A - B,B - C,A + B,B + C,用空格隔开。 范围均在-30到30之间(闭区间)。
输出:输出为一行,如果存在满足的整数A,B,C则按顺序输出A,B,C,用空格隔开,行末无空格。 如果不存在这样的整数A,B,C,则输出No
//需要注意的是:输入时整数,输出也需要时整数,如果说输出不是整数,那就是没有解,应该输出no
//而java在做除法的时候,除数和被除数都是int,结果也就是int,就会导致无法确定这个解到底是不是整数,因此需要使用精度类型
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextInt()) {
int a = scanner.nextInt();
int b = scanner.nextInt();
int c = scanner.nextInt();
int d = scanner.nextInt();
//根据题目中的公式先表达出每人手中的糖果
float A=(a+c)/2f;
float B=(c-a)/2f;
float C=(d-b)/2f;
if((A-((a+c)/2))!=0){
System.out.print("No");
return ;
}
if((B-((c-a)/2)!=0)||(B!=((b+c)/2))){
System.out.print("No");
return ;
}
if((C-((d-b)/2))!=0){
System.out.print("No");
return ;
}
System.out.print((int)A+" "+(int)B+" "+(int)C);
}
}
2、n个数中出现次数大于等于n/2的数
输入n个整数,输出出现次数大于等于数组长度一半的数。
输入:每个测试输入包含 n个空格分割的n个整数,n不超过100,其中有一个整数出现次数大于等于n/2。
输出:输出出现次数大于等于n/2的数。
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Map<String,Integer> map = new HashMap<>();
String[] nums = new String[1000];
while (scanner.hasNext()) {
String str = scanner.nextLine();
nums = str.split(" ");
for(String i : nums) {
Integer value = map.get(i);
if(value == null) {
map.put(i,1);
}else {
map.put(i,value+1);
}
}
for(HashMap.Entry<String,Integer> entry : map.entrySet()) {
if(entry.getValue() >= nums.length / 2) {
System.out.println(entry.getKey());
}
}
}
}
3、不要二
二货小易有一个W*H的网格盒子,网格的行编号为0H-1,网格的列编号为0W-1。每个格子至多可以放一块蛋糕,任意两块蛋糕的欧几里得距离不能等于2。
小易想知道最多可以放多少块蛋糕在网格盒子里。
输入描述:每组数组包含网格长宽W,H,用空格分割.(1 ≤ W、H ≤ 1000)
输出描述:输出一个最多可以放的蛋糕数
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int col = in.nextInt();
int row = in.nextInt();
int[][] grid = new int[row][col];
//把所有可以放蛋糕的数组内容都设为1
for(int i = 0; i < row; i++){
if(i % 4 == 0 || i % 4 == 1){
for(int j = 0; j < col; j++){
if(j % 4 == 0 || j % 4 == 1){
grid[i][j] = 1;
}
}
}
else {
for(int j = 0; j < col; j++){
if(j % 4 == 2 || j % 4 == 3){
grid[i][j] = 1;
}
}
}
}
int count = 0;
for(int x = 0; x < row; x++){
for(int y = 0; y < col; y++){
if(grid[x][y] == 1){
count++;
}
}
}
System.out.println(count);
}
4、求最小公倍数
正整数A和正整数B 的最小公倍数是指 能被A和B整除的最小的正整数值,设计一个算法,求输入A和B的最小公倍数。
最小公倍数=(a*b) / 最大公约数
最大公约数:
- a/b,令r为所得余数(0≤r<b) 若r=0,算法结束,a即为答案
- 互换:置 a←b,b←r,并返回第一步
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int a =scanner.nextInt();
int b = scanner.nextInt();
System.out.println(lcm(a,b));
}
//最小公倍数 = (a*b)/最大公约数
private static int lcm(int a, int b) {
return (a * b) / gcd(a,b);
}
//求最大公约数
private static int gcd(int a, int b) {
if(b == 0) {
return a;
}
return gcd(b,a % b);
}
5、删数
有一个数组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]进行计算。
输出描述:
一行输出最后一个被删掉的数的原始下标位置。
解题思路:可以将输入的数直接放在List中,题目中要求每隔两个数字就删除掉一个,从0号下标开始算起,2号下标就应该删除掉。使用(i+2)%size,来找到需要删除的下标
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
int n = scanner.nextInt();
if(n > 1000) {
n = 999;
}
List<Integer> list = new ArrayList<>();
for (int i = 0; i < n; i++) {
list.add(i);
}
int i = 0;
while (list.size() > 1) {
i = (i + 2) % list.size();
list.remove(i);
}
System.out.println(list.get(0));
}
}
6、n个数中最小的k个
输入描述:每个测试输入包含空格分割的n+1个整数,最后一个整数为k值,n不超过100。
输出描述:输出n个整数里最小的k个数。升序输出
(1)直接使用Arrays.sort()方法
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
String line = scanner.nextLine();
String[] arr = line.split(" ");
int[] arr1 = new int[arr.length-1];
for (int i = 0; i < arr.length-1; i++) {
arr1[i] = Integer.parseInt(arr[i]);
}
Arrays.sort(arr1);
int n = Integer.parseInt(arr[arr.length-1]);
for (int i = 0; i < n; i++) {
System.out.print(arr1[i] + " ");
}
}
}
(2)使用快速排序
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String str = sc.nextLine();
String[] a = str.split(" ");
int[] num = new int[a.length-1];
for (int i = 0; i < a.length-1; i++) {
num[i] = Integer.parseInt(a[i]);
}
int k = Integer.parseInt(a[a.length-1]);//a中的最后一个元素
int start = 0;
int end = num.length-1;
int index = qSort(num,start,end);
while (index != k) {
if(index > k) {
end = index - 1;
index = qSort(num,start,end);
}else {
start = index + 1;
index = qSort(num,start,end);
}
}
Arrays.sort(num,0,k);
for (int i = 0; i < k; i++) {
System.out.print(num[i] + " ");
}
}
}
private static int qSort(int[] num, int start, int end) {
int dig = num[start];//基准值
while (start < end) {
while (start < end && num[end] >= dig) {
end--;
}
num[start] = num[end];
while (start < end && num[start] < dig) {
start++;
}
num[end] = num[start];
}
num[start] = dig;
return start;
}
7、末尾0的个数
输入一个正整数n,求n!(即阶乘)末尾有多少个0
输入:输入为一行,n(1 ≤ n ≤ 1000)
输出:输出一个整数
(1)直接使用%10的办法来计算,但是这个方法如果阶乘数字很大就会导致越界。
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int sum = 0;
while (scanner.hasNext()) {
double n = scanner.nextInt();
for (double i = n-1; i > 0; i--) {
n = n * i;
}
while (n % 10 == 0) {
sum++;
n = n/10;
}
System.out.println(sum);
}
}
(2)这里可以想象最后阶乘的数字,任何一个数字都可以由小于或等于自己的数字分解而成,而阶乘最后求得的数字是一个特殊的分解。因此末尾为0的个数实际就是2*5的个数,2的个数明显是很多的,因此问题就转化成求5的个数。但是5的倍数中也有5的这个因数,需要特殊处理。
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int res = 0;
for (int i = n; i >= 5; i--) {
int tmp = i;
while (tmp % 5 == 0) {
res++;
//处理5的倍数的情况
tmp = tmp / 5;
}
}
System.out.println(res);
}
8、数字颠倒
输入一个整数,将这个整数以字符串的形式逆序输出程序不考虑负数的情况,若数字含有0,则逆序形式也含有0,如输入为100,则输出为001
输入:输入一个int整数
输出:将整个整数逆序输出
(1)StringBuilder中reverse()方法
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
String str = n +"";
StringBuilder sb = new StringBuilder(str);
sb.reverse();
System.out.println(sb.toString());
}
(2)%10/10
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
if(n == 0) {
System.out.println(0);
}
while (n != 0) {
int t = n % 10;
n = n / 10;
System.out.print(t);
}
}
9、Fibonacci数列
Fibonacci数列是这样定义的:
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数
(1)直接将1000000个斐波那契数存入到数组中,查看输入的n在哪个区间范围,直接求最小的步数。
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int[] fiboncci = new int[1000000];
fiboncci[0] = 0;
fiboncci[1] = 1;
for (int i = 2; i < fiboncci.length; i++) {
fiboncci[i] = fiboncci[i-1] + fiboncci[i-2];
}
int n = sc.nextInt();
int left = 0;
int right = 0;
for (int i = 0; i < fiboncci.length; i++) {
if(n == fiboncci[i]) {
System.out.println(0);
return;
}
if(n < fiboncci[i] && n > fiboncci[i-1]) {
right = fiboncci[i] - n;
left = n - fiboncci[i-1];
if(right < left) {
System.out.println(right);
return;
}else {
System.out.println(left);
return;
}
}
}
}
(2)斐波那契数列的规律是A(n)=A(n-1)+A(n-2),这个题目不需要我们知道整个斐波那契数列的数值,只需要比较n和前后两个数字的大小,所以我们只需要用a b c来代替A(n) A(n-1) A(n-2),如果某一项大于等于n,就停止迭代,最后计算n的值介于最后两个数字之间的距离,找出最小的即可。
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = 0;
int a = 0,b = 1, c = 1;
if(sc.hasNext()) {
n = sc.nextInt();
}
while (c < n) {
a = b;
b = c;
c = a+b;
}
int dis1 = n - b;
int dis2 = c - n;
System.out.println(dis1<dis2?dis1:dis2);
}
10、 机器人走方格
有一个X*Y的网格,一个机器人只能走格点且只能向右或向下走,要从左上角走到右下角。请设计一个算法,计算机器人有多少种走法。
给定两个正整数int x,int y,请返回机器人的走法数目。保证x+y小于等于12。
题目中要求机器人只能向右或者向下走,如果向下走,就变成了计算(X-1)*Y网格的走法有多少。如果向右走,就变成了计算X * (Y-1)网格的走法有多少。当网格只有一行或者一列的时候,就只有一种方法
public int countWays(int x, int y) {
if(x == 1 || y == 1) {
return 1;
}
return countWays(x-1,y) + countWays(x,y-1);
}