第十二届蓝桥杯Java B组——前期知识汇总梳理

1、掌握基础结构的写法:

自定义数据类型的快排

解析:基本数据类型的快排使用:Arrays.sort()方法,譬如电影节这样的问题,程序需要对每部电影的结束时间进行从小到大进行排序。就需要自己在自定义类改写“compareTo()”方法

package summarizeMyWork;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

//此类结构常常出现在贪心算法中,接下来的程序是以“电影节”这个问题为原型展开的:
/*描述
大学生电影节在北大举办! 这天,在北大各地放了多部电影,给定每部电影的放映时间区间,区间重叠的电影不可能同时看(端点可以重合),问李雷最多可以看多少部电影。

输入
多组数据。每组数据开头是n(n<=100),表示共n场电影。
接下来n行,每行两个整数(0到1000之间),表示一场电影的放映区间
n=0则数据结束
输出
对每组数据输出最多能看几部电影
样例输入
8
3 4
0 7 
3 8 
15 19
15 20
10 15
8 18 
6 12 
0
样例输出
3
*/
public class 自定义数据类型的快排 {

	static class movie implements Comparable<movie>{//这里容易忘记写后面的“implements Comparable<movie>”!
		int start;
		int end;
		public movie(int s,int e) {
			this.start=s;
			this.end=e;
		}
		@Override
		public String toString() {
			return "电影开始时间:"+this.start+"电影结束时间:"+this.end;
		}
		@Override
		public int compareTo(movie next) {
			return this.end-next.end;//返回结果为负,即为升序
		}
	}
	public static void main(String[] args) {
		movie[] m=new movie[10];
		m[0]=new movie(2, 9);
		m[1]=new movie(21, 29);
		m[2]=new movie(2, 93);
		m[3]=new movie(5, 3);
		m[4]=new movie(2, 0);
		m[5]=new movie(0, 7);
		m[6]=new movie(2, 6);
		m[7]=new movie(44, 3);
		m[8]=new movie(47, 88);
		m[9]=new movie(3, 38);
		List<movie> list=new ArrayList<movie>(Arrays.asList(m));//对于List这个类,eclips会自动引包,指向awt,需要删掉改成util包!
		Collections.sort(list);
		//遍历
		for(movie e:list) {
			System.out.println(e.toString());
		}
		//排序结果重新赋给数组
		int c=0;
		for(movie e:list) {
			m[c++]=e;
		}
		//获取链表中的某个对象
		System.out.println("获取到的对象  "+list.get(6));
		
	}

}

自定义数据类型的优先队列

package summarizeMyWork;

import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;

//此类结构常常出现在贪心算法中,接下来的程序是以“畜栏保留问题”这个问题为原型展开的:
/*
 * 描述
农场有N头牛,每头牛会在一个特定的时间区间[A, B](包括A和B)在畜栏里挤奶,且一个畜栏里同时只能有一头牛在挤奶。现在农场主希望知道最少几个畜栏能满足上述要求,并要求给出每头牛被安排的方案。对于多种可行方案,主要输出一种即可。

输入
输入的第一行包含一个整数N(1 ≤ N ≤ 50, 000),表示有N牛头;接下来N行每行包含两个数,分别表示这头牛的挤奶时间[Ai, Bi](1 ≤ A≤ B ≤ 1, 000, 000)。
输出
输出的第一行包含一个整数,表示最少需要的畜栏数;接下来N行,第i+1行描述了第i头牛所被分配的畜栏编号(从1开始)。
样例输入
5
1 10
2 4
3 6
5 8
4 7
样例输出
4
1
2
3
2
4
*/
//分析:譬如畜栏保留这样的问题,程序需要设置一个优先队列,按照挤奶时间结束时间早晚存放畜栏。则需要写一个“ new Comparator<>”对象,用于优先队列
public class 自定义数据类型的优先队列 {

	static class corral {
		int code;
		int lasttime;
		public corral(int c,int l) {
			this.code=c;
			this.lasttime=l;
		}
		@Override
		public String toString() {
			return "畜栏编码"+this.code+"畜栏结束时间"+this.lasttime;
		}
	}
	static Comparator<corral> comparator=new Comparator<corral>() {
		public int compare(corral c1,corral c2) {
			return c1.lasttime-c2.lasttime;
		}
	};
	public static void main(String[] args) {
		corral[] c=new corral[5];
		c[0]=new corral(1, 9);
		c[1]=new corral(2, 29);
		c[2]=new corral(3, 96);
		c[3]=new corral(4, 21);
		c[4]=new corral(5, 1);
		Queue<corral> queue=new PriorityQueue<corral>(comparator);
		for(int i=0;i<5;i++) {
			queue.add(c[i]);//对于队列而言,只能通过add操作将数据存入队列,才会进行排序
		}
		//返回队首元素,基本上常用的就是代码里面使用到的这四个方法
		System.out.println(queue.peek());
		//与链表不同的是,队列必须采用以下方法进行遍历:
		System.out.println(queue.size());
		while(!queue.isEmpty()) {
			System.out.println(queue.poll());
		}
//		for(int i=0;i<queue.size();i++) {//,采用这个方法只打印了3个结果,是因为队列的size是动态在变化的
//			System.out.println(queue.poll());
//		}
		
	}

}

普通数据类型的优先队列

package summarizeMyWork;

import java.util.PriorityQueue;
import java.util.Queue;

public class 普通数据类型的优先队列 {

	public static void main(String[] args) {
	
		Queue<Integer> queue=new PriorityQueue<Integer>();
		queue.offer(1);
		queue.offer(0);
		queue.offer(-1);
		System.out.println(queue.element());//返回队首元素
		while(!queue.isEmpty()) {
			System.out.println(queue.poll());
		}
		

	}

}

归并排序

package summarizeMyWork;

public class 归并排序 {
	//存储归并排序所需的数据必须在全局变量之下
	static int[] array=new int[100];
	static int[] b=new int[100];
	public static void main(String[] args) {
	
		int c=2039;
		for(int i=0;i<100;i++) {
			array[i]=c--;
		}
		MergeSort(array,0,99);//与String.substring方法不同的是:归并排序传入的值应当是(start_index,end_index)
		for(int i=0;i<100;i++) {
			System.out.println(array[i]);
		}
	}
	static void MergeSort(int[] a,int s,int e) {
		if(s<e) {
			int mid=s+(e-s)/2;
			MergeSort(a, s, mid);
			MergeSort(a, mid+1, e);
			Judge(a,s,mid,e);
		}
	}
	static void Judge(int[] a,int s,int mid,int e) {
		int p1=s,p2=mid+1;
		int pb=0;
		while(p1<=mid&&p2<=e) {
			if(a[p1]>=a[p2]) {
				b[pb++]=a[p2++];
			}
			else {
				b[pb++]=a[p1++];
				//像排列的逆序数这样的问题,只是在这里加了一个ans=mid-p1+1;
			}
		}
		while(p1<=mid){//粗心大意,这些界限容易写错
			b[pb++]=a[p1++];
		}
		while(p2<=e) {
			b[pb++]=a[p2++];
		}
		for(int i=0;i<e-s+1;i++) {
			a[s+i]=b[i];
		}
	}

}

什么时候使用归并排序?

归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。
归并排序最优时间复杂度是O(nlog2n) ,最坏的时间复杂度是O(nlog2n) , 它是稳定性很好的一个排序算法。
在大多数情况下,快速排序的效率都要比归并排序高,那归并排序的优势是什么呢?在我们的快排中!我们的一切操作都是在原有 的列表之上进行操作的,并没有生成新的列表。但是我们的归并排序的时候,我们需要先切分,这时候我们切分之后会形成新的列表,然后是对新的列表进行操作的!这就是区别。在算法中往往不仅仅是对数组进行排序,归并排序运用分治的思想,譬如“排列的逆序数”这样的问题,需要用到分治解决问题时,归并排序就有了天然的优势。

归并排序+自定义数据类型+自定义排序的综合性问题(DNA序列)

题目是:
在这里插入图片描述


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

//3:DNA排序
//查看 提交 统计 提问
//总时间限制: 1000ms 内存限制: 65536kB
//描述
//现在有一些长度相等的DNA串(只由ACGT四个字母组成),请将它们按照逆序对的数量多少排序。
//逆序对指的是字符串A中的两个字符A[i]、A[j],具有i < j 且 A[i] > A[j] 的性质。如字符串”ATCG“中,T和C是一个逆序对,T和G是另一个逆序对,这个字符串的逆序对数为2。
//输入
//第1行:两个整数n和m,n(0<n<=50)表示字符串长度,m(0<m<=100)表示字符串数量
//第2至m+1行:每行是一个长度为n的字符串
//输出
//按逆序对数从少到多输出字符串,逆序对数一样多的字符串按照输入的顺序输出。
//样例输入
//10 6
//AACATGAAGG
//TTTTGGCCAA
//TTTGGCCAAA
//GATCAGATTT
//CCCGGGGGGA
//ATCGATGCAT
//样例输出
//CCCGGGGGGA
//AACATGAAGG
//GATCAGATTT
//ATCGATGCAT
//TTTTGGCCAA
//TTTGGCCAAA
/*
 * 这道题知识点是分治归并排序+自定义数据类型+自定义排序
 * 描述
现在有一些长度相等的DNA串(只由ACGT四个字母组成),请将它们按照逆序对的数量多少排序。
逆序对指的是字符串A中的两个字符A[i]、A[j],具有i < j 且 A[i] > A[j] 的性质。如字符串”ATCG“中,T和C是一个逆序对,T和G是另一个逆序对,这个字符串的逆序对数为2。
输入
第1行:两个整数n和m,n(0<n<=50)表示字符串长度,m(0<m<=100)表示字符串数量
第2至m+1行:每行是一个长度为n的字符串
输出
按逆序对数从少到多输出字符串,逆序对数一样多的字符串按照输入的顺序输出。*/
public class DNA排序的分治 {

	static numm[] num;
	static char[] b;
	static class numm implements Comparable<numm>{
		int code;
		int count;
		public numm(int c,int co) {
			this.code=c;
			this.count=co;
		}
		
		@Override
		public int compareTo(numm next) {
			return this.count-next.count;
		}
		@Override 
		public String toString () {
			return "编号"+code+"序列数"+count;
		}
	}
	public static void main(String[] args) {
		
		Scanner reader=new Scanner(System.in);
		int m=reader.nextInt();//认真读题!比如这道题就是先给你列,再给你行
		int n=reader.nextInt();
		String[] string=new String[n];
		char[] a=new char[m];
		b=new char[m];
		num=new numm[n];
		for(int i=0;i<n;i++) {
			string[i]=reader.next();
			num[i]=new numm(i,0);
			for(int j=0;j<m;j++)
				a[j]=string[i].charAt(j);
//			for(int j=0;j<m-1;j++) {
//				for(int k=j+1;k<m;k++) {
//					if(string[i].charAt(j)>string[i].charAt(k)) {
//						count++;
//						num[i].count=count;//注意必须在上面new 对象,在这里new就会出现多个。
//					}
//				}
//			}
			MergeSort(a,i,0,m-1);
//			System.out.println(num[i].count);
		}
		List<numm> nList=new ArrayList<numm>(Arrays.asList(num));
		Collections.sort(nList);
		for(numm e:nList) {
//			System.out.print(e.toString()+"  ");
			System.out.println(string[e.code]);
		}
		
	}
	static void MergeSort(char[] a,int i,int s,int e) {
		if(s<e) {
			int mid=s+(e-s)/2;
			MergeSort(a,i, s, mid);
			MergeSort(a,i, mid+1, e);
			Judge(a, i,s,mid, e);
		}
	}
	static void Judge(char[] a,int i,int s,int mid,int e) {
		int p1=s,p2=mid+1;//错过,写成p2=e
		int pb=0;
		while(p1<=mid&&p2<=e) {
			if(a[p1]>a[p2]) {
				num[i].count+=mid-p1+1;
				b[pb++]=a[p2++];
			}
			else {
				b[pb++]=a[p1++];
			}
		}
		while(p1<=mid)
			b[pb++]=a[p1++];
		while(p2<=e)
			b[pb++]=a[p2++];
		for(int k=0;k<e-s+1;k++) {
			a[s+k]=b[k];
		}
	}
}

HashMap

package summarizeMyWork;

import java.util.HashMap;

public class hashMap {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		HashMap<String,String> map=new HashMap<>();
		map.put("账号", "密码");
		String string1="cqust";
		System.out.println(map.containsKey(string1));
		System.out.println(map.get("账号"));
	}

}

二分查找

package summarizeMyWork;

public class 二分查找 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		int[] array=new int[100];
		for(int i=0;i<100;i++) {
			array[i]=i;
		}
		//数组是排序好了的。
		System.out.println(BinarySort(array,0,99));
		
	}
	static int BinarySort(int[] a,int s,int e) {
		int left=s,right=e,max=0;
		int mid=left+(right-left)/2;
		while(left<=right) {
			if(mid<87) {//查找小于87的最大的数,具体问题具体分析
				max=mid;
				left=mid+1;
			}
			else {
				right=mid-1;
			}
			mid=left+(right-left)/2;
		}
		return max;
	}

}

2、掌握基础知识:

基本数据类型的范围

int型(2 * 10^9)
long型(9 * 10^18)

递归什么时候越界

溢出的意思就是越界,操作系统会给每个进程分配一个最大上限的堆栈空间,操作系统分配给一个进程的栈空间是2M,堆空间在32位机器上是4G。
撇如“数字三角形”这样的问题,如果使用递归求解,算法的时间复杂度 是在2^100 左右。这样的程序不存在计算机可以在一个人的有生之年之内算出来。

中学基本知识——数学公式

0、a%1000007的含义是a/1000007的余数是多少。
1、欧几里得定理(也叫辗转相除法)gcd(a,b)=gcd(a,a%b);
像下面这道题如果还是暴力求解一定会出现越界的情况,如果使用数学公式就很简单gcd(f(2020),f(520))=f(gcd(2020,520));在这里插入图片描述

2、大整数取模:(这个如果想要掌握就需要反复记忆)
(a+b)%n=(a%n+b%n)%n;
(a-b)%n=((a%n-b%n)+n)%n;
(ab)%n=(a%b)(b%n)%n
对于一个大的只能用数组存储的数来说:
因为数字有个规律1234=((1*10+2)*10+3)*10+4
for(int i=0;i<a.lenght;i++){
long ans=(int )(ans 10+a[i]-‘0’)%n;
}
3、奇数,偶数,质数,合数,众数,平均
(1)奇数,又称单数, 整数中,能被2整除的数是偶数,不能被2整除的数是奇数,奇数的个位为1,3,5,7,9。
(2)偶数,整数中,能够被2整除的数,叫做偶数,正的偶数又称双数。偶数包括正偶数、负偶数和0
(3)质数,又称素数,有无限个。质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数。
(4)合数,是指自然数中除能被1和本数整除外,还能被其他的数整除的数。
(5)众数(Mode)众数是指一组数据中出现次数最多的那个数据,一组数据可以有多个众数,也可以没有众数。众数是统计学名词,在统计分布上具有明显集中趋势点的数值,代表数据的一般水平(众数可以不存在或多于一个)。
(6)平均数是指在一组数据中所有数据之和再除以数据的个数。平均数是表示一组数据集中趋势的量数,它是反映数据集中趋势的一项指标。
(7)方差计算公式:s^2 =(1/n)
[(x1-x0)^2 + (x2-x0)^2 +…+ (xn-x0)^2]
(8)极差计算公式:x=xmax-xmin
(9)标准差=方差的算术平方根
4、正三角、平行四边形、2个菱形、2个梯形、圆形、圆周长、2个弧长、2个扇形、圆柱圆锥侧面积和全面积公式
弧长:l = n(圆心角)× π(圆周率)× r(半径)/180=α(圆心角弧度数)× r(半径)
扇形面积:
在这里插入图片描述
圆锥侧面积:圆锥的侧面展开图是扇形,该扇形的半径是母线长L(注意,此处L是圆锥母线的长,不是弧长),扇形的弧长是圆锥底面圆的周长2πr,其中r是底面圆的半径。套用第二条扇形面积公式得
S圆锥侧=L(2πr)/2=πrL。
5、其他偶尔需要用到的就请各位道友务必自行百度。

字符串类型的灵活运用

String类型是Java组算法经常使用的数据类型,对于它的运用也非常得灵活,需要熟练掌握
StringBuilder 、BigInteger、BigDecimal、Integer等类的常用方法。

package summarizeMyWork;

public class 字符串API {

	public static void main(String[] args) {
		//1、将int转换成string类型
		String  s=String.valueOf(122*111);
		System.out.println(s);
		//2、判断字符串是不是以参数指定内容结束
		boolean s2=s.endsWith("00");
		//3、判断字符串是不是以参数指定内容开始
		boolean s3=s.startsWith("1");
		System.out.println(s2+" "+s3);
		//4、获取子串,常用于校验+隐藏,含头不含尾
		String s4=s.substring(0,3);
		System.out.println(s4);
		//5、!字符串!转换成Int型
		int s5=Integer.valueOf(s);
		//6、!字符!转换成Int型,也可以用于将字符串转换成整型
		int s6=Integer.parseInt(String.valueOf(s.charAt(4)));
		System.out.println(s5+" "+s6);
		//7、去除开头结尾空格和tab
		String s7=s.trim();
		//8、将字符串按照给定正则表达式的分割成子串
		String[] s8=s.split(" ");
		//9、统一转换大小写
		String s9=s.toLowerCase();
		String s10=s.toUpperCase();
		//10、将子一个字符串变为字符数组
		char[] c=s.toCharArray();
		//将字符数组变为字符串
		String s11=new String(c);
		//将部分字符串变为string
		String s12=new String(c,0,3);
		//将整型(整型数组)转成字符串
		String s13=" ";
		s13+=Integer.toString(c[0]);
		//11、按字典顺序比较两个字符串(区分大小写与不区分大小写)
		if(s9.compareTo(s10)>0)System.out.println("区分大小写");
		if(s9.compareToIgnoreCase(s10)==0)System.out.println("不区分大小写");
		//12、判断此字符串第一次/最后一次出现指定字符处的索引
		int s14=s.indexOf('1',0);
		int s15=s.lastIndexOf('1',0);
		//13、替换字符/字符串,不能用字符串替换字符,也不能用字符替换字符串
		String s16=s.replace('1', '9');
		System.out.println(s16);
		//14、对一个字符串进行修改
		StringBuilder s17=new StringBuilder();
		s17.append("zxcvbnm");
		s17.insert(3, "asdf");
		s17.setCharAt(0, 'Z');
		String s18=s17.toString();
		System.out.println(s18);
		//15、以二进制返回一个整数的字符串表示形式
		String  s19=Integer.toBinaryString(10);
		String s20=Integer.toHexString(10);
		String s21=Integer.toOctalString(10);
		
	}

}

掌握经典题型:

Balanced lineup

走马日

最长公共子序列

输出前k大的数

排列的逆序数

背包问题

  • 14
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值