> 文章列表 > Java题目训练——字符串反转和公共子串计算

Java题目训练——字符串反转和公共子串计算

Java题目训练——字符串反转和公共子串计算

目录

一、字符串反转

二、公共子串计算


一、字符串反转

题目描述:

接受一个只包含小写字母的字符串,然后输出该字符串反转后的字符串。(字符串长度不超过1000)

输入描述:

输入一行,为一个只包含小写字母的字符串。

输出描述:

输出该字符串反转后的字符串。

示例

示例1

输入:abcd

输出:dcba

题目解析:

        本题是一道很经典的题目,有很多种方式,这里我选择新建一个StringBuilder的字符串sb,然后从后往前遍历初始字符串,利用StringBuilder的append方法,就元素按遍历顺序加入,最好返回sb字符串,实现字符串反转。

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);String s = scanner.nextLine();if(s.length() == 0){return;}System.out.println(res(s));}public static String res(String s){StringBuilder sb = new StringBuilder();for (int i = s.length() - 1; i >= 0; i--) {sb.append(s.charAt(i));}return sb.toString();}
}

二、公共子串计算

题目描述:

给定两个只包含小写字母的字符串,计算两个字符串的最大公共子串的长度。

注:子串的定义指一个字符串删掉其部分前缀和后缀(也可以不删)后形成的字符串。

数据范围:字符串长度:1<=s<=150

进阶:时间复杂度:O(n^{3}) ,空间复杂度:O(n)

输入描述:

输入两个只包含小写字母的字符串

输出描述:

输出一个整数,代表最大公共子串的长度

示例

示例1

输入:asdfas

           werasdfaswer

输出:6

题目解析: 

这道和求最长公共子串的思路基本一样,但是还是有细节问题不一样,有兴趣可以参考:

这里介绍三种思路:

1. 动态规划(推荐)

        (1). 创立状态数组arr = new int[s1.length() + 1][s2.length() + 1]。

        (2). 寻找状态方程:如果此时位置的字符相同(s1.charAt(i - 1) == s2.charAt(j - 1)),那么说明这时字符是重复的,直接等于上一个状态的结果再+1。

        (3). 设立初始态:默认为0即可,本题通过条件自动更新。

        由于题目要求返回最大公共子串的长度,所以要设立一个变量max存储最大长度,更新max,最后返回max即可。

2. 普通思路

        设置两层循环,外层循环控制子串的起始位置,内层循还向后遍历,新建一个StringBuilder的字符串sb(方便修改),内层循还向后遍历,将字符通过StringBuilder的append方法添加至sb,如果此时的字符串sb被字符串s2所包含,那么才能判断sb的长度(子串)是否大于保存的最大值max,遍历完所有子串的情况,最后返回即可。

        这里需要注意循环的条件和范围,范围都是对s1的限制。

3. 左右指针——可以看作普通思路的优化

        设置左指针left从s1的左端开始,设置右指针right从s1的右端开始,思路有点像常规思路,外循环控制左指针的位置,内循环只要left <= right,就判断此时截取的s1.substring(left, right)是否被s2包含,并且长度有没有超过之前记录的最长子串的长度max,如果没有超过或者不符合条件,rright--,继续遍历;只要超过,就是这种情况(left = i)的最大长度(因为right一直在--),直接退出内循环(继续遍历也符合s2包含的条件,但长度越来越短,此时已经找到最长子串,没有必要继续)。

       由于题目要求返回最大公共子串的长度,所以要设立一个变量max存储最大长度,更新max,最后返回max即可。

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);String s1 = scanner.nextLine();String s2 = scanner.nextLine();System.out.println(comLen(s1, s2));}//1. 动态规划public static int comLen(String s1, String s2){int[][] res = new int[s1.length() + 1][s2.length() + 1];res[1][1] = 0;int max = 0;for (int i = 1; i <= s1.length() ; i++) {for (int j = 1; j <= s2.length(); j++) {if(s1.charAt(i - 1) == s2.charAt(j - 1)){res[i][j] = res[i - 1][j - 1] + 1;if(max < res[i][j]){max = res[i][j];}}}}return max;}//2. 普通思路public static int comLen1(String s1, String s2){int max = 0;for (int i = 0; i < s1.length(); i++) {StringBuilder sb = new StringBuilder();for(int j = i; j < s1.length(); j++){if(s2.contains(sb.append(s1.charAt(j)))){if(sb.length() > max){max = sb.length();}}}}return max;}//3. 左右指针public static int comLen2(String s1, String s2){int max = 0;for (int i = 0; i < s1.length(); i++) {int left = i;int right = s1.length();while(left <= right){int t = s1.substring(left, right).length();if(s2.contains(s1.substring(left, right)) && max < t){max = t;break;}right--;}}return max;}
}

如有建议或想法,欢迎一起讨论学习~