2013
1第一题世界末日
日历类的方便使用
Calendar calendar=Calendar.getInstance();
for(int year=1999;year<5000;year+=100){
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, 11);
calendar.set(calendar.DAY_OF_MONTH, 31);
if(calendar.get(calendar.DAY_OF_WEEK)==1){
System.out.print(Calendar.DAY_OF_WEEK);
break;
}
}
其他用法
a、add方法
public abstract void add(int field,int amount)
该方法的作用是在Calendar对象中的某个字段上增加或减少一定的数值,增加是amount的值为正,减少时amount的值为负。
例如在计算一下当前时间100天以后的日期,代码如下:
Calendar c3 = Calendar.getInstance();
c3.add(Calendar.DATE, 100);
int year1 = c3.get(Calendar.YEAR);
//月份
int month1 = c3.get(Calendar.MONTH) + 1;
b、after方法
public boolean after(Object when)
该方法的作用是判断当前日期对象是否在when对象的后面,如果在when对象的后面则返回true,否则返回false。例如:
Calendar c4 = Calendar.getInstance();
c4.set(2009, 10 - 1, 10);
Calendar c5 = Calendar.getInstance();
c5.set(2010, 10 - 1, 10);
boolean b = c5.after(c4);
第三题振兴中华
要求跳过的路线刚好构成“从我做起振兴中华”这句话。
请你帮助小明算一算他一共有多少种可能的跳跃路线呢?
搜索模板
public static int three(int i,int j){
if(i==3 || j==4)
return 1;//为什么是||,因为这个题只是为了计数,到了边界就只有一个方向了,所以不用一直走下去直接加1就行了
int t1=three(i+1,j);
int t2=three(i,j+1);
int w=t1+t2;
return w;
}
黄金连分数
BigInteger与BigDecimal的使用
https://blog.csdn.net/weixin_42265324/article/details/88726765
根据规律写出来发现是斐波纳挈
***你的任务是:写出精确到小数点后100位精度的黄金分割值。***注意这句话程序得到的100必须是稳定的,因此循环的量大一些检验检验
错误票据
你的任务是通过编程,找出断号的ID和重号的ID。
注意输入是不定长的数组,输入方式
//题目要求输入的是不定长的数组,因此输入的方法如下
Scanner snScanner=new Scanner(System.in);
ArrayList<Integer> list=new ArrayList<Integer>();
int n=snScanner.nextInt();
snScanner.nextLine();
int[][] ids=new int[n][];
for(int i=0;i<n;i++){
String lineString=snScanner.nextLine();
String[] splitStrings=lineString.split(" ");
for(int j=0;j<splitStrings.length;j++){
list.add(Integer.parseInt(splitStrings[j]));
}
}
还有就是Arraylist的使用(https://www.cnblogs.com/kungfupanda/p/7357142.html)
要注意,arraylist.get取出来不是int,要用equals
if(list.get(i).equals(list.get(i-1))){
c=list.get(i);
}
幸运数
首先从1开始写出自然数1,2,3,4,5,6,… 1 就是第一个幸运数。 我们从2这个数开始。把所有序号能被2整除的项删除,变为: 1
_ 3 _ 5 _ 7 _ 9 … 把它们缩紧,重新记序,为: 1 3 5 7 9 … 。这时,3为第2个幸运数,然后把所有能被3整除的序号位置的数删去。注意,是序号位置,不是那个数本身能否被3整除!! 删除的应该是5,11,
17, … 此时7为第3个幸运数,然后再删去序号位置能被7整除的(19,39,…)
这个题要注意的就是数组删除的部位可以记下这个模板,2014年也有类似的题
主要就是坑位p和i的变化
while(true){
int p=l+1;//数字向前挪动的坑位
for(int i=l+1;i<n/2;i++){
//要删除的数不做处理
if((i+1)%a[l]==0){
}
//不删除的数就是要挪动的
else {
a[p]=a[i];
p++;
}
}
l++;
//结束条件是幸运数大于N了
if(a[l]>=n) break;
}
带分数
全排列!全排列!全排列!全排列!全排列!全排列!全排列!
一般就在check中更改模板
//全排列一个数组
//确定某一个排列的第K位
public static void f9(int[] arr,int k){
if(k==9){ //排到数组最后一个元素就结束
if(check(arr)){
ans++;
}
}
//选定第K位
for(int i=k;i<arr.length;i++){
//将第i位与第K 位进行交换
int t=arr[i];
arr[i]=arr[k];
arr[k]=t;
//移交下一层
f9(arr,k+1);
//回溯,换回来
t=arr[i];
arr[i]=arr[k];
arr[k]=t;
}
}
2014
1,第三题猜字母
快速生成字母方式
char arr[]=new char[19];
for(int i=0;i<19;++i){
arr[i]=(char)('a'+i);
}
对于数组,所有偶数往前提,忽略奇数,一个数组元素往前移的模板
while(len!=1){
int k=0;
//把所有的偶数往前提,忽略奇数
for(int i=1;i<len;i+=2){
arr1[k++]=arr1[i];
}
len=k;
}
2 第六题
计算最大公约数模板
//计算两数的最大公约数
private static int gcd(int a,int b) {
if(b==0) return a;
return gcd(b, a%b);
}
扑克排序
还是全排列,不过全排列中数组有重复值,得到的结果肯定也有重复值
利用HashSet进行去重
static Set<String> set=new HashSet<String>();
public static void f7(char[] a,int k){
if(k==a.length){
String s=new String(a);
if(check(s)){
set.add(s);
}
}
for(int i=k;i<a.length;i++){
char t=a[k];
a[k]=a[i];
a[i]=t;
f7(a, k+1);
t=a[k];
a[k]=a[i];
a[i]=t;
}
}
地宫取宝
X 国王有一个地宫宝库。是 n x m 个格子的矩阵。每个格子放一件宝贝。每个宝贝贴着价值标签。
地宫的入口在左上角,出口在右下角。
小明被带到地宫的入口,国王要求他只能向右或向下行走。
走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。
当小明走到出口时,如果他手中的宝贝恰好是k件,则这些宝贝就可以送给小明。
请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这k件宝贝。
首先dfs搜索所有路径,计算个数
public static void fun9(int x,int y,int kh,int max1){
//看解析终止条件应该这样写
if(x==n||y==m){
return;
}
int cur=jz[x][y];
if(x==n-1&&y==m-1){//走到最后一个格子
if(kh==k||(kh==k-1)&&cur>max1){
count9++;
if(count9>1000000007){
count9%=1000000007;
}
}
}
//价值大的可以拿可以不拿
if(jz[x][y]>max1){
fun9(x, y+1, kh++, jz[x][y]);
fun9(x+1, y, kh++, jz[x][y]);
}
//考虑拿的情况
fun9(x, y+1, kh, max1);
fun9(x+1, y, kh, max1);
}
但是这样时间超了
修改记忆型搜索,不是动态规划
//记忆型深度搜索
static int[][][][] cache=new int[51][51][14][14];
public static long dfs(int x,int y,int kh,int max1){
//如果cache中有记录那就直接输出记录
if(cache[x][y][max1-1][kh]!=-1){
return cache[x][y][max1-1][kh];
}
if(x==n||y==m||kh>k){
return 0;
}
int cur=jz[x][y];
int ans=0;
if(x==n-1&&y==m-1){
if(kh==k||(kh==k-1&&cur>max1))return 1;
}
if(cur>max1){
ans+=dfs(x, y+1, kh++, cur);
ans+=dfs(x+1, y, kh++, cur);
}
ans+=dfs(x, y+1, kh, max1);
ans+=dfs(x+1, y, kh, max1);
cache[x][y][max1][kh]=ans%1000000007;
return ans%1000000007;
}
2015
2016
剪邮票
如何全排列二维矩阵以及连通性检查的方法
static boolean check1(int[] a){
//将a的这个排列映射到二维矩阵上面,全排列a就相当于排列这个二维矩阵了
int g[][]=new int[3][4];
for(int i=0;i<3;++i){
for(int j=0;j<4;++j){
if(a[i*4+j]==1) g[i][j]=1;
else {
g[i][j]=0;
}
}
}
//连通性检查,如果只有一个连通块cnt=1
int cnt=0;
for(int i=0;i<3;++i){
for(int j=0;j<4;++j){
if(g[i][j]==1){
dfs(g,i,j);
cnt++;
}
}
}
return cnt==1;
}
public static void dfs(int g[][],int i,int j){
g[i][j]=0;
if(i-1>=0&&g[i-1][j]==1)dfs(g, i-1, j);
if(i+1<=2&&g[i+1][j]==1)dfs(g, i+1, j);
if(j-1>=0&&g[i][j-1]==1)dfs(g, i-1, j);
if(i+1<=3&&g[i][j+1]==1)dfs(g, i-1, j);
}
注意再用set去重
取球博弈
两个人玩取球的游戏。 一共有N个球,每人轮流取球,每次可取集合{n1,n2,n3}中的任何一个数目。 如果无法继续取球,则游戏结束。
此时,持有奇数个球的一方获胜。 如果两人都是奇数,则为平局。假设双方都采用最聪明的取法, 第一个取球的人一定能赢吗? 试编程解决这个问题。
最聪明的做法就是试探各种结果后,只要有结果是赢那就是我赢,没有赢只有平那就是我平,都没有那就是我输
2018
最长字串
#先了解一下最长子序列,两个都是用动态规划解决的
https://blog.csdn.net/hrn1216/article/details/51534607