牛客 Java算法基础班入门算法

循环单词

如果一个单词通过循环右移获得的单词,我们称这些单词都为一种循环单词。 例如: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);
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

心向阳光的天域

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值