区间k大数查询
例题:资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个。
输入格式
第一行包含一个数n,表示序列长度。
第二行包含n个正整数,表示给定的序列。
第三个包含一个正整数m,表示询问个数。
接下来m行,每行三个数l,r,K,表示询问序列从左往右第l个数到第r个数中,从大往小第K大的数是哪个。序列元素从1开始标号。
输出格式
总共输出m行,每行一个数,表示询问的答案。
样例输入
5
1 2 3 4 5
2
1 5 2
2 3 2
样例输出
4
2
数据规模与约定
对于30%的数据,n,m<=100;
对于100%的数据,n,m<=1000;
保证k<=(r-l+1),序列中的数<=106。
解析:首先要理解题意,细读题目,要写一个方法去找到这个第K大的数
代码如下:针对本题意尚未完善
import java.util.Scanner;
public class Lanqiaobei3_1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int [] arr = new int[n];
for (int i =0;i<n;i++){
arr[i]=sc.nextInt();
}
int m = sc.nextInt();
int a [] [] =new int [m][3];
for (int i =0;i<m;i++){
for (int j = 0;j<3;j++){
a[i][j]=sc.nextInt();
}
}
for(int i =0;i<function(arr,a,m).length;i++){
System.out.println(function(arr,a,m)[i]);
}
}
public static int[] function(int arr[],int arr1[][],int m){
/*for (int i= 0;i<arr.length;i++){
for (int j= 1;j<arr.length;j++){
if (arr[j]<=arr[j-1]){
int temp=arr[j-1];
arr[j-1]=arr[j];
arr[j]=temp;
}
}
}*/
//int a [] = Arrays.copyOfRange(arr,arr1[0]-1,arr1[1]+1);
/*for (int i = 0;i<a.length;i++){
System.out.println(a[i]);
}*/
int b [] =new int[m];
for (int i= 0;i<b.length;i++){
b[i]=arr[arr1[i][1]-arr1[i][2]];
}
return b;
}
}
(由于为细心看题,误解了题意。 原题中:“接下来m行,每行三个数l,r,K,表示询问序列从左往右第l个数到第r个数中,从大往小第K大的数是哪个。序列元素从1开始标号。”我却是先对数组进行排序,在找区间内的值,原题中是先区间缩小再排序找第K大的数) 更新…
代码更新如下(修改了之前由于误解题的部分)
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int [] arr = new int[n];
for (int i =0;i<n;i++){
arr[i]=sc.nextInt();
}
int m = sc.nextInt();
int a [] [] =new int [m][3];
for (int i =0;i<m;i++){
for (int j = 0;j<3;j++){
a[i][j]=sc.nextInt();
}
}
for(int i =0;i<function(arr,a,m).length;i++){
System.out.println(function(arr,a,m)[i]);
}
}
public static int[] function(int arr[],int arr1[][],int m){
/*for (int i = 0;i<a.length;i++){
System.out.println(a[i]);
}*/
int b [] =new int[m];
for (int i= 0;i<b.length;i++){
int a [] = Arrays.copyOfRange(arr,arr1[i][0]-1,arr1[i][1]+0);
paixu(a);
b[i]=a[arr1[i][1]-arr1[i][0]+1-arr1[i][2]];
}
return b;
}
public static int [] paixu(int arr[]){
for (int i= 0;i<arr.length;i++){
for (int j= 1;j<arr.length;j++){
if (arr[j]<=arr[j-1]){
int temp=arr[j-1];
arr[j-1]=arr[j];
arr[j]=temp;
}
}
}
return arr;
}
}
这次虽然正确了,但是在测试系统上判断为超时,做一次教训记录下来吧。
正确满分代码代码如下:
import java.util.Arrays;
import java.util.Scanner;
public class Lanqiaobei3_1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int [] arr = new int[n];
for (int i =0;i<n;i++){
arr[i]=sc.nextInt();
}
int m = sc.nextInt();
int a [] [] =new int [m][3];
for (int i =0;i<m;i++){
for (int j = 0;j<3;j++){
a[i][j]=sc.nextInt();
}
}
function(arr,a,m);
}
public static void function(int arr[],int arr1[][],int m){
/*for (int i = 0;i<a.length;i++){
System.out.println(a[i]);
}*/
int b [] =new int[m];
for (int i= 0;i<b.length;i++){
int a [] = Arrays.copyOfRange(arr,arr1[i][0]-1,arr1[i][1]+0);
Arrays.sort(a);
b[i]=a[arr1[i][1]-arr1[i][0]+1-arr1[i][2]];
System.out.println(b[i]);
}
}
}
学到了:
1.题目有点障眼(因为题中给的初始序列:1,2,3,4,5 是一个已经排好序的序列,加上没有认真读题,就很容易误解题意,导致全部功夫都白费,因此要细度题意,写的时候也要思考并返回再看一遍题目。)
2.Arrays类中的sort方法、copyofRange方法
3.不要写太多for循环浪费时间,写完要检查一遍,去掉可去的for循环,减少编译时间(例如本题对数组进行排序用写的冒泡排序浪费了很多时间,改用sort方法,节约了很多时间,再检查可去的for循环,即可达到要求。)
最大最小公倍数
例题:资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
已知一个正整数N,问从1~N中任选出三个数,他们的最小公倍数最大可以为多少。
输入格式
输入一个正整数N。
输出格式
输出一个整数,表示你找到的最小公倍数。
样例输入
9
样例输出
504
数据规模与约定
1 <= N <= 106。
解析:最开始的思路是写出一个方法求出最小公倍数,再用循环找到最大的那个最小公倍数,但是最后运行时间过长,其中我还以为N范围是1到106,以后应该注意复制粘贴造成的失误,最后无奈在网上查到其他方法,直接找最大值求解。
代码:
import java.util.Scanner;
public class Lanqiaobei3_2 {
public static void main(String[] args) {
//三个数不一定连续,三个数为不同的三个数
Scanner sc =new Scanner(System.in);
int n= sc.nextInt();
//int arr[]= new int[Combination1(n,3)];
//for (int i=0;i<arr.length;i++) {
int v = 0;
for (int a = 1; a <= n; a++) {
for (int b = 1; b <= n; b++) {
for (int c = 1; c <= n; c++) {
if (a != b && a != c && b != c) {
v=littlenumber(a, b, c);
}
}
}
}
//}
/*for (int i=0;i<arr.length;i++) {
System.out.println(arr[i]);
}*/
System.out.println(v);
}
//此方法必须改进,也就只能改这个方法了
public static int littlenumber(int a,int b,int c){
int i=a*b*c;
int r =-1;
for ( ;i>0;i--){
if (i%a==0&&i%b==0&&i%c==0){
r=i;
}
}
return r;
}
public static int Combination1(int n, int k) {
int a=1,b=1;
if(k>n/2) {
k=n-k;
}
for(int i=1;i<=k;i++) {
a*=(n+1-i);
b*=i;
}
return a/b;
}
}
总结:算法是以数学问题为基础的问题,遇到算法问题不要急着去写代码求结果,先试着把算法问题先当做数学问题演草,处理完问题过程后再开始写代码。
以下方法思路:
若把本题作为一个数学问题处理,寻找思路,那么我们可以把输入的N分为三大类进行分别处理,演草可知:为奇数则直接最大的三个数字相乘即可,为偶数要是直接以 n * (n - 1) * (n - 3)处理就草率了,没有分析到当N为3的倍数的偶数时的情况,例如N为12,
12 * 11 *10与12 *11 * 9 与 11 * 10 *9三个组合当然是(n - 1) * (n - 2) * (n - 3)最大,所以考虑问题时一定要全面。
最后把此题的数学方法处理过程转化为代码就OK了。
import java.util.Scanner;
public class Lanqiaobei3_2 {
public static void main(String[] args) {
//三个数不一定连续,三个数为不同的三个数
Scanner sc = new Scanner(System.in);
long n = sc.nextLong();
//int arr[]= new int[Combination1(n,3)];
//for (int i=0;i<arr.length;i++) {
/*int v = 0;
for (int a = 1; a <= n; a++) {
for (int b = 1; b <= n; b++) {
for (int c = 1; c <= n; c++) {
if (a != b && a != c && b != c) {
v=littlenumber(a, b, c);
}
}
}
}
//}
/*for (int i=0;i<arr.length;i++) {
System.out.println(arr[i]);
}*/
//System.out.println(v);
long x = 0;
if (n % 2 != 0) {//若n为奇数
x = n * (n - 1) * (n - 2);
} else if (n % 3 == 0) {//n为3的倍数的偶数
x = (n - 1) * (n - 2) * (n - 3);
} else {
x = n * (n - 1) * (n - 3);
}
System.out.println(x);
}
}
送分啦
资源限制
时间限制:1.0s 内存限制:512.0MB
问题描述
这题想得分吗?想,请输出“yes”;不想,请输出“no”。
输出格式
输出包括一行,为“yes”或“no”。
代码:
public class Main {
public static void main(String[] args) {
System.out.println("yes");
}
}
K好数
资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
如果一个自然数N的K进制表示中任意的相邻的两位都不是相邻的数字,那么我们就说这个数是K好数。求L位K进制数中K好数的数目。例如K = 4,L = 2的时候,所有K好数为11、13、20、22、30、31、33 共7个。由于这个数目很大,请你输出它对1000000007取模后的值。
输入格式
输入包含两个正整数,K和L。
输出格式
输出一个整数,表示答案对1000000007取模后的值。
样例输入
4 2
样例输出
7
数据规模与约定
对于30%的数据,KL <= 106;
对于50%的数据,K <= 16, L <= 10;
对于100%的数据,1 <= K,L <= 100。
解析:还不会,两天了,没啥思路,网上看不懂,慢慢学习吧。
大小写转换
例题:
资源限制
时间限制:1.0s 内存限制:512.0MB
问题描述
编写一个程序,输入一个字符串(长度不超过20),然后把这个字符串内的每一个字符进行大小写变换,即将大写字母变成小写,小写字母变成大写,然后把这个新的字符串输出。
输入格式:输入一个字符串,而且这个字符串当中只包含英文字母,不包含其他类型的字符,也没有空格。
输出格式:输出经过转换后的字符串。
输入输出样例
样例输入
AeDb
样例输出
aEdB
解析:此题主要考查对字符及字符串相关方法的了解
代码:
import java.util.Scanner;
public class Lanqiaobei3_84 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s1 = sc.nextLine();
char [] a = new char[s1.length()];
for (int i=0;i<s1.length();i++){
if (Character.isUpperCase(s1.charAt(i))){ //用此方法判断大小写
a[i]=Character.toLowerCase(s1.charAt(i)); //用此方法改变大小写
}else {
a[i]=Character.toUpperCase(s1.charAt(i));
}
}
String s2= String.valueOf(a);//用此方法将字符数组变为字符串
System.out.println(s2);
}
}
注意对这些方法的记忆(isUpperCase toUpperCase String.valueOf())
前缀表达式
资源限制
时间限制:1.0s 内存限制:512.0MB
问题描述
编写一个程序,以字符串方式输入一个前缀表达式,然后计算它的值。输入格式为:“运算符 对象1 对象2”,其中,运算符为“+”(加法)、“-”(减法)、“*”(乘法)或“/”(除法),运算对象为不超过10的整数,它们之间用一个空格隔开。要求:对于加、减、乘、除这四种运算,分别设计相应的函数来实现。
输入格式:输入只有一行,即一个前缀表达式字符串。
输出格式:输出相应的计算结果(如果是除法,直接采用c语言的“/”运算符,结果为整数)。
输入输出样例
样例输入
- 5 2
样例输出
7
解析:此题我的思路是另写一个类,在类中写好四个方法
代码:
import java.util.Scanner;
public class Lanqiaobei3_92 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
new Yunsuan(sc.next(), Integer.parseInt(sc.next()), Integer.parseInt(sc.next()));
}
}
class Yunsuan{
public String fuhao;
public int num1;
public int num2;
public Yunsuan(String fuhao,int num1,int num2){
this.fuhao=fuhao;
this.num1=num1;
this.num2=num2;
if (fuhao.equals("+")){
this.add(num1,num2);
}else if (fuhao.equals("-")){
this.subtra(num1,num2);
}else if (fuhao.equals("*")){
this.cheng(num1,num2);
}else if (fuhao.equals("/")){
this.chu(num1,num2);
}
}
public void add(int x,int y){
System.out.println(x + y);
}
public void subtra(int x,int y){
System.out.println(x - y);
}
public void cheng(int x,int y){
System.out.println(x * y);
}public void chu(int x,int y){
System.out.println(x / y);
}
}
中间碰到的问题:
1.要找空格后下一个字符,不用再去分割字符串,只需要用next方法即可,这个在之前学习过。
2.之间new了Yunsuan类后返回的是地址值,而后改进发现fuhao ==“+”,这样子进行比对是不行的,此过程是不断调试发现的,而后改进为equals方法比对。
Anagrams问题
资源限制
时间限制:1.0s 内存限制:512.0MB
问题描述
Anagrams指的是具有如下特性的两个单词:在这两个单词当中,每一个英文字母(不区分大小写)所出现的次数都是相同的。例如,“Unclear”和“Nuclear”、“Rimon”和“MinOR”都是Anagrams。编写一个程序,输入两个单词,然后判断一下,这两个单词是否是Anagrams。每一个单词的长度不会超过80个字符,而且是大小写无关的。
输入格式:输入有两行,分别为两个单词。
输出格式:输出只有一个字母Y或N,分别表示Yes和No。
输入输出样例
样例输入
Unclear
Nuclear
样例输出
Y
解析:
//思路:题目要求大小写不区分,那么将字母都变为大写或小写
将字符串转化为字符数组并进行排序,从而进行比较
代码:
import java.util.Arrays;
import java.util.Scanner;
public class Lanqiaobei3_91 {
public static void main(String[] args) {
//思路:题目要求大小写不区分,那么将字母都变为大写或小写
//将字符串转化为字符数组并进行排序,从而进行比较
Scanner sc = new Scanner(System.in);
String str = sc.next().toLowerCase();
char [] arr = str.toCharArray();
Arrays.sort(arr);
String str1 = sc.next().toLowerCase();
char [] arr1 = str1.toCharArray();
Arrays.sort(arr1);
if (Arrays.equals(arr,arr1)){
System.out.println("Y");
}else {
System.out.println("N");
}
}
}
总结:这次练习首先是想到了要先缕清思路,在编写过程。
过程中遇到的问题:
1.对字母进行排序,本没思路,在网上找到了思路。思路是主要是利用Arrays类的sort排序方法,所以要将字符串转化为数组再排序
2.排序后的比对问题:首先是想到将数组转化为字符串利用equals方法比对,调试后发现转化后的字符串是地址值,所以改变思路,直接比对数组,但是arr.equals(arr1)这样比对还是无法正确比对,之后在网上查到比对用Arrays.equals()方法,从而正确比对。