【算法】字符串的旋转及单词翻转

本文探讨了字符串的旋转问题,包括不同解决方案如蛮力移位、substring引用和三步反转策略。同时介绍了单词翻转,同样采用三步反转方法,保持单词内字符顺序不变。内容摘自《编程之法——面试和算法心得》。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

核心代码摘录自《编程之法——面试和算法心得》一书,侵删。
本文目的只是做记录,记录心得与代码,便于以后测试使用。



字符串的旋转

题目描述:

给定一个字符串,要求将字符串前面的若干个字符,移动到字符串的尾部。
示例:

原始字符串:abcdef
移动几个字符?3
打印结果:defabc

个人分析:此问题,虽然明确指明是字符串的旋转,其实本意是字符数组的旋转。

测试代码

public static void main(String[] args) {
   
   
		System.out.println("给定一个字符串,要求将字符串前面的若干个字符,移动到字符串的尾部。");
		System.out.print("原始字符串:");
		char[] s = StdIn.readString().toCharArray();
		System.out.print("移动几个字符?");
		int m = StdIn.readInt();
		if(!(0 < m) || !(m < s.length) ) {
   
   
			return ;
		}
		
		LeftRotateString(s, s.length, m);
		System.out.printf("打印结果:%s", String.valueOf(s));
	}

方案一:蛮力移位

	// 蛮力移位
	public static void leftShiftOne(char[] s, int n) {
   
   // n 是数组长度
		char first = s[0];
		for(int i = 1; i < n; i++) {
   
   
			s[i-1] = s[i];
		}
		s[n-1] = first;
	}
	
	public static void leftRotateString(char[] s, int n, int m) {
   
   
		while(m--!=0) {
   
   
			leftShiftOne(s, n);
		}
		// 时间复杂度 O(nm),空间复杂度O(1)
	}

方案二:参考substring

	public static void LeftRotateString3(char[] s, int n, int m) {
   
   
		char[] tmp = new char[m];
		for(int
### 字符串算法及相关练习题 字符串作为计算机科学中最基础的数据结构之一,其相关算法在实际应用中非常广泛。以下是几个常见的字符串算法及其对应的练习题: #### 1. **无重复字符的最长子串** 该问题的目标是从输入字符串中找到不包含重复字符的最长子串长度。可以通过滑动窗口技术实现此功能。 ```python def length_of_longest_substring(s: str) -> int: char_set = set() l = 0 res = 0 for r in range(len(s)): while s[r] in char_set: char_set.remove(s[l]) l += 1 char_set.add(s[r]) res = max(res, r - l + 1) return res ``` 上述方法的时间复杂度为 O(N),空间复杂度同样为 O(N)[^4]。 --- #### 2. **最长回文子串** 目标是在给定字符串中找出最长的回文子串。可以采用动态规划或中心扩展法解决这一问题。 ```python def longest_palindrome(s: str) -> str: if not s or len(s) < 1: return "" start, end = 0, 0 def expand_around_center(left, right): while left >= 0 and right < len(s) and s[left] == s[right]: left -= 1 right += 1 return right - left - 1 for i in range(len(s)): len1 = expand_around_center(i, i) len2 = expand_around_center(i, i + 1) curr_len = max(len1, len2) if curr_len > end - start: start = i - (curr_len - 1) // 2 end = i + curr_len // 2 return s[start:end+1] ``` 这种方法通过枚举每个可能的中心来计算最大回文半径。 --- #### 3. **反转字符串中的单词** 对于一个字符串 `s`,将其内部的单词顺序翻转并去除多余空格是一个经典问题。 ```python def reverse_words(s: str) -> str: words = s.strip().split()[::-1] return ' '.join(words) print(reverse_words("Python Programming")) # 输出:"Programming Python" ``` 这里利用了内置函数 split 和 join 来处理空白字符以及拼接操作[^2]。 --- #### 4. **字符串的循环左移** 将字符串按照指定步数向左移动若干位也是常见考察点之一。 ```cpp class Solution { public: string rotateString(string s, int n){ if(n <= 0 || s.empty()) return s; n %= s.length(); std::rotate(s.begin(), s.begin()+n, s.end()); return s; } }; ``` 这段 C++ 实现展示了如何优雅地完成旋转动作[^5]。 --- #### 5. **KMP模式匹配算法** Knuth-Morris-Pratt(KMP) 是一种高效的字符串查找算法,能够在线性时间内定位子串的位置。 ```java public static void computeLPSArray(String pat, int M, int[] lps){ int len = 0; lps[0]=0; int i=1; while(i<M){ if(pat.charAt(i)==pat.charAt(len)){ len++; lps[i]=len; i++; } else{ if(len!=0){ len=lps[len-1]; } else{ lps[i]=0; i++; } } } } ``` 以上 Java 版本实现了 KMP 的核心部分——构建 LPS 数组的过程[^1]。 --- ### 总结 这些例子涵盖了从简单到复杂的多种字符串处理技巧,适合用来准备数据结构与算法方面的面试。每道题目都经过精心挑选以覆盖不同难度级别和技术要点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值