LeetCode ACM模式——字符串篇

目录

344. 反转字符串

541. 反转字符串 II

剑指 Offer 05. 替换空格

151. 反转字符串中的单词

剑指 Offer 58 - II. 左旋转字符串

28. 找出字符串中第一个匹配项的下标

459. 重复的子字符串

 刷题顺序及思路来源于代码随想录,网站地址:https://programmercarl.com 



​​​​​​344. 反转字符串

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题

输入:s = ["h","e","l","l","o"]
输出:["o","l","l","e","h"]
import java.util.Scanner;

/**
 * @author light
 * @Description 反转字符串
 * @create 2023-08-03 9:54
 */
public class ReverseStringTest {
	public static void main(String[] args) {
		Scanner input=new Scanner(System.in);
		String str=input.next();
		char[] arr=str.toCharArray();
		reverseString(arr);
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i]);
		}
	}
	public static void reverseString(char[] s) {
		for (int i = 0; i < s.length/2; i++) {
			char temp=s[s.length-i-1];
			s[s.length-i-1]=s[i];
			s[i]=temp;
		}

	}
}

541. 反转字符串 II

给定一个字符串 s 和一个整数 k,从字符串开头算起, 每计数至 2k 个字符,就反转这 2k 个字符中的前 k 个字符。

如果剩余字符少于 k 个,则将剩余字符全部反转。

如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。

输入:s = "abcdefg", k = 2
输出:"bacdfeg"
import java.util.Scanner;

/**
 * @author light
 * @Description 反转字符串 II
 *
 * 思路:
 * 其实在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。
 *
 * 因为要找的也就是每2 * k 区间的起点,这样写,程序会高效很多。
 *
 * 所以当需要固定规律一段一段去处理字符串的时候,要想想在在for循环的表达式上做做文章。
 * @create 2023-08-03 10:32
 */
public class ReverseStrTest {
	public static void main(String[] args) {
		Scanner input=new Scanner(System.in);
		String s=input.next();
		int k=input.nextInt();
		String str=reverseStr(s,k);
		System.out.println(str);
	}
	public static String reverseStr(String s, int k) {
		char[] arr=s.toCharArray();
		for (int i = 0; i < arr.length; i+=(2*k)) {
			if(i+k<=arr.length){
				//1.每隔2k个字符反转前k个
				//2.剩余字符小于2k但大于或等于k个,反转前k个字符
				int end=i+k-1;
				reverse(arr,i,end);
			}else{
				//3.剩余字符不足k个,将剩余字符全部反转
				reverse(arr,i,arr.length-1);
			}
		}
		return new String(arr);
	}
	//自定义反转函数
	public static void  reverse(char[] arr,int start,int end){
		while(start<end){
			char temp=arr[end];
			arr[end]=arr[start];
			arr[start]=temp;
			end--;
			start++;
		}
	}
}

剑指 Offer 05. 替换空格

请实现一个函数,把字符串 s 中的每个空格替换成"%20"

输入:s = "We are happy."
输出:"We%20are%20happy."
import java.util.Scanner;

/**
 * @author light
 * @Description 替换空格
 * 请实现一个函数,把字符串s中的每个空格替换成"%20"。
 *
 * @create 2023-08-03 11:05
 */
public class ReplaceSpaceTest {
	public static void main(String[] args) {
		Scanner input=new Scanner(System.in);
		/*
		1.next()方法只会读取输入中的一个单词(以空格为分隔符),并将其作为字符串返回。
		2.nextLine()方法会读取整行输入,并将其作为字符串返回。
		 */
		String s=input.nextLine();
		s=replaceSpace(s);
		System.out.println(s);
	}
	public static String replaceSpace(String s) {
		if(s==null||s.length()==0){
			return s;
		}
		StringBuilder sb=new StringBuilder();
		for (int i = 0; i < s.length(); i++) {
			if(s.charAt(i)==' '){
				sb.append("%20");
			}else{
				sb.append(s.charAt(i));
			}
		}
		return sb.toString();
	}
}

151. 反转字符串中的单词

给你一个字符串 s ,请你反转字符串中 单词 的顺序。

单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。

返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。

注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。

输入:s = "the sky is blue"
输出:"blue is sky the"
import java.util.Scanner;

/**
 * @author light
 * @Description 反转字符串中的单词
 * @create 2023-08-03 11:39
 */
public class ReverseWordsTest {
	public static void main(String[] args) {
		Scanner input=new Scanner(System.in);
		/*
		1.next()方法只会读取输入中的一个单词(以空格为分隔符),并将其作为字符串返回。
		2.nextLine()方法会读取整行输入,并将其作为字符串返回。
		 */
		String s=input.nextLine();
		s=reverseWords(s);
		System.out.println(s);

	}
	public static String reverseWords(String s) {
		char[] arr=s.toCharArray();
		//1.去掉字符串中首尾及中间多余空格
		arr=removeExtraSpaces(arr);
		//System.out.println("去除多余空格后:");
		//for (int i = 0; i < arr.length; i++) {
		//	System.out.print(arr[i]);
		//}
		//2.将字符串全部反转
		reverseStr(arr,0,arr.length-1);
		//System.out.println("\n全部反转后:");
		//for (int i = 0; i < arr.length; i++) {
		//	System.out.print(arr[i]);
		//}
		//3.将字符串中单词再反转一遍
		reverseEachWord(arr);
		//System.out.println("\n反转单个单词后:");
		//for (int i = 0; i < arr.length; i++) {
		//	System.out.print(arr[i]);
		//}
		return new String(arr);
	}

	private static char[] removeExtraSpaces(char[] arr) {
		//双指针
		int slow=0;
		for (int fast = 0; fast < arr.length; fast++) {
			//移除所有空格
			if(arr[fast]!=' '){
				//除了第一个单词外,所有单词中间有一个空格
				if(slow!=0){
					arr[slow]=' ';
					slow++;
				}
				while(fast<arr.length&&arr[fast]!=' '){
					arr[slow++]=arr[fast++];
				}
			}
		}
		char[] ch=new char[slow];
		//System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
		//src:源数组 srcPos:源数组要复制的起始位置 dest:目的数组 destPos:目的数组放置的起始位置 length:复制的长度.
		// 就是把一个数组中某一段字节数据放到另一个数组中
		System.arraycopy(arr,0,ch,0,slow);
		return ch;

	}

	private static void reverseStr(char[] arr,int start,int end) {
		while(start<end){
			char temp=arr[end];
			arr[end]=arr[start];
			arr[start]=temp;
			end--;
			start++;
		}
	}

	private static void reverseEachWord(char[] arr) {
		int start=0;
		int end=0;
		while(end<arr.length){
			while(end<arr.length&&arr[end]!=' '){
				end++;
			}
			reverseStr(arr,start,end-1);
			start=end+1;
			end=start+1;
		}
	}
}

剑指 Offer 58 - II. 左旋转字符串

字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。

输入: s = "abcdefg", k = 2
输出: "cdefgab"
import java.util.Scanner;

/**
 * @author light
 * @Description 左旋转字符串
 * @create 2023-08-03 13:08
 */
public class ReverseLeftWordsTest {
	public static void main(String[] args) {
		Scanner input=new Scanner(System.in);
		String s=input.next();
		int k=input.nextInt();
		s=reverseLeftWords(s,k);
		System.out.println(s);

	}
	public static String reverseLeftWords(String s, int n) {
		//在原有字符串上操作
		char[] arr=s.toCharArray();
		//先反转前n个字符
		reverse(arr,0,n-1);
		//在反转后半部分字符
		reverse(arr,n,arr.length-1);
		//最后反转整个字符
		reverse(arr,0,arr.length-1);
		return new String(arr);
	}
	public static void  reverse(char[] arr,int start,int end){
		while(start<end){
			char temp=arr[end];
			arr[end]=arr[start];
			arr[start]=temp;
			end--;
			start++;
		}
	}
}

28. 找出字符串中第一个匹配项的下标

给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回  -1 

输入:haystack = "sadbutsad", needle = "sad"
输出:0
解释:"sad" 在下标 0 和 6 处匹配。
第一个匹配项的下标是 0 ,所以返回 0 。


import java.util.Scanner;

/**
 * @author light
 * @Description 找出字符串中第一个匹配项的下标(实现strStr()函数
 *
 *
 * (kmp算法:当出现字符串不匹配时,可以记录一部分之前已经匹配的文本内部,
 * 			 利用这些信息避免从头再去做匹配
 * 		本质:在当前文本串和模式串检索过程中,若出现了不匹配,如何充分利用已经匹配的部分
 * @create 2023-08-03 20:53
 */
public class StrStrTest {
	public static void main(String[] args) {
		Scanner input=new Scanner(System.in);
		String haystack =input.next();
		String needle =input.next();
		int res = strStr(haystack, needle);
		System.out.println(res);

	}
	public static int strStr(String haystack, String needle) {
		int[] next=new int[needle.length()];
		/*获取next数组(前缀表
		next数组:用来回退的,他记录了模式串中与主串不皮牌的时候,模式串应该从哪里开始重新匹配
		 */
		getNext(next,needle);
		int j=0;
		for (int i = 0; i < haystack.length(); i++) {
			while (j>0&&haystack.charAt(i)!=needle.charAt(j)){
				j=next[j-1];
			}
			if(haystack.charAt(i)==needle.charAt(j)){
				j++;
			}
			if(j==needle.length()){
				return i-needle.length()+1;
			}
		}

		return -1;
	}

	public static void getNext(int[] next,String needle){
		/*1.初始化:
			j:前缀末尾位置(并且是i(包括i)之前的最长相等前后缀长度
			i:后缀末尾位置
			初始化next数组
		 */
		int j=0;
		next[0]=0;
		for (int i = 1; i <needle.length() ; i++) {
			//2.前后缀不相等
			while(j>0&&needle.charAt(i)!=needle.charAt(j)){
				j=next[j-1];
			}
			//3.前后缀相等
			if(needle.charAt(i)==needle.charAt(j)){
				j++;
			}
			//4.为next数组赋值
			next[i]=j;
		}

	}
}

459. 重复的子字符串

给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。

输入: s = "abab"
输出: true
解释: 可由子串 "ab" 重复两次构成。
import java.util.Scanner;

/**
 * @author light
 * @Description 重复的子字符串
 *
 *(枚举法)
 * @create 2023-08-11 1:40
 */
public class RepeatedSubstringPatternTest {
	public static void main(String[] args) {
		Scanner input=new Scanner(System.in);
		String s =input.next();
		boolean res = repeatedSubstringPattern(s);
		System.out.println(res);
	}
	public static boolean repeatedSubstringPattern(String s) {
		int n = s.length();
		for (int i = 1; i * 2 <= n; ++i) {
			if (n % i == 0) {
				boolean match = true;
				for (int j = i; j < n; ++j) {
					if (s.charAt(j) != s.charAt(j - i)) {
						match = false;
						break;
					}
				}
				if (match) {
					return true;
				}
			}
		}
		return false;
	}

}

猜你喜欢

转载自blog.csdn.net/zssxcj/article/details/132076660
今日推荐