344.反转字符串
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。
示例 1:
输入:["h","e","l","l","o"]
输出:["o","l","l","e","h"]
示例 2:
输入:["H","a","n","n","a","h"]
输出:["h","a","n","n","a","H"]
class Solution {
public void reverseString(char[] s) {
int i=0;
int j=s.length-1;
while(i<j){
char temp=s[i];//字符串是char
s[i]=s[j];
s[j]=temp;
i++;
j--;
}
}
}
541. 反转字符串II
给定一个字符串 s 和一个整数 k,从字符串开头算起, 每计数至 2k 个字符,就反转这 2k 个字符中的前 k 个字符。
如果剩余字符少于 k 个,则将剩余字符全部反转。
如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
示例:
输入: s = "abcdefg", k = 2
输出: "bacdfeg"
思路
其实在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。
class Solution {
public String reverseStr(String s, int k) {
char[] ch=s.toCharArray();//转换后更好处理
for(int i=0;i<ch.length;i+=2*k){//每次移动2k
int end=Math.min(i+k-1,ch.length-1);//没到取k,到了取最后一个
int start=i;//防止++的时候覆盖i
while(start<end){
char temp=ch[start];//char不是int
ch[start]=ch[end];
ch[end]=temp;
start++;
end--;
}
}
return new String(ch);//转换成string回去
}
}
替换数字
给定一个字符串 s,它包含小写字母和数字字符,请编写一个函数,将字符串中的字母字符保持不变,而将每个数字字符替换为number。
例如,对于输入字符串 "a1b2c3",函数应该将其转换为 "anumberbnumbercnumber"。
对于输入字符串 "a5b",函数应该将其转换为 "anumberb"
输入:一个字符串 s,s 仅包含小写字母和数字字符。
输出:打印一个新的字符串,其中每个数字字符都被替换为了number
样例输入:a1b2c3
样例输出:anumberbnumbercnumber
数据范围:1 <= s.length < 10000。
拓展
这里也给大家拓展一下字符串和数组有什么差别,
字符串是若干字符组成的有限序列,也可以理解为是一个字符数组,但是很多语言对字符串做了特殊的规定,接下来我来说一说C/C++中的字符串。
在C语言中,把一个字符串存入一个数组时,也把结束符 '\0'存入数组,并以此作为该字符串是否结束的标志。
例如这段代码:
char a[5] = "asd";
for (int i = 0; a[i] != '\0'; i++) {
}
在C++中,提供一个string类,string类会提供 size接口,可以用来判断string类字符串是否结束,就不用'\0'来判断是否结束。
例如这段代码:
string a = "asd";
for (int i = 0; i < a.size(); i++) {
}
那么vector< char > 和 string 又有什么区别呢?
其实在基本操作上没有区别,但是 string提供更多的字符串处理的相关接口,例如string 重载了+,而vector却没有。
所以想处理字符串,我们还是会定义一个string类型。
补充:java
在 Java 编程中,字符串和数组是基础但非常重要的数据结构。理解如何在两者之间转换以及对其进行操作是写出高效代码的关键。
字符串
创建字符串
字符串是不可变的对象,意味着一旦创建,其值不能被更改。以下是几种创建字符串的方式:
java
复制代码
String str1 = "Hello, World!";
String str2 = new String("Hello, World!"); // 不推荐,通常只需要使用字面值创建
char[] charArray = {'H', 'e', 'l', 'l', 'o'};
String str3 = new String(charArray);
常用方法
-
长度
java
复制代码
int length = str1.length(); // 获取字符串长度
-
字符访问
java
复制代码
char c = str1.charAt(0); // 获取字符串中指定位置的字符
-
字符串截取
java
复制代码
String substr = str1.substring(0, 5); // 获取子字符串
-
字符串比较
java
复制代码
boolean isEqual = str1.equals(str2); // 比较字符串内容是否相等 boolean isEqualIgnoreCase = str1.equalsIgnoreCase("hello, world!"); // 忽略大小写比较
-
字符串拼接
java
复制代码
String str4 = str1 + " How are you?"; // 使用 + 进行拼接 String str5 = str1.concat(" How are you?"); // 使用 concat() 方法进行拼接
-
字符串分割
java
复制代码
String[] parts = str1.split(", "); // 分割字符串
字符串转字符数组
java
复制代码
char[] charArray = str1.toCharArray(); // 将字符串转换为字符数组
数组
数组的创建与初始化
java
复制代码
int[] intArray = {1, 2, 3, 4, 5}; // 静态初始化
int[] anotherArray = new int[5]; // 动态初始化,长度为 5,默认值为 0
常用操作
-
数组长度
java
复制代码
int length = intArray.length; // 获取数组长度
-
访问和修改数组元素
java
复制代码
int element = intArray[0]; // 获取数组第一个元素 intArray[1] = 10; // 修改数组第二个元素的值
-
遍历数组
java
复制代码
for (int i = 0; i < intArray.length; i++) { System.out.println(intArray[i]); } // 使用增强 for 循环 for (int num : intArray) { System.out.println(num); }
-
数组排序
java
复制代码
Arrays.sort(intArray); // 对数组进行升序排序
-
数组转换为字符串
java
复制代码
String arrayStr = Arrays.toString(intArray); // 将数组转换为字符串表示,方便打印
字符数组和字符串之间的转换
字符数组转字符串
java
复制代码
char[] charArray = {'H', 'e', 'l', 'l', 'o'};
String str = new String(charArray); // 将字符数组转换为字符串
字符串转字符数组
java
复制代码
String str = "Hello";
char[] charArray = str.toCharArray(); // 将字符串转换为字符数组
示例:在字符串和字符数组之间转换并进行操作
下面是一个示例,展示了如何在字符串和字符数组之间转换并反转一个字符串:
java
复制代码
public class StringArrayExample {
public static void main(String[] args) {
String originalString = "Hello, World!";
System.out.println("Original String: " + originalString);
// 转换为字符数组
char[] charArray = originalString.toCharArray();
// 反转字符数组
reverseArray(charArray);
// 转换回字符串
String reversedString = new String(charArray);
System.out.println("Reversed String: " + reversedString);
}
// 反转字符数组的辅助方法
private static void reverseArray(char[] array) {
int left = 0;
int right = array.length - 1;
while (left < right) {
char temp = array[left];
array[left] = array[right];
array[right] = temp;
left++;
right--;
}
}
}
总结
在 Java 中,字符串和数组是两个基本的数据结构,理解如何使用它们能让你的代码更加高效和易于维护。字符串是不可变对象,用于表示文字数据。而数组是固定长度的结构,可以存储相同类型的数据。通过合适的方法,你可以在它们之间进行转换,并对数据进行各种操作。希望这个解释能帮助你更好地理解和应用 Java 中的字符串和数组。
*string字符串 转换成char array(字符数组)后更好处理
char[] ch=s.toCharArray();//转换后更好处理
可以用s[i],否则要用:
s.charAt(i)
java的字符串不能原地修改,必须复制成char array才行
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.next();
int len=s.length();
//处理长度
for(int i=0;i<s.length();i++){//这里不能用len做终止,已经在修改了
if(s.charAt(i)>='0' &&s.charAt(i)<='9'){
len+=5;//每个数字+5长度,其实java不需要额外申请空间
}
}
//新建长度len的数组,save pre length into ret
char[] ret=new char[len];
for(int i=0;i<s.length();i++){
ret[i]=s.charAt(i);
}
for(int i = s.length() - 1, j = len - 1; i >= 0; i--){
if (ret[i]>='0'&&ret[i]<='9'){
ret[j--] = 'r';
ret[j--] = 'e';
ret[j--] = 'b';
ret[j--] = 'm';
ret[j--] = 'u';
ret[j--] = 'n';
}
else{
ret[j--]=ret[i];
}
}
System.out.println(ret);
}
}
151.翻转字符串里的单词
给定一个字符串,逐个翻转字符串中的每个单词。
示例 1:
输入: "the sky is blue"
输出: "blue is sky the"
示例 2:
输入: " hello world! "
输出: "world! hello"
解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
示例 3:
输入: "a good example"
输出: "example good a"
解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
方法一:使用语言特性
思路和算法
很多语言对字符串提供了 split(拆分),reverse(翻转)和 join(连接)等方法,因此我们可以简单的调用内置的 API 完成操作:
使用 split 将字符串按空格分割成字符串数组;
使用 reverse 将字符串数组进行反转;
使用 join 方法将字符串数组拼成一个字符串。
class Solution {
public String reverseWords(String s) {
// 除去开头和末尾的空白字符
s = s.trim();
// 正则匹配连续的空白字符作为分隔符分割
List<String> wordList = Arrays.asList(s.split("\\s+"));
Collections.reverse(wordList);
return String.join(" ", wordList);
}
}
复杂度分析
时间复杂度:O(n),其中 n 为输入字符串的长度。
空间复杂度:O(n),用来存储字符串分割之后的结果。
思路二
- 移除多余空格
- 将整个字符串反转
- 将每个单词反转
在 Java 中,StringBuilder
是用于创建和操作可变字符串的类。相较于 String
类的不可变特性,使用 StringBuilder
进行字符串操作可以节省内存并提高性能。常见的操作包括 append
方法用于追加字符串以及 toString
方法用于将 StringBuilder
对象转换为字符串。
*选择使用双指针
class Solution {
public String reverseWords(String s) {
s=s.trim();
StringBuilder ret=new StringBuilder();
int len=s.length()-1;
int i=len,j=len;
while(i>=0){
while(i>=0&&s.charAt(i)!=' '){//找到单词尾部,在单词范围内,移动快指针,找到单词头部//因为已经trim过了,必然第一个是字符而非空格,初始的j就是第一个单词尾部
i--;
}
ret.append(s.substring(i+1,j+1)+' ');
while(i>=0&&s.charAt(i)==' '){//i已经到空格了读取空格去掉,直到下一个新单词
i--;
}
j=i;
}
return ret.toString().trim();
}
}
StringBuilder
的使用
创建 StringBuilder
StringBuilder sb = new StringBuilder();
或者带有初始字符串:
StringBuilder sb = new StringBuilder("Hello");
append
方法
append
方法用于将指定的字符串、字符或其他数据拼接到 StringBuilder
对象的末尾。
StringBuilder sb = new StringBuilder();
sb.append("Hello, ");
sb.append("world!");
System.out.println(sb.toString()); // 输出 "Hello, world!"
append
方法有很多重载版本,可以处理不同类型的数据:
sb.append('a'); // 追加字符
sb.append(123); // 追加整数
sb.append(45.67); // 追加浮点数
sb.append(true); // 追加布尔值
sb.append("String"); // 追加字符串
toString
方法
toString
方法将 StringBuilder
对象转换为 String
对象。
String finalString = sb.toString();
示例代码
以下是一个完整的示例,展示了如何使用 StringBuilder
来构建一个字符串,并最终转换为 String
对象输出到控制台。
public class StringBuilderExample {
public static void main(String[] args) {
// 创建 StringBuilder 对象
StringBuilder sb = new StringBuilder();
// 追加各种类型数据
sb.append("Hello, ");
sb.append("world! ");
sb.append(123);
sb.append(' ');
sb.append(45.67);
sb.append(' ');
sb.append(true);
// 将 StringBuilder 转换为 String 并输出
String finalString = sb.toString();
System.out.println(finalString); // 输出 "Hello, world! 123 45.67 true"
}
}
使用场景
- 字符串拼接:如果需要频繁拼接字符串,使用
StringBuilder
可以避免创建大量临时字符串对象,有效提升性能。 - 动态生成字符串:在循环中生成或修改字符串,对
StringBuilder
操作的性能远优于String
。
使用 StringBuilder 处理复杂字符串操作
为了解更多复杂字符串操作场景,以下是一个如何从多个部分动态生成最终字符串的例子:
示例代码
public class ComplexStringBuilderExample {
public static void main(String[] args) {
// 创建 StringBuilder 对象
StringBuilder sb = new StringBuilder();
// 定义不同的数据部分
String greeting = "Hello, ";
String name = "John";
int age = 30;
String city = "New York";
// 动态构建字符串
sb.append(greeting);
sb.append(name);
sb.append(". You are ");
sb.append(age);
sb.append(" years old and live in ");
sb.append(city);
sb.append(".");
// 将 StringBuilder 转换为 String 并输出
String finalString = sb.toString();
System.out.println(finalString);
// 输出 "Hello, John. You are 30 years old and live in New York."
}
}
复杂字符串操作分离逻辑
这种方式帮助将字符串操作逻辑拆分为更小的部分,避免了代码的冗长与难以维护。例如,你可以将某些字符串生成代码封装进方法或类中,并将这些方法的结果拼接进 StringBuilder
。
public class UserFormatter {
public static void main(String[] args) {
// 创建 StringBuilder 对象
StringBuilder sb = new StringBuilder();
// 定义用户信息
User user = new User("John", 30, "New York");
// 动态构建用户信息字符串
sb.append(formatGreeting(user.getName()));
sb.append(" You are ");
sb.append(user.getAge());
sb.append(" years old and live in ");
sb.append(user.getCity());
sb.append(".");
// 将 StringBuilder 转换为 String 并输出
String finalString = sb.toString();
System.out.println(finalString);
// 输出 "Hello, John. You are 30 years old and live in New York."
}
private static String formatGreeting(String name) {
return "Hello, " + name + ".";
}
}
// 用户类
class User {
private String name;
private int age;
private String city;
public User(String name, int age, String city) {
this.name = name;
this.age = age;
this.city = city;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String getCity() {
return city;
}
}
通过这些示例代码,你可以看到 StringBuilder
的强大功能,特别是在处理动态字符串生成和拼接时,是非常高效和适用的工具。希望这些解释对你理解和运用 StringBuilder
能有所帮助。如果有更进一步的问题,请随时提问!
在 Java 中,String
类提供了 substring
方法,用于提取字符串的子串。该方法具有两个重载版本:
substring(int beginIndex)
: 从指定的beginIndex
开始一直到字符串的结尾。substring(int beginIndex, int endIndex)
: 从beginIndex
开始到endIndex
(不包括endIndex
)的子字符串。
使用示例
示例 1:substring(int beginIndex)
public class SubstringExample {
public static void main(String[] args) {
String str = "Hello, world!";
String substr = str.substring(7);
System.out.println(substr); // 输出 "world!"
}
}
示例 2:substring(int beginIndex, int endIndex)
public class SubstringExample {
public static void main(String[] args) {
String str = "Hello, world!";
String substr = str.substring(7, 12);
System.out.println(substr); // 输出 "world"
}
}
方法签名
public String substring(int beginIndex)
- 参数:
beginIndex
:开始提取子串的索引(从 0 开始)。
- 返回值:从
beginIndex
开始到字符串结尾的子字符串。 - 异常:
- 抛出
IndexOutOfBoundsException
,如果beginIndex
为负数或者超出字符串长度。
- 抛出
public String substring(int beginIndex, int endIndex)
- 参数:
beginIndex
:开始提取子串的索引。endIndex
:结束提取子串的索引(不包括endIndex
)。
- 返回值:从
beginIndex
开始到endIndex
之前的子字符串。 - 异常:
- 抛出
IndexOutOfBoundsException
,如果beginIndex
为负数,或者endIndex
大于字符串长度,或者beginIndex
大于endIndex
。
- 抛出
注意事项
- 索引从 0 开始。
beginIndex
必须在 [0, length()] 范围内。endIndex
必须在 [beginIndex, length()] 范围内。
示例:综合使用 substring
方法
以下是一个综合示例,展示了如何使用 substring
方法从字符串中提取不同的部分:
public class ComprehensiveSubstringExample {
public static void main(String[] args) {
String str = "The quick brown fox jumps over the lazy dog.";
// 提取从索引 4 开始到字符串末尾的子字符串
String substr1 = str.substring(4);
System.out.println(substr1); // 输出 "quick brown fox jumps over the lazy dog."
// 提取从索引 4 开始到索引 9(不包括)的子字符串
String substr2 = str.substring(4, 9);
System.out.println(substr2); // 输出 "quick"
// 提取字符串的前 3 个字符
String substr3 = str.substring(0, 3);
System.out.println(substr3); // 输出 "The"
// 提取字符串的最后 8 个字符
String substr4 = str.substring(str.length() - 8);
System.out.println(substr4); // 输出 "lazy dog."
}
}
用 substring
解决实际问题
假设我们需要解析一个逗号分隔的字符串,并从中分别提取字段。可以通过 String
类的 split
方法和 substring
方法共同实现。
public class ParseCSVExample {
public static void main(String[] args) {
String csvRow = "John,Doe,30,M,New York";
// 使用 split 方法将字符串拆分成数组
String[] fields = csvRow.split(",");
// 提取姓名、姓氏和城市
String firstName = fields[0];
String lastName = fields[1];
String city = fields[4];
System.out.println("First Name: " + firstName); // 输出 "John"
System.out.println("Last Name: " + lastName); // 输出 "Doe"
System.out.println("City: " + city); // 输出 "New York"
}
}
使用 substring
和 StringBuilder
进行字符串处理
假设我们需要从一大段字符串中提取特定模式的数据,并动态构建一个新的字符串,可以结合substring
和 StringBuilder
实现:
public class DynamicStringBuildingExample {
public static void main(String[] args) {
String str = "Data1=100;Data2=200;Data3=300";
// 使用 StringBuilder 进行灵活的字符串拼接
StringBuilder sb = new StringBuilder();
int startIndex = 0;
while (startIndex < str.length()) {
int equalIndex = str.indexOf('=', startIndex);
int semicolonIndex = str.indexOf(';', startIndex);
if (semicolonIndex == -1) {
semicolonIndex = str.length(); // 如果没有找到 ; ,则取字符串的末尾
}
// 提取数据名称和值
String dataName = str.substring(startIndex, equalIndex);
String dataValue = str.substring(equalIndex + 1, semicolonIndex);
// 构建新的字符串
sb.append(dataName + ": " + dataValue + "\n");
// 更新 startIndex
startIndex = semicolonIndex + 1;
}
System.out.println(sb.toString());
// 输出:
// Data1: 100
// Data2: 200
// Data3: 300
}
}
通过这些示例和解释,你可以看到 substring
在各种字符串操作中的应用及其灵活性。希望这些解释对你理解和使用 substring
方法有所帮助。如果有任何问题,欢迎随时提问!
在 Java 中,String
类提供了 trim
方法,用于去除字符串两端的空白字符(空格、制表符等)。这个方法非常方便用于数据清理和预处理场景。
trim
方法
定义和使用
public String trim()
- 返回值:返回一个新的字符串,表示去除前导和尾部空白后的结果。
- 原字符串不变:
trim
方法返回的是一个新字符串,原字符串保持不变,因为String
是不可变的对象。
示例代码
public class TrimExample {
public static void main(String[] args) {
String str = " Hello, World! ";
String trimmedStr = str.trim();
System.out.println("Before trim: '" + str + "'");
System.out.println("After trim: '" + trimmedStr + "'");
}
}
输出:
Before trim: ' Hello, World! '
After trim: 'Hello, World!'
应用场景
- 数据清理:在处理用户输入或从文件读取数据时,确保输入数据没有意外的前导或尾部空白。
- 字符串比对:在比对字符串时,先去除两端空白字符,以防止不必要的错误或误差。
注意事项
trim
只能去除两端的空白字符,不会影响字符串内部的空白字符(如空格或制表符)。- 如果需要去除字符串内部的空白字符,可以使用正则表达式或其他方法。
去除字符串内部的空白字符
如果我们需要去除不仅仅是两端的空白字符,还需要去除字符串内部的空白字符,可以结合 replace
方法或正则表达式:
使用 replaceAll
方法
public class RemoveInternalWhitespace {
public static void main(String[] args) {
String str = " Hello, World! ";
String trimmedStr = str.trim();
String result = trimmedStr.replaceAll("\\s+", ""); // 去除所有空白字符(包括中间的)
System.out.println("Before: '" + str + "'");
System.out.println("After removing internal whitespace: '" + result + "'");
}
}
输出:
Before: ' Hello, World! '
After removing internal whitespace: 'Hello,World!'
综合示例
以下示例展示了如何去除一段字符串两端和中间的空白字符:
public class ComprehensiveTrimExample {
public static void main(String[] args) {
String originalString = " John Doe ";
// 去除两端空白字符
String trimmedString = originalString.trim();
System.out.println("Original: '" + originalString + "'");
System.out.println("Trimmed: '" + trimmedString + "'");
// 去除中间的空白字符
String noWhitespaceString = trimmedString.replaceAll("\\s+", "");
System.out.println("No Whitespace: '" + noWhitespaceString + "'");
}
}
输出:
Original: ' John Doe '
Trimmed: 'John Doe'
No Whitespace: 'JohnDoe'
利用 trim
方法处理文件数据
假设我们从文件中读取了多行数据,并希望对于每行数据都去除两端的空白字符,可以如下操作:
import java.util.*;
import java.io.*;
public class TrimFileData {
public static void main(String[] args) {
List<String> lines = Arrays.asList(
" Line 1 with leading and trailing spaces ",
" Line 2 with leading and trailing spaces ",
" Line 3 with leading and trailing spaces "
);
List<String> trimmedLines = new ArrayList<>();
for (String line : lines) {
String trimmedLine = line.trim();
trimmedLines.add(trimmedLine);
}
System.out.println("Original Lines:");
for (String line : lines) {
System.out.println("'" + line + "'");
}
System.out.println("\nTrimmed Lines:");
for (String line : trimmedLines) {
System.out.println("'" + line + "'");
}
}
}
输出:
Original Lines:
' Line 1 with leading and trailing spaces '
' Line 2 with leading and trailing spaces '
' Line 3 with leading and trailing spaces '
Trimmed Lines:
'Line 1 with leading and trailing spaces'
'Line 2 with leading and trailing spaces'
'Line 3 with leading and trailing spaces'
通过 trim
方法,我们可以很方便地去除字符串两端的空白字符,而结合其他字符串方法,如 replaceAll
等,我们还可以灵活地处理字符串内部的空白字符。这些字符串预处理方法在数据清理和准备过程中非常有用。希望这些示例和解释能够帮助你更好地理解和应用 trim
方法。如果你有任何问题,欢迎随时提问!
思路三
双端队列
思路和算法
由于双端队列支持从队列头部插入的方法,因此我们可以沿着字符串一个一个单词处理,然后将单词压入队列的头部,再将队列转成字符串即可。
class Solution {
public String reverseWords(String s) {
int left = 0, right = s.length() - 1;
// 去掉字符串开头的空白字符
while (left <= right && s.charAt(left) == ' ') {
++left;
}
// 去掉字符串末尾的空白字符
while (left <= right && s.charAt(right) == ' ') {
--right;
}
Deque<String> d = new ArrayDeque<String>();
StringBuilder word = new StringBuilder();
while (left <= right) {
char c = s.charAt(left);
if ((word.length() != 0) && (c == ' ')) {
// 将单词 push 到队列的头部
d.offerFirst(word.toString());
word.setLength(0);
} else if (c != ' ') {
word.append(c);
}
++left;
}
d.offerFirst(word.toString());
return String.join(" ", d);
}
}
复杂度分析
时间复杂度:O(n),其中 n 为输入字符串的长度。
空间复杂度:O(n),双端队列存储单词需要 O(n) 的空间。
右旋字符串
字符串的右旋转操作是把字符串尾部的若干个字符转移到字符串的前面。给定一个字符串 s 和一个正整数 k,请编写一个函数,将字符串中的后面 k 个字符移到字符串的前面,实现字符串的右旋转操作。
例如,对于输入字符串 "abcdefg" 和整数 2,函数应该将其转换为 "fgabcde"。
输入:输入共包含两行,第一行为一个正整数 k,代表右旋转的位数。第二行为字符串 s,代表需要旋转的字符串。
输出:输出共一行,为进行了右旋转操作后的字符串。
样例输入:
2
abcdefg
1
2
样例输出:
fgabcde
1
数据范围:1 <= k < 10000, 1 <= s.length < 10000;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = Integer.parseInt(in.nextLine());
String s = in.nextLine();
int len=s.length();
char[] ch=s.toCharArray();
reverseString(ch,0,len-1);
reverseString(ch,0,n-1);
reverseString(ch,n,len-1);
System.out.println(ch);
}
public static void reverseString(char[] ch,int i,int j){
while(i<j){
char temp=ch[i];
ch[i]=ch[j];
ch[j]=temp;
i++;
j--;
}
}
}