一个字符串的非空子串是指字符串中长度至少为 1 的连续的一段字符组成的串。
例如,字符串aaab 有非空子串a,b,aa,ab,aaa,aab,aaab,一共 7个注意在计算时,只算本质不同的串的个数。
请问,字符串0100110001010001 有多少个不同的非空子串?
使用枚举获得所有子串,之后使用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 位数字。
本题数列是基于斐波那契数列的变形,题目关键是在计算每一项数值的过程中需要对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 被视为同一种。
本题的关键在于设定a
代码如下
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
小蓝正在学习一门神奇的语言,这门语言中的单词都是由小写英文字母组 成,有些单词很长,远远超过正常英文单词的长度。小蓝学了很长时间也记不住一些单词,他准备不再完全记忆这些单词,而是根据单词中哪个字母出现得最多来分辨单词。
现在,请你帮助小蓝,给了一个单词后,帮助他找到出现最多的字母和这 个字母出现的次数。
本题关键在于抓住字符类型(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 型的回文日期各是哪一天。
本题的关键在于最后输出的日期需要符合规范,因此不能单纯的使用累加法来进行日期的递增,这里使用了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组成的三位数。
本题可以有以下两种思路:
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,判断是否回文。
本题的关键在于使用尺取法,即将普通的双重循环,变成一个循环。
例如:将双重循环
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];
}
}
有 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个物品
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) 满足:
【输入格式】
第一行包含一个整数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);
}
}