Java学习记录2


一、日期问题

遇到计算XX年X月X日到YY年Y月Y日的问题,可以通过Calendar类和Date类去解决问题,代码如下
package lianxi;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
//计算日期间有多少天、或者用excel表计算更方便
public class 日期问题 {
    public static void main(String[] args) throws ParseException {
        String day1="1921-7-23";
        String day2="2020-7-1";
        SimpleDateFormat format1=new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat format2=new SimpleDateFormat("yyyy-MM-dd");
        Date date1=format1.parse(day1);
        Date date2=format2.parse(day2);
        Calendar calendar1=Calendar.getInstance();
        Calendar calendar2=Calendar.getInstance();
        calendar1.setTime(date1);
        calendar2.setTime(date2);
        long time1=calendar1.getTimeInMillis();
        long time2=calendar2.getTimeInMillis();
        long sum=(time2-time1)/(1000*60*60*24);
        System.out.println(sum);
    }
}

首先设定开始和结尾日期的字符串
然后申请两个SimpleDateFormat的格式变量,然后定义新的Date 通过调用format.parse(day)的方法,将字符串放入format内,之后通过calendar申请日历,并且用settime设置时间,最后通过time2-time1的方式再除了10006060*24可以获得间隔多少天。
更加便捷的方法是通过excel进行操作,如下:
在这里插入图片描述

二、迷宫问题

首先是创建box类,定义x和y坐标

static class box{
        int x;
        int y;
    }

其次定义判定方法ff和check

public static boolean ff(box[] bb,int n,int m)
    {   int len=bb.length;
        for (int i = 0; i <len; i++) {
            if (bb[i].x==n&&bb[i].y==m)
            {
                return true;
            }
        }
        return false;
    }
 public static void check(box[] bb)
    {   int a[][]={{1,0},{-1,0},{0,1},{0,-1}};//4,2
        int len=bb.length;
        int n=0,m=0;
        int b[][]={{1,1},{-1,-1},{-1,1},{1,-1}};
        int[] sum = new int[5];
        for (int i = 0; i < len; i++) {
            int x=bb[i].x;
            int y=bb[i].y;
            int flag=0;
            for (int j = 0; j < 4; j++) {
                n=x+a[j][0];
                m=y+a[j][1];
                if (ff(bb,n,m))
                {
                    flag++;
                }
            }
            if (flag==4)
            {   int temp=0;
                for (int j = 0; j < 4; j++) {
                    n=x+b[j][0];
                    m=y+b[j][1];
                    if (ff(bb,n,m))
                    {
                        temp++;
                    }
                }
                sum[temp]++;
            }
        }
        for (int i = 0; i < sum.length; i++) {
            System.out.println(sum[i]);
        }
    }

剩下的就是主函数main的正常输入输出
值得一提的是除了Scanner方法以外,还可以使用BufferedReader方法,在刷题的时候发现庞大的数据使用Scanner的话所需的时间是非常大。

public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        String str= bufferedReader.readLine();
        int n=Integer.valueOf(str);
        box[] bb = new box[n];
        for (int i = 0; i < n; i++) {
            bb[i]=new box();
            str=bufferedReader.readLine();
            String s[]=str.trim().split(" ");
            bb[i].x=Integer.valueOf(s[0]);
            bb[i].y=Integer.valueOf(s[1]);
        }
        check(bb);
    }

唯一要注意的是好像BufferedReader每次只能读取一行,所以需要对读取的字符串进行split的操作

三、稀疏向量CSP

这个解法我借阅了CSDN的大神,第一次输入正常录入数据,第二组则是边检查边录入,可以剩下不少时间,虽然所用的时间也不短,但相比我之前的方法可以达到满分

package lianxi;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;
//稀疏向量
public class ccf04 {
    public static void main(String[] args) throws IOException {
        //BufferedReader读取快
        BufferedReader scanner = new BufferedReader(new InputStreamReader(System.in));
        String str=scanner.readLine();
        String s[]=str.trim().split(" ");
        int n=  Integer.valueOf(s[0]);
        int a = Integer.valueOf(s[1]);
        int b = Integer.valueOf(s[2]);
        HashMap<Integer, Integer> arr = new HashMap<>();
        for (int i = 0; i <a; i++) {
            str=scanner.readLine();
            String sa[]=str.trim().split(" ");
            arr.put(Integer.valueOf(sa[0]),Integer.valueOf(sa[1]));
        }
        long res=0;
        int index=0;
        int value=0;
        for (int i = 0; i < b; i++) {
            str=scanner.readLine();
            String sb[]=str.trim().split(" ");
            index=Integer.valueOf(sb[0]);
            value=Integer.valueOf(sb[1]);
            if (value!=0&&arr.containsKey(index))
            {
                res+=value*arr.get(index);
            }
        }
        System.out.println(res);
    }
}

在这里插入图片描述

四、线性分类器CSP

这道题整体上还是蛮简单的,初次尝试我想用的是边录入边检查放入数组内,希望可以节省运行时间,最后发现对数据的判定很奇怪;参考网上的答案后,建议是用更暴力的方法即可

package lianxi;
import java.util.ArrayList;
import java.util.Scanner;
//线性分类器
class box{
    int x;
    int y;
    String type;
}
public class ccf03 {
    public static void check(int x0,int x1,int x2,box b[],int a[],int n){
        int len=b.length;
        boolean flag=true;
        for (int i = 0; i <len-1; i++) {
            if (b[i].type.equals(b[i + 1].type)) {
                if ((x0 + b[i].x * x1 + b[i].y * x2) * (x0 + b[i + 1].x * x1 + b[i + 1].y * x2) < 0) {
                    flag=false;
                    break;
                }
            } else {
                if ((x0 + b[i].x * x1 + b[i].y * x2) * (x0 + b[i + 1].x * x1 + b[i + 1].y * x2) > 0) {
                    flag=false;
                    break;
                }
            }
        }
        if (flag) {
            a[n]=1;
        }
            else {
            a[n]=0;
        }
        }
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n=in.nextInt();//点个数
        int m=in.nextInt();//查询个数
        box[] boxes = new box[n];
        int[] a = new int[m];
        for (int i = 0; i < n; i++) {
            boxes[i]=new box();
            boxes[i].x=in.nextInt();
            boxes[i].y=in.nextInt();
            boxes[i].type=in.next();
        }
        for (int i = 0; i < m; i++) {
            int x0=in.nextInt();
            int x1=in.nextInt();
            int x2=in.nextInt();
            check(x0,x1,x2,boxes,a,i);
        }
        for (int i = 0; i < m; i++) {
            if (a[i]==1)
                System.out.println("Yes");
            else
                System.out.println("No");
        }
    }
}

五、数字三角形蓝桥杯

本题解题思路是利用递归,求取最大值,难度不大,编写代码偷懒了一些,只用了一组数据,没用输入的情况

package lianxi;

import java.util.Arrays;
import java.util.Scanner;

//数字三角形
public class lqb05 {
    static int n=5;
    static int max=0;
    static int map1[][]={{7},{3,8},{8,1,0},{2,7,4,4},{4,5,2,6,5}};
    public static void main(String[] args) {
        dfs(0,0,0);
        System.out.println(max);
    }
    public static void dfs(int i,int j,int sum){
       if (i==n-1)
       {
           sum+=map1[i][j];
           if (sum>max)
           max=sum;
           return;
       }
       dfs(i+1,j,sum+map1[i][j]);
       dfs(i+1,j+1,sum+map1[i][j]);
       return;
    }
}

之前还遇到过这个题的升级版,是左拐和右拐的次数不能超过1,即需要对路线进行判定,基本上就是在dfs的方法添加两个变量,然后退出的语句再加个判定即可

六 、01背包蓝桥杯

01背包也是老经典的问题了,也是通过递归的解决,比上一题要多考虑的是return的情景,负载重要小于0和可选物品达到要求,以及选择拿和不拿的情况

package lianxi;
//01背包
public class lqb04 {
    static int w[]={2,1,3,2};
    static int v[]={3,2,4,2};
    static int W=5;
    static int n=4;
    public static void main(String[] args) {
        int ww=W;
        int ans=dfs(0,ww);
        System.out.println(ans);
    }
    public static int dfs(int i,int ww)
    {
        if (ww<=0)  return 0;
        if (i==n)   return 0;
        int v2=dfs(i+1,ww); //不选择当前物品
        if (ww>=w[i])
        {
            int v1=v[i]+dfs(i+1,ww-w[i]);
            return Math.max(v1,v2);
        }else
            return v2;
    }
}

七、素数环蓝桥杯

这题我应该也是参考CSDN的大神的答案,解决方案也是递归,但是对判断又提高了要求
isp函数是对素数的判断
check函数是对已经形成的环进行判定,如数组内已有该元素或判断结果不为素数,则返回false,这里递归使用了回溯的方法,对数进行了全排列,我觉得这道题思路是很明确的,但是实现的函数有一些复杂0 0

package lianxi;
import java.util.Scanner;
//素数环
public class lqb02 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n=in.nextInt(); //输入个数
        int a[]=new int[n];
        a[0]=1; //初始化a0为1
        dfs(a,n,1);
    }
    public static void dfs(int a[],int n,int cur)
    {
        if (cur==n&&isp(a[0]+a[n-1]))
        {
            for (int i = 0; i < a.length; i++) {
                System.out.print(a[i]+" ");
            }
            System.out.println();
            return;
        }
        for (int i = 2; i <=n; i++) {
            if (check(a,i,cur))
            {
                a[cur]=i;
                dfs(a,n,cur+1);
                a[cur]=0;
            }
        }
    }
    public static boolean check(int a[],int i,int cur)
    {
        for (int e:a)
        {
            if (e==i||!isp(a[cur-1]+i))
                return false;
        }
        return true;
    }
    public static boolean isp(int k)
    {
        for (int i = 2; i<k; i++) {
            if (k%i==0)
                return false;
        }
        return true;
    }
}

八、翻硬币蓝桥杯

翻硬币这道题,是对初始状态和末状态的硬币进行判定,若不同则进行翻硬币操作,每次都翻动相邻的两枚硬币,感觉就是指针的移动,最后判断一下即可,思路很清晰>.<

package lianxi;

import java.util.Scanner;
//翻硬币
public class lqb03 {
    static int res=0;
    public static void ff(char c1[],char c2[])
    {
        for (int i = 0; i <c1.length; i++) {
            if (c1[i]!=c2[i])
            {
                if (c1[i]=='*') {
                    c1[i] = 'o';
                    if (c1[i+1]=='*')
                        c1[i+1]='o';
                    else
                        c1[i+1]='*';
                }
                else {
                    c1[i] = '*';
                    if (c1[i+1]=='*')
                        c1[i+1]='o';
                    else
                        c1[i+1]='*';
                }
                res++;
            }
        }
    }
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String str1=in.nextLine();//first
        String str2=in.nextLine();//end
        char c1[]=str1.toCharArray();
        char c2[]=str2.toCharArray();
        ff(c1,c2);
        System.out.println(res);
    }
}

九、放学CSP

这道题我起初想用递归去解决,发现判定的难度非常大,参阅大神的答案发现用累加的方式可能更好,思路更清晰一些,判定的难度也不大,基本上就是加减法,可惜没想出来这个方法
初步的判断是k==0时,tiem直接加t即可
第二步是对time<t的情况进行判定(k=1,2,3已分)
红灯就加剩余的时间t,绿灯直接return,黄灯则需要用t加上红灯的最大时间r;
第三步则是细分time>t的情况
定义temp时间,当k=1初始是红灯情况下,temp=红灯最大时间r+已有时间sum-剩余时间t再对total时间取余,如果temp小于红灯最大时间r,说明经过已有时间sum,还处于红灯的情况,那么就用红灯时间r-temp就是等待时间了,如果是黄灯情况,则用total时间-temp时间,则是等待黄灯的时间,再加上红灯时间,就是该情况所需要的等待时间,绿灯则通过,当k=2/3的情况下,除了对temp的初始化有差别,其余都一致,当k=2黄灯时,则用total+已有时间sum-剩余时间t再对total时间取余,当k=3绿灯时,则用红灯时间r+绿灯时间+已有时间sum-剩余时间t再对total时间取余

package lianxi;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class ccf放学 {
    static int r;
    static int y;
    static int g;
    static int time;
    static int total;
    public static void ff(int k,int t)
    {
        if (k==0)
            time+=t;
        else
        {
            if (k==1)
            {
                if (time<t)
                {
                    time=t;
                }
                else
                {
                    int temp = (r + time - t) % total;
                            if (temp < r) //红灯
                        {
                            temp = r - temp;
                            time += temp;
                        }
                            else if (temp <= r + g)//绿灯
                        {
                            return ;
                        }
                            else //黄灯
                        {
                            temp = total - temp;
                            temp += r;
                            time += temp;
                        }
                }
            }
            else if (k==2)
            {
                if (time<t)
                {
                    time=t+r;
                }
                else
                {
                    int temp=(total+time-t)%total;
                    if (temp<r)//red
                    {
                        temp=r-temp;
                        time+=temp;
                    }
                    else if (temp<=r+g)
                    {
                        return;
                    }
                    else {
                        //yellow
                        temp=total-temp;
                        temp+=r;
                        time+=temp;
                    }
                }
            }
            else
            {
                if (time<t)
                {
                    return;
                }
                else
                {
                    int temp=(r+g+time-t)%total;
                    if (temp<r)//red
                    {
                        temp=r-temp;
                        time+=temp;
                    }
                    else if (temp<=r+g)
                    {
                        return;
                    }
                    else {
                        //yellow
                        temp=total-temp;
                        temp+=r;
                        time+=temp;
                    }
                }
            }

        }

    }
    public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        String s1[]= bufferedReader.readLine().trim().split(" ");
        r=Integer.valueOf(s1[0]);
        y=Integer.valueOf(s1[1]);
        g=Integer.valueOf(s1[2]);
        total=r+y+g;
        String s2=bufferedReader.readLine();
        int n=Integer.valueOf(s2);
        for (int i = 0; i < n; i++) {
            String s3[]= bufferedReader.readLine().trim().split(" ");
            ff(Integer.valueOf(s3[0]),Integer.valueOf(s3[1]));
        }
        System.out.println(time);
    }
}

十、完全二叉树的权值蓝桥杯

题目梗概如下
在这里插入图片描述
这道题我还是用偷懒的方法,并没有按照常规的树去建立和计算,直接使用数据和层次的关系解决
因为本题输入是按层次遍历的顺序输入,然后建立方法,其变量有tree数组,层次k,和存放sum和的集合

package lianxi;

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

public class 二叉树权值 {
    static int n;
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        n=scanner.nextInt();
        int[] tree = new int[n+1];
        ArrayList<Integer> list = new ArrayList<>();
        for (int i = 1; i <n+1; i++) {
            tree[i]=scanner.nextInt();
        }
        ff(tree,0,list);
        int max=list.get(0);
        int temp=0;
        for (int i = 1; i < list.size(); i++) {
            if (list.get(i)>max)
            {
                max=list.get(i);
                temp=i;
            }
        }
        System.out.println(temp+1);
    }
    public static void ff(int tree[],int k,ArrayList<Integer> list)
    {
        int start=(int)Math.pow(2,k);
        if (start>n)
        {
            return;
        }
        int end=(int)Math.pow(2,k+1);
        if (end>n){
            end=n;
        }
        int sum=0;
        for (int i =start; i <end ; i++) {
            sum+=tree[i];
        }
        list.add(sum);
        ff(tree,k+1,list);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值