蓝桥杯31天冲刺之二 [java]

文章目录

  • 排他平方数
  • 买不到的数目
  • 回文日期
  • 约瑟夫环

排他平方数

题目链接:https://www.lanqiao.cn/problems/712/learning/

这里有一个地方需要注意的是,使用long的时候要显示转换一下,或者写成222L这种形式,不然像19行那里会直接变成负数,具体原因与数字在计算机中的编码格式有关,有兴趣可自己了解一下

然后在这种题里面应该掌握的就是哈希集合去查找元素,使用普通列表查找元素的时间复杂度为O(n),但是对于哈希集合来说只有O(1),哈希表也是类似的

package daily;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 题目链接:https://www.lanqiao.cn/problems/712/learning/
 * 
 * @author Jia
 *
 */
public class day3_9_1 {
	public static void main(String[] args) {
		List<Integer> list = new ArrayList<>();
		// 因为要求每个数位上位置不能相同,所以直接省略前面和后面有相同数字的
		for (int i = 123456; i <= 987654; i++) {
			long mult = (long) i * i;
			// 这里判断是不是6位数都不相同,如果有相同的则哈希集合大小小于6
			Set<Integer> set = getSet(i);
			if (set.size() != 6) {
				continue;
			}

			// 这里判断是否有重复的数字,也是用哈希集合判断,对于查找老说O(1)时间非常好用
			while (mult > 0) {
				if (set.contains((int) (mult % 10))) {
					break;
				}
				mult = mult / 10;
			}
			if (mult == 0) {
				list.add(i);
			}
		}
		// System.out.println(list); 这里可以看总共有几个数字,由于提交时不能有多余输出就注释了
		for (int i = 0; i < list.size(); i++) {
			if (list.get(i) != 203879) {
				System.out.println(list.get(i));
			}
		}
	}

	/**
	 * 将传入的数组按位转换为一个哈希集合
	 * 
	 * @param i
	 * @return
	 */
	private static Set<Integer> getSet(int i) {
		Set<Integer> set = new HashSet<>();
		while (i > 0) {
			set.add(i % 10);
			i /= 10;
		}
		return set;
	}
}

买不到的数目

题目链接:https://www.lanqiao.cn/problems/213/learning/

这个题是一个典型的动态规划问题,如果这个数减去n或者减去m可以拼出来,那么这个数一定可以拼出来,用这个作为dp的递推式就可以很容易做出来,dp一般用得都是数组去记录情况的,这里我是看到题目中输入的范围在0-1000,如果用数组会浪费部分空间,所以直接使用哈希集合了,如果使用数组的话需要判断的是arr[i]==true

package daily;

import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

public class day3_9_2 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int m = sc.nextInt();
		int n = sc.nextInt();
		sc.close();

		Set<Integer> set = new HashSet<>();
		int max = 0;
		set.add(m);
		set.add(n);
		for (int i = 0; i < m * n; i++) {
			// 判断减去m或n是否可以拼出来,如果可以的话则这个数肯定可以拼出来
			if (set.contains(i - n) || set.contains(i - m)) {
				set.add(i);
			} else {
				max = i;
			}
		}
		System.out.println(max);
	}
}

回文日期

题目链接:https://www.lanqiao.cn/problems/498/learning/

在这个题里面,如果自己处理合法的数字的话需要考虑每个月有多少天,直接使用日历类去得到遍历的对象,然后自己格式化一下就可以得到合法的数字了

另外,我觉得如果直接判断是不是回文数或者是不是ABAB型的有点难,于是我就采用构造它的回文数与它的ABAB型回文数,然后判断是不是与原数字相同,这种比直接判断应该能简单一点

package daily;

import java.util.Calendar;
import java.util.Scanner;

public class day3_9_3 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int N = sc.nextInt();
		sc.close();
		int normal = 0;
		int ababType = 0;
		// 设置初始日期,按照格式取数字就了
		Calendar c = Calendar.getInstance();
		c.clear();
		c.set(Calendar.YEAR, N / 10000);
		c.set(Calendar.MONTH, (N % 10000 / 100) - 1);
		c.set(Calendar.DAY_OF_MONTH, N % 100);

		for (int i = N + 1; i < 99999999; i++) {
			// 每次循环加一天
			c.add(Calendar.DAY_OF_MONTH, 1);
			// 得到这一天的格式化日期
			int date = c.get(Calendar.YEAR) * 10000 + (c.get(Calendar.MONTH) + 1) * 100 + c.get(Calendar.DAY_OF_MONTH);

			// 在这里判断是不是回文数
			int rev = reverse(date);
			// 如果翻转后的数字与原数字相同,则就是回文数
			if (rev == date) {
				if (isABAB(date)) {
					// 这里表示当前数字是ABAB型的
					ababType = date;
					break;
				}
				if (normal == 0) {
					normal = date;
				}
			}
		}
		if (normal == 0) {
			System.out.println(ababType);
			System.out.println(ababType);
		} else {
			System.out.println(normal);
			System.out.println(ababType);
		}

	}

	/**
	 * 这里根据ABAB型回文数构造数字,判断与原数字是否相同
	 * 
	 * @param i
	 * @return
	 */
	private static boolean isABAB(int i) {
		int A = i % 10;
		int B = (i % 100) / 10;
		int[] nums = { A, B, A, B, B, A, B, A };
		int sum = 0;
		for (int j = 0; j < nums.length; j++) {
			sum = sum * 10 + nums[j];
		}
		return sum == i;
	}

	/**
	 * 这里翻转原数字,判断与数字是否相同
	 * 
	 * @param i
	 * @return
	 */
	private static int reverse(int i) {
		int ret = 0;
		while (i > 0) {
			ret = ret * 10 + i % 10;
			i = i / 10;
		}
		return ret;
	}
}

约瑟夫环

题目链接: https://www.lanqiao.cn/problems/231/learning/

这个题我没做出来,正常做法直接超时了,挺懵逼的,然后在网上找到了递推的方法,反正我没看懂…后面再琢磨琢磨

package daily;

import java.util.Scanner;

public class day3_9_4_ac {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int k = sc.nextInt();
		sc.close();

		int res = 0;
		for (int i = 2; i <= n; i++) {
			res = (res + k) % i;
		}
		System.out.print(res + 1);
	}
}

下面是我超时的做法,希望大佬可以说说怎么改进

package daily;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class day3_9_4 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int k = sc.nextInt();
		sc.close();

		int count = n;// 当前剩余人数
		List<Integer> indexArray = new ArrayList<>();
		for (int i = 0; i < n; i++) {
			indexArray.add(i);
		}

		int index = 0;
		while (count > 1) {
			// 当前指向的人是第一个,所以只需要向后面数k-1个
			index = (index + k - 1) % indexArray.size();
			indexArray.remove(index);

			count--;
		}
		// 输出结果
		System.out.println(indexArray.get(0) + 1);
	}
}

你可能感兴趣的:(蓝桥杯,蓝桥杯,java,算法)