蓝桥杯-算法训练

区间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()方法,从而正确比对。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值