循环单词
如果一个单词通过循环右移获得的单词,我们称这些单词都为一种循环单词。 例如:picture 和 turepic 就是属于同一种循环单词。 现在给出n个单词,需要统计这个n个单词中有多少种循环单词。
输入描述:
输入包括n+1行:
第一行为单词个数n(1 ≤ n ≤ 50)
接下来的n行,每行一个单词word[i],长度length(1 ≤ length ≤ 50)。
由小写字母构成
输出描述:
输出循环单词的种数
示例1
输入
5
picture
turepic
icturep
word
ordw
输出
2
示例2
输入
4
goran
igor
domagoj
relja
输出
4
说明
并不是必须包含两个或两个以上的不同单词才算一种循环单词!
代码实现
package com.loopword;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/**
* @author wty
* @date 2022/11/23 0:19
*/
public class Exercise03 {
@Test
public void test() {
Scanner scanner = new Scanner(System.in);
int i = scanner.nextInt();
if (i <= 0 || i > 50) {
System.out.println("输入的数字n有误,n(1 ≤ n ≤ 50)");
return;
}
int num = getNum(i,scanner);
System.out.println(num);
}
public int getNum(int i,Scanner scanner) {
int count = 0;
// 构建一个集合
List<String> list = new ArrayList<>();
scanner = new Scanner(System.in);
for (int j = 0; j < i; j++) {
String next = scanner.next();
if (next.length() <= 0 || next.length() > 50) {
System.out.println("输入的字符串s长度有误,s长度(1 ≤ s ≤ 50)");
break;
}
if (!list.contains(next)) {
++count;
list.add(next);
for (int l = 0; l < next.length() - 1; l++) {
// 取出最后一个字符
String last = String.valueOf(next.charAt(next.length() - 1));
// 截取第一个字符开始到 倒数第二个字符
next = next.substring(0, next.length() - 1);
next = last + next;
list.add(next);
}
}
}
scanner.close();
return count;
}
}
组装三角形
牛牛手里有N根木棒,分别编号为1~N,现在他从N根里想取出三根木棒,使得三根木棒构成一个三角形,你能计算出牛牛有多少种取法吗?(考虑两种取法中使用的木棒编号有一个不一样就认为是不同的取法)。
输入描述
首先输入一个正整数N,接下来的一行共有N个正整数表示每个木棒的长度。
N ≤ 50, 木棒的长度 ≤ 10000.
输出描述
输出一个整数表示方法数。
示例1
输入
5
1 2 3 4 5
输出
3
代码示例
package com.tran;
import org.junit.Test;
import java.util.Scanner;
/**
* 组装三角形
*
* @author wty
* @date 2022/11/23 11:43
*/
public class Maketriangle {
@Test
public void test(){
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
if (N > 50 || N <= 0){
System.out.println("输入的N不符合规范,N ≤ 50");
return;
}
int array[] = new int[N];
for (int i = 0; i < N; i++) {
int length = scanner.nextInt();
if (length > 10000 || length <= 0){
System.out.println("输入的length不符合规范,木棒的长度 ≤ 10000");
return;
}
array[i] = length;
}
int num = mdTriangle(array);
System.out.println(num);
}
public int mdTriangle(int array[]){
int sum = 0;
int length = array.length;
// 定义三个指针 i,j,k
// i < array.length i[0,2]
for (int i = 0; i < length - 2; i++) {
// j < array.length - 1 j[1,3]
for (int j = i + 1; j < length - 1 ; j++) {
// k < array.length - 2 k[2,4]
for (int k = j+1; k < length ; k++) {
if ((array[i]!= array[j] && array[j] != array[k])
&& (array[i] + array[j] > array[k]
&& array[j] + array[k] > array[i]
&& array[k] + array[i] > array[j])){
++sum;
}
}
}
}
return sum;
}
}
操作序列
小易有一个长度为n的整数序列,a_1,…,a_n。然后考虑在一个空序列b上进行n次以下操作:
1、将a_i放入b序列的末尾
2、逆置b序列
小易需要你计算输出操作n次之后的b序列。
输入描述
输入包括两行,第一行包括一个整数n(2 ≤ n ≤ 2*10^5),即序列的长度。
第二行包括n个整数a_i(1 ≤ a_i ≤ 10^9),即序列a中的每个整数,以空格分割。
输出描述:
在一行中输出操作n次之后的b序列,以空格分割,行末无空格。
示例1
输入
4
1 2 3 4
输出
4 2 1 3
代码示例
package com.operationsequence;
import org.junit.Test;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Scanner;
import java.util.Stack;
/**
* @author wty
* @date 2022/11/23 14:51
*/
public class Exercise {
/**
* 初始思路:
* 其实是个找规律题, 每一次数序逆置是为了把 下标按奇数、偶数分开放在两侧。
* 因此可以设置两个数组分别存放奇数序列和偶数序列,最后计算n的奇偶性,
* n为奇数,先倒序输出奇数序列,然后,顺序输出偶数序列;否之,正好相反。
*/
@Test
public void test(){
// 偶数标志
boolean enenFlag = false;
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
if (n < 2 || n > 2*10e5){
System.out.println("输入的n不符合规则,n(2 ≤ n ≤ 2*10^5)");
return;
}
Stack<Integer> stack = new Stack<>();
ArrayList<Integer> list = new ArrayList<>();
if (n%2 == 0){
// 说明是偶数,那么偶数加入栈
enenFlag = true;
}
for (int i = 0; i < n; i++) {
int a_i = scanner.nextInt();
// if (a_i < 1 || a_i > 10e9){
// System.out.println("输入的a_i不符合规则,a_i(1 ≤ a_i ≤ 10^9)");
// }
// a_i是偶数
if (a_i %2 == 0){
if (enenFlag){
stack.push(a_i);
}else {
list.add(a_i);
}
}else {
// a_i是奇数
if (enenFlag){
list.add(a_i);
}else {
stack.push(a_i);
}
}
}
int length = stack.size();
// // stack进行冒泡排序把大的提到前面
// for (int i = 0; i < length - 1; i++) {
// for (int j = 0; j < length - i - 1; j++) {
// if (stack.get(j) < stack.get(j + 1)){
// int temp = stack.get(j);
// stack.set(j,stack.get(j + 1));
// stack.set(j + 1,temp);
// }
// }
// }
// 遍历
for (int i = 0; i < length; i++) {
System.out.print(stack.pop() + " ");
}
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i) + " ");
}
}
/**
* 改进思路:上面的方式虽然能做出来,但是测试用例只能通过一半
* 因为10*e9这么大的数字,用遍历和插入来说效率太慢,自然想到了链表的形式。
*
* 新建一个空链表,奇数往右边加,偶数往左边加,在输出时如果数组长度是偶数则正向输出反之倒序输出,
* 涉及到插入操作时概率快的当然选LinkedList了
*/
@Test
public void test2(){
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
if (n < 2 || n > 2*10e5){
System.out.println("输入的n不符合规则,n(2 ≤ n ≤ 2*10^5)");
return;
}
LinkedList<Integer> linkedList = new LinkedList<>();
for (int i = 0; i < n; i++) {
int a_i = scanner.nextInt();
if (a_i %2 == 0){
// 偶数往左边插入
linkedList.addFirst(a_i);
}else {
// 奇数往右边插入
linkedList.addLast(a_i);
}
}
// 遍历 N如果是偶数就正向遍历
int length = linkedList.size();
if (n%2 == 0){
for (int i = 0; i < length; i++) {
System.out.print(linkedList.get(i) + " ");
}
}else {
// N如果是奇数就反向遍历
for (int j = length - 1; j >= 0; j--) {
System.out.print(linkedList.get(j) + " ");
}
}
}
/**
* 只是由于要操作大量元素,虽然LinkedList比ArrayList快了很多,
* 但是在提交时还是超时,case通过50%。
*/
@Test
public void test3(){
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
if (n < 2 || n > 2*10e5){
System.out.println("输入的n不符合规则,n(2 ≤ n ≤ 2*10^5)");
return;
}
int []array = new int[n];
for (int i = 0; i < n; i++) {
int j = scanner.nextInt();
array[i] = j;
}
if(n%2 == 0){
int preIndex = 0;
int lastIndex = array.length - 1;
while (lastIndex %2 == 1 && lastIndex > -1){
if(lastIndex == 1) {
System.out.print(array[lastIndex]);
} else {
System.out.print(array[lastIndex] + " ");
}
lastIndex -= 2;
}
System.out.print(" ");
while (preIndex %2 == 0 && preIndex < array.length){
if(preIndex == array.length - 1 || preIndex == array.length - 2) {
System.out.print(array[preIndex]);
} else {
System.out.print(array[preIndex] + " ");
}
preIndex += 2;
}
}else{
int preIndex = 1,lastIndex = array.length - 1;
while (lastIndex %2 == 0 && lastIndex > -1){
if( lastIndex == 0) {
System.out.print(array[lastIndex]);
} else {
System.out.print(array[lastIndex] + " ");
}
lastIndex -= 2;
}
System.out.print(" ");
while (preIndex %2 == 1 && preIndex < array.length){
if(preIndex == array.length - 1 || preIndex == array.length - 2) {
System.out.print(array[preIndex]);
} else {
System.out.print(array[preIndex] + " ");
}
preIndex += 2;
}
}
}
@Test
public void test4() {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
if (n < 2 || n > 2 * 10e5) {
System.out.println("输入的n不符合规则,n(2 ≤ n ≤ 2*10^5)");
return;
}
ArrayList<Integer> list = new ArrayList<>();
int[] array = new int[n];
for (int i = 0; i < n; i++) {
array[i] = scanner.nextInt();
}
int min = (n % 2 == 1) ? n - 1 : n;
int index = 0;
while (index < min) {
if (index % 2 == 0) {
list.add(array[index++]);
} else {
// 用于在列表的指定位置插入指定元素,
// 并将当前处于该位置的元素及其后续元素的索引加 1。
list.add(0, array[index++]);
}
}
// N是偶数
if (min == n) {
for (int i = 0; i < list.size() - 1; i++) {
System.out.print(list.get(i) + " ");
}
System.out.println(list.get(list.size() - 1));
} else {
// N是奇数
list.add(array[array.length - 1]);
for (int i = list.size() - 1; i > 0; i--) {
System.out.print(list.get(i) + " ");
}
System.out.println(list.get(0));
}
}
@Test
public void test5(){
int a = 1;
System.out.println(a&1);
}
}
最长公共连续子串
牛牛有两个字符串(可能包含空格),牛牛想找出其中最长的公共连续子串,希望你能帮助他,并输出其长度。
输入描述
输入为两行字符串(可能包含空格),长度均小于等于50.
输出描述:
输出为一个整数,表示最长公共连续子串的长度。
示例1
输入
abcde
abgde
输出
2
代码示例
package com.longestcommonsubstring;
import org.junit.Test;
import java.util.Scanner;
/**
* @author wty
* @date 2022/11/23 17:54
*/
public class Exercise {
@Test
public void test(){
Scanner scanner = new Scanner(System.in);
String a = scanner.nextLine();
if (a.length() > 50){
System.out.println("输入的字符串长度不符合规范 长度均小于等于50");
}
String b = scanner.nextLine();
if (b.length() > 50){
System.out.println("输入的字符串长度不符合规范 长度均小于等于50");
}
// M是行
int M = b.length();
// N是列
int N = a.length();
int dp[][] = new int [M + 1][N + 1];
int max = 0;
// 初始化
for (int i = 0; i < N; i++) {
dp[0][i] = 0;
}
for (int j = 0; j < M; j++) {
dp[j][0] = 0;
}
for (int i = 1; i <= M; i++) {
for (int j = 1; j <= N; j++) {
if (a.charAt(j - 1) == b.charAt(i - 1)){
dp[i][j] = dp[i-1][j-1] + 1;
}else {
dp[i][j] = 0;
}
max = Math.max(max,dp[i][j]);
}
}
for (int i = 0; i < dp.length; i++) {
for (int j = 0; j < dp[i].length; j++) {
System.out.print(dp[i][j] + " ");
}
System.out.println();
}
System.out.println(max);
}
}
牛牛的数列
牛牛现在有一个n个数组成的数列,牛牛现在想取一个连续的子序列,并且这个子序列还必须得满足:最多只改变一个数,就可以使得这个连续的子序列是一个严格上升的子序列,牛牛想知道这个连续子序列最长的长度是多少。
输入描述
输入包括两行,第一行包括一个整数n(1 ≤ n ≤ 10^5),即数列的长度;
第二行n个整数a_i, 表示数列中的每个数(1 ≤ a_i ≤ 10^9),以空格分割。
输出描述
输出一个整数,表示最长的长度。
示例:
输入
6
7 2 3 1 5 6
输出
5
代码示例
package com.array;
import org.junit.Test;
import java.util.Scanner;
/**
* @author wty
* @date 2022/11/23 19:01
*/
@SuppressWarnings({"all"})
public class ArraysExercise {
@Test
public void test() {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
if (n <=0 || n > 10e9){
System.out.println("输入的整数有误,不满足n(1 ≤ n ≤ 10^5)");
return;
}
//分别为序列的首尾留一位,下面输入时起始赋值是a[1],结束是a[n],
// 所以a[0],a[n+1]会被默认初始化为0,即a[0]=0,a[n+1]=0
int[] a = new int[n + 2];
for (int i = 1; i <= n; i++) {
a[i] = scanner.nextInt();
}
//记录正序遍历找出递增的各个子序列长度
int[] left = new int[n + 1];
//记录逆序遍历找出递增的各个子序列长度
int[] right = new int[n + 2];
for (int i = 1; i <= n; i++) {//正向统计连续递增序列的长度(以第i位数结尾的递增子序列)
left[i] = a[i - 1] < a[i] ? left[i - 1] + 1 : 1;//i=1时,a[0]=0<1<=a[1](因为要求数据1 ≤ a_i ≤ 10^9),left[0]默认初始化为0,则left[1]=1
}
for (int j = n; j > 0; j--) {//逆向统计连续递增序列的长度(以第i位数开始的递增子序列)
right[j] = a[j] < a[j + 1] ? right[j + 1] + 1 : 1;//j=n时,a[n]>=1>a[n+1]=0,right[n+1]默认初始化为0,则right[n]=1
}
int result = 1;//最小的序列长度为1,所以把result初始化为1
for (int i = 1; i <= n; i++) {//加1是算上第i位数的长度.对于每一位置i有左侧到它最长的连续子序列长度left[i] 右侧有连续递增子序列长度right[i]
//此处是为了比较result、left[i-1]+1、right[i+1]+1的最大值,并赋给result
result = Math.max(result, left[i - 1] + 1);
result = Math.max(result, right[i + 1] + 1);
if (a[i + 1] - a[i - 1] >= 2) {//第i+1位与第i-1位至少相差2位,则可以修改第i位数,使第i-1、i、i+1也可以组成连续递增序列。
result = Math.max(result, left[i - 1] + right[i + 1] + 1);//查找两个和的最大值
}
}
System.out.println(result);
}
}