蓝桥刷题记录

16 篇文章 3 订阅
5 篇文章 1 订阅

一、《不同子串》

问题描述

一个字符串的非空子串是指字符串中长度至少为 1 的连续的一段字符组成的串。
例如,字符串aaab 有非空子串a,b,aa,ab,aaa,aab,aaab,一共 7个注意在计算时,只算本质不同的串的个数。
请问,字符串0100110001010001 有多少个不同的非空子串?

  • 输入:0100110001010001
  • 输出:100

算法分析

使用枚举获得所有子串,之后使用HashSet数据类型进行去重操作。

代码如下

package lanqiao;
import java.util.HashSet;
import java.util.Scanner;
public class DifferentSubstring {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		String line = scanner.nextLine();
		HashSet<String> hSet = new HashSet<String>();
		for(int i=0;i<line.length();i++) {
			for(int j=i;j<line.length();j++) {
				hSet.add(line.substring(i, j+1));
			}
		}
		System.out.println(hSet.size());
	}
}

二、《数列求值》

问题描述

给定数列 1,1,1,3,5,9,17,"·,从第 4 项开始,每项都是前 3 项的和。
求第 20190324 项的最后 4 位数字。

  • 输入:20190324
  • 输出:4659

算法分析

本题数列是基于斐波那契数列的变形,题目关键是在计算每一项数值的过程中需要对10000的进行取模(取余)运算(只取最后4位数字),防止数值过大溢出。

代码如下

package lanqiao;
import java.util.Scanner;
public class EvaluationOfSequence {
	public static void main(String[] args) {
		int a=1,b=1,c=1;
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt()-1;
		int temp;
		while(n>0) {
			//防止溢出
			temp = (a+b+c)%10000;
			a=b;
			b=c;
			c=temp;
			n--;
		}
		System.out.println(a);
	}
}

三、《数的分解》

问题描述

把 2019 分解成 3 个各不相同的正整数之和,并且要求每个正整数都不包含数字 2 和 4,一共有多少种不同的分解方法?
注意交换 3 个整数的顺序被视为同一种方法,例如 1000+1001+18 和1001+1000+18 被视为同一种。

  • 输入:2019
  • 输出:40785

算法分析

本题的关键在于设定a<b<c,防止解法重复,即让b从a+1开始枚举,同时c=2019-a-b需要大于b。

代码如下

package lanqiao;
import java.util.Scanner;
public class DecompositionOfNumber {
	private static boolean has2or4(int x) {
		String xString = String.valueOf(x);
		if (xString.indexOf("2")!=-1||xString.indexOf("4")!=-1) {
			return true;
		}
		return false;
	}
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt();
		int a,b,c,res=0;
		//让b从a+1开始
		for(a=1;a<2019;a++) {
			for(b=a+1;b<2019&&n-a-b>b;b++) {
				c=2019-a-b;
				if (!has2or4(a)&&!has2or4(b)&&!has2or4(c)) {
					res++;
				}
			}
		}
		System.out.println(res);
	}
}

2023.3.21


四、《单词分析》

问题描述

小蓝正在学习一门神奇的语言,这门语言中的单词都是由小写英文字母组 成,有些单词很长,远远超过正常英文单词的长度。小蓝学了很长时间也记不住一些单词,他准备不再完全记忆这些单词,而是根据单词中哪个字母出现得最多来分辨单词。

现在,请你帮助小蓝,给了一个单词后,帮助他找到出现最多的字母和这 个字母出现的次数。

  • 输入:longlonglongistoolong
  • 输出:
    • o
    • 6

算法分析

本题关键在于抓住字符类型(char)和整数类型(int)的关系,即:(int)‘a’=97.这样可以使用一个整型数组既保存字符(通过字符转整数类型后的对应索引保存),又记录出现次数。

代码如下

package lanqiao;
import java.util.Scanner;
public class WordAnalysis{
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String str = scanner.nextLine();
        //创建一个整型数组,用来保存26个字母的出现次数
        int[] a = new int[26];
        for (int i = 0; i < str.length(); i++) {
        	//遍历输入的字符串str,出现字符则增加次数
            a[str.charAt(i) - 'a']++;
        }
        //用来保存结果
        char ch='a';
        int max=0;
        for(int i=0;i<26;i++) {
            if(a[i]>max) {
                max=a[i];
                ch=(char)('a'+i);
            }
        }
        System.out.println(ch);
        System.out.println(max);
    }
}

五、《回文日期》

问题描述

2020 年春节期间,有一个特殊的日期引起了大家的注意:2020 年 2 月 2 日。因为如果将这个日期按 “yyyymmdd” 的格式写成一个 8 位数是 20200202,恰好是一个回文数。我们称这样的日期是回文日期。

有人表示 20200202 是 “千年一遇” 的特殊日子。对此小明很不认同,因为不到 2 年之后就是下一个回文日期:20211202 即 2021 年 12 月 2 日。

也有人表示 20200202 并不仅仅是一个回文日期,还是一个 ABABBABA 型的回文日期。对此小明也不认同,因为大约 100 年后就能遇到下一个 ABABBABA 型的回文日期:21211212 即 2121 年 12 月 12 日。算不上 “千年一遇”,顶多算 “千年两遇”。

给定一个 8 位数的日期,请你计算该日期之后下一个回文日期和下一个 ABABBABA 型的回文日期各是哪一天。

  • 输入:20200202
  • 输出:
    • 20211202
    • 21211212

算法分析

本题的关键在于最后输出的日期需要符合规范,因此不能单纯的使用累加法来进行日期的递增,这里使用了LocalDate类型中的plusDays()方法来实现日期规范递增。

代码如下

package lanqiao;

import java.time.LocalDate;
import java.util.Scanner;

public class PalindromeDate {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
        String str = in.nextLine();
        //从输入字符串中拆分出年月日
        int year = Integer.parseInt(str.substring(0, 4));
        int month = Integer.parseInt(str.substring(4, 6));
        int day = Integer.parseInt(str.substring(6, 8));
        LocalDate date = LocalDate.now();
        //将年月日赋给date对象
        date = date.withYear(year);
        date = date.withMonth(month);
        date = date.withDayOfMonth(day);
        //日期往后加一天,不需要考虑日期违规的问题
        date = date.plusDays(1);
        //用来保存结果
        String a = null;
        String b = null;
        boolean isFind = false;
        while (true) {
            String dateStr = date.toString().replace("-", "");
            if (isPalindromeDate(dateStr)) {
                if (!isFind) {
                    isFind = true;
                    a = dateStr;
                }
                if (isABABBABA(dateStr)) {
                    b = dateStr;
                    break;
                }
            }
            date = date.plusDays(1);
        }
        System.out.println(a);
        System.out.println(b);

        in.close();
    }
	//判断是否是回文日期
    static boolean isPalindromeDate(String date) {
        for (int i = 0; i < date.length() / 2; i++) {
            if (date.charAt(i) != date.charAt(date.length() - 1 - i)) {
                return false;
            }
        }
        return true;
    }
    //判断是否符合ABABBABA类型
    static boolean isABABBABA(String date) {
        char[] c = date.toCharArray();
        return c[0] == c[2] && c[2] == c[5] && c[5] == c[7] && c[1] == c[3] && c[3] == c[4] && c[4] == c[6];
    }
}

六、《超级质数》

问题描述

如果一个质数 P 的每位数字都是质数, 而且每两个相邻的数字组成的两位 数是质数, 而且每三位相邻的数字组成的三位数是质数, 依次类推, 如果每相 邻的 k 位数字组成的 k 位数都是质数, 则 P 称为超级质数。

如果把超级质数 P 看成一个字符串, 则这个超级质数的每个子串都是质数。

例如, 53 是一个超级质数。请问, 最大的超级质数是多少?

答案提交:
这是一道结果填空的题, 你只需要算出结果后提交即可。本题的结果为一 个整数, 在提交答案时只填写这个整数, 填写多余的内容将无法得分。

算法分析

由超级质数的规则,不难看出超级质数只能由2、3、5和7组成,两两组合剩下23,37,53,73然后再扩展到三位数,四位数质数开始已经没有符合规则的超级质数了,因此初步断定超级质数为2、3、5和7组成的三位数。
本题可以有以下两种思路:

  1. 枚举:从某一大数开始递减枚举并判断,直到找到符合规则的超级质数为止。
  2. 排列组合:通过对2、3、5和7排列组合分析出最大的超级质数。

枚举代码如下

package lanqiao;
import java.util.HashSet;
import java.util.Iterator;
public class SuperPrime {
	static boolean isSP(String a) {
		HashSet<String> hashSet = new HashSet<String>();
		for(int i=0;i<a.length();i++) {
			for(int j=i;j<a.length();j++) {
				hashSet.add(a.substring(i, j+1));
			}
		}
		Iterator<String> iterator = hashSet.iterator();
		//遍历所有不重复的子串
		while(iterator.hasNext()) {
			int temp = Integer.valueOf(iterator.next());
			if (temp==1) {
				return false;
			}
			int i = 2;
	        for (;i < temp;i++){
	            if (temp % i == 0){
	            	return false;
	            }
	        }
		}
		return true;
	}
	public static void main(String[] args) {
		int i=100000;
		while(!isSP(String.valueOf(i))) {
			i--;
		}
		System.out.println(i);
	}
}

排列组合思路如下

1.10以内的质数有2,3,5,7
2.根据超级质数的组成规则可以组成23,25,27,32,35,37,52,53,57,72,73,75这样的组合,
满足要求的有23,37,53,73 
3.根据这些组合可以组成237,373,573,737这样的数字组合,满足要求的只有373
4.根据组成规则已经不能在373的基础之上进行组合,即为最大超级质数 

七、《回文数——尺取法》

问题描述

给定一个长度为n的字符串s,判断是否回文。

  • 输入:32123
  • 输出:是回文数

算法分析

本题的关键在于使用尺取法,即将普通的双重循环,变成一个循环。
例如:将双重循环

for(int i=0;i<n;i++){               //i从前往后
    for(int j=n-1;j>= 0;j--){        //j从后往前
    
    }
}

变为

for(int  i=0,j=n-1;i<j;i++,j--){      //i从前往后,j从后往前

}

代码如下

package lanqiao;
import java.util.Scanner;
public class RulerMethod {
	public static void main(String[] args) {
				Scanner scanner = new Scanner(System.in);
				String l = scanner.nextLine();
				char[]line = l.toCharArray();
				int length = l.length();
				if(length==0||length==1) {
					System.out.println("是回文数");
				}
				int i,j;
				for(i=0,j=length-1;i<j;i++,j--) {
					if (line[i]!=line[j]) {
						System.out.println("不是回文数");
						break;
					}
				}
				if (i==j) {
					System.out.println("是回文数");
				}
	}
}

八、《上台阶》

问题描述

小蓝要上一个楼梯,共15级台阶。
小蓝每步可以上1级台阶,也可以上2级、3级或4级,再多就没办法一步走到了。
每级台阶上有一个数值,可能正也可能负,每次走到一级台阶上,小蓝的得分就加上这级台阶上的数值。
台阶上的数值依次为:1,2,1,1,1,1,5,5,4,-1,-1,-2,-3,-1,-9。
小蓝希望不超过6步走到台阶顶端,请问他得分的最大值是多少?
注意,小蓝开始站在地面上,地面没有分值。他最终要走到台阶顶端,所以最终一定会走到数值为-9的那级台阶,所以-9一定会加到得分里面。
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
【答案】5

算法分析

本题的关键是采用DFS深度优先搜索算法

代码如下

package lanqiao;

public class StepUp {
	//设定一个无穷大数INF
	private static int INF = 0x3f3f3f3f;
	//创建数组a保存每一级台阶的分数
	static int a[] = {0,1,2,1,1,1,1,5,5,4,-1,-1,-2,-3,-1,-9};
	public static void main(String[] args) {
		//从头开始深度优先搜索
		System.out.println(dfs(0,0));
	}
	static int dfs(int idx, int k) {//idx是台阶数,k是步数
		if(idx == 15){
			return a[15];//最后一阶-9
		}
		if(k == 6) {//6步
			return -INF;
		}
		//首先将ans设定为-INF,即负无穷大
		int ans = -INF;//得分
		for(int i=1;i <= 4 && idx + i <= 15;i++){
			ans = Math.max(ans, dfs(idx + i, k + 1));
		}
		return ans + a[idx];
	}
}

九、《0-1背包问题》

问题描述

有 N件物品和一个容量是 V 的背包。每件物品 只能使用一次。
第 i 件物品的体积是 v i,价值是 w i。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。
输入:
4 5
1 2
2 4
3 4
4 5
输出:
8

算法分析

本题的思路采用动态规划,关键在于弄清楚状态表(如下代码中的f即为状态表)。
f[i,j]:从前i个物品中选,且最大体积不超过j的选法的最大价值。
既然是从前i个物品当中选, 最后一步一定是决定 选不选第i个物品

  1. 选取第i个物品=====>f[i,j]= f[i - 1,j - v[i]]+ w[i]
  2. 不选取第i个物品=====>f[i,j]= f[i - 1,j]

代码如下

package backpack;
import java.util.Scanner;
public class DynamicProgramming {
	public static void main(String[] args) {
		int N = 1010;
		//物品体积
		int[] v = new int[N];
		//物品价值
		int[] w = new int[N];
		int[][] f = new int[N][N];
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt();
		int m = scanner.nextInt();
	    for (int i = 1; i <= n; i ++ ) {
	    	v[i] = scanner.nextInt();
	    	w[i] = scanner.nextInt();
	    }
	    //f[i][j]表示当背包容量为j时,现在有i件物品可以装情况下,最大的价值
	    for (int i = 1; i <= n; i ++ )
	        for (int j = 0; j <= m; j ++ )
	        {
	            f[i][j] = f[i-1][j]; // 由于j不一定大于等于当前第i个物品,因此必须先把不选第i个物品的情况赋值给f【i,j】
	            if (j >= v[i]) // 背包所能容纳的最大体积大于等于当前第i个物品,才有选择或者不选的权利
	            {
	                f[i][j] = Math.max(f[i-1][j] , f[i-1][j-v[i]] + w [i]); // 从两种情况选择大的
	            }       
	        }
	    System.out.println(f[n][m]);
	}
}

十、《股票买卖》

问题描述

给定一个长度为 N 的数组,数组中的第 i 个数字表示一个给定股票在第 i 天的价格。(1≤N≤105)
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

输入:
6
7 1 5 3 6 4
输出:
7

算法分析

本题的关键为贪心:只要相邻的两个时机,前面的价格小于后面的价格,我们就交易一次,肯定是后面的价格高了卖出才会有利润。

代码如下

package backpack;
import java.util.Scanner;
public class greedy {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int N = scanner.nextInt();
		int[]arr = new int[N];
		int res = 0;
		for(int i=0;i<N;i++) {
			arr[i] = scanner.nextInt();
		}
		for(int i=0;i<N-1;i++) {
			if(arr[i+1]>arr[i]) {
				res+=arr[i+1]-arr[i];
			}
		}
		System.out.println(res);
	}
}

十一、《递增三元组》

问题描述

给定三个整数数组
A = [A1, A2, … AN],
B = [B1, B2, … BN],
C = [C1, C2, … CN],
请你统计有多少个三元组(i, j, k) 满足:

  1. 1 <= i, j, k <= N
  2. Ai < Bj < Ck

【输入格式】
第一行包含一个整数N。
第二行包含N个整数A1, A2, … AN。
第三行包含N个整数B1, B2, … BN。
第四行包含N个整数C1, C2, … CN。
【输入样例】
3
1 1 1
2 2 2
3 3 3
【输出样例】
27

算法分析

本题采用的是暴力解法,即:遍历三个数组的全部元素,若找到符合要求的三元组则res++。

代码如下

package lanqiao;
import java.util.Arrays;
import java.util.Scanner;
public class IncreasingTriplet {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int N = scanner.nextInt();
		int[]arr = new int[N];
		int[]brr = new int[N];
		int[]crr = new int[N];
		for(int i=0;i<N;i++) {
			arr[i]=scanner.nextInt();
		}
		for(int i=0;i<N;i++) {
			brr[i]=scanner.nextInt();
		}
		for(int i=0;i<N;i++) {
			crr[i]=scanner.nextInt();
		}
		Arrays.sort(arr);
		Arrays.sort(brr);
		Arrays.sort(crr);
		int res = 0;
		for(int i=0;i<N;i++) {
			for(int j=0;j<N;j++) {
				if(arr[i]>=brr[j]) {
					continue;
				}
			for(int k=0;k<N;k++) {
				if(brr[j]>=crr[k]) {
					continue;
				}
				res++;
			}
			}
		}
		System.out.println(res);
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值