算法通关村第十二关——字符串反转问题解析

这篇具有很好参考价值的文章主要介绍了算法通关村第十二关——字符串反转问题解析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

字符串反转是关于字符串算法里的重要问题,虽然不是太难,但需要考虑到一些边界问题。本篇文章就对几道字符串反转题目进行分析。

1.反转字符串

力扣344题,编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

分析:这是最基础的字符串反转问题,我们除了可以用语言内置函数解决(面试时基本不会让用),还可以采用双指针的办法解决,算法步骤如下:

  1. 设置left = 0, right = strArray.length - 1
  2. left < right时:
    • 交换strArray[left]strArray[right]
    • left右移一位,right左移一位
  3. left >= right时,反转完成,对反转后的字符串数组进行拼接strArray.join(''),最后返回拼接后的字符串

本题代码如下:文章来源地址https://www.toymoban.com/news/detail-691288.html

/**
 * @param {character[]} s
 * @return {void}
 * */
function reverseStr(s) {
	// 特判
	if (s === null || s.length === 0) {
		return s;
	}

	// 双指针交换
	let left = 0, right = s.length - 1;
	while (left <= right) {
		[s[left], s[right]] = [s[right], s[left]];
		left++;
		right--;
	}
}

注意:如果实际给你的是字符串而不是这道题给的字符串数组,就需要利用JS的Array.from(s)将字符串转换为字符串数组

2.每2k个字符就反转前k个字符

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

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

分析:这道题没有什么好说的,就是让每2k个字符就反转前k个字符。记得先把字符串转换为字符串数组,如果字符串长度不足k,就反转整个字符串。

代码如下:

// 每2k个字符就反转前k个字符
function reverseStr(s, k) {
	if (s === null || s.length === 0) {
		return s;
	}
	// 转换为字符串数组
	const strArray = Array.from(s);

	const lengthStr = strArray.length;
	for (let i = 0; i < lengthStr; i += 2*k) {
         // 字符串长度不足k,就反转整个字符串
		reverse(strArray, i, Math.min(i + k, lengthStr) - 1);
	}
	// 拼接反转后的字符串
	return strArray.join('');
}

/**
 * 反转字符函数
 * */
function reverse(strArray, left, right) {
	while (left < right) {
		[strArray[left], strArray[right]] = [strArray[right], strArray[left]];
		left++;
		right--;
	}
}

3.仅仅反转字母

力扣917题,给定一个字符串 S,返回 “反转后的” 字符串,其中不是字母的字符都保留在原地,而所有字母的位置发生反转。

分析:首先想到的就是利用双指针和字母对应的ASCII码判断来实现:

  1. 字符串转为字符串数组,left = 0right = Array.length - 1;
  2. left < right
    • 如果两个指针指向的都是字母,就交换位置
    • 如果右指针指向的是字母,左指针不是,则left++
    • 同样如果左指针指向的是字母,右指针不是,则right--
    • 如果两个指针指向的都不是字母,则left++,right--
  3. 拼接反转后的字符串并返回

代码如下:

// 首先想到利用双指针实现
function reverseOnlyLetters(s) {
    // 特判
	if (s === null || s.length === 0) {
		return s;
	}
	
    // 得到字符串数组
	const strArray = Array.from(s);
	const lengthStr = s.length;

	let left = 0, right = lengthStr - 1;

	while (left < right) {
		// 两个指针的指向都是字符串
		if (isLetter(s, left) && isLetter(s, right)) {
			[strArray[left], strArray[right]] = [strArray[right], strArray[left]];
			left++;
			right--;
		}
		// 一个指向的是字母,一个不是
		else if (!isLetter(s, left)) {
			left++;
		}
		else if (!isLetter(s, right)) {
			right--;
		}
		// 两个指针指向的都不是字母
		else {
			left++;
			right--;
		}
	}

	return strArray.join('');
}

// 判断当前字符是否是字母
function isLetter(s, index) {
	if (s.charCodeAt(index) >= 65 && s.charCodeAt(index) <= 90 || 
		s.charCodeAt(index) >= 97 && s.charCodeAt(index) <= 122) {
		return true;
	}
	return false;
}

4.反转字符串里的单词

力扣151题,给你一个字符串 s ,逐个反转字符串中的所有 单词 。单词是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。请你返回一个反转 s 中单词顺序并用单个空格相连的字符串。
说明:

  • 输入字符串 s 可以在前面、后面或者单词间包含多余的空格。
  • 反转后单词间应当仅用一个空格分隔。
  • 反转后的字符串中不应包含额外的空格。

分析:本题同样可以用语言内置函数来实现,且比较简单,实际应用当中可以,但为了我们加深我们对数据结构的认知,最好还是自己实现一遍。思路大概都是一致的:

  1. 将字符串转换为字符串数组,去除字符串里多余的空格
  2. 反转整个字符串,此时单词字母也是逆序
  3. 再反转每个单词

算法通关村第十二关——字符串反转问题解析,算法,算法,数据结构,前端,javascript

本题代码如下:

// 使用内置函数
function reverseWords(s) {
	// 去除开头和结尾的空格
	s = s.trim();
	// 按空格分割字符串,匹配所有空格
	const reg = /\s+/; 
	const words = s.split(reg);
	words.reverse();
	return words.join(' ');
}

/*---------------------------------------*/


// 不使用内置函数,自己实现
function reverseWords(s) {
	// 字符串转数组
	const strArray = Array.from(s);
	// 得到去除了多余空格后的字符串数组
	const trimedStrArray =  trimSpaces(strArray);
	// 得到反转字符串数组
	reverse(trimedStrArray, 0, trimedStrArray.length - 1 );
	// 对反转字符串数组的每个单词进行反转
	const res = reverseEachWord(trimedStrArray);
	return res.join('');
}

/**
 * 去除字符串数组多余空格
 * */
function trimSpaces(strArray) {
	let left = 0, right = 0, arrLength = strArray.length;
	while (left < arrLength) {
		// 移除开始位置和重复的空格
		if (strArray[left] === ' ' && (left === 0 || strArray[left - 1] === ' ')) {
			left++;
		} else {
			strArray[right++] = strArray[left++];
		}
	}

	// 移除末尾空格
	strArray.length = (strArray[right - 1] === ' ' ? right - 1 : right);

	return strArray;
}

/**
 * 反转每个单词
 * */
// 双指针
function reverseEachWord(strArray) {
	const lengthOfStrArray = strArray.length;
	let start = 0, end = 0;

	while (start < lengthOfStrArray) {
		// 找到一个单词的末尾
		while (end < lengthOfStrArray && strArray[end] !== ' ') {
			end++;
		}
		// 反转单词,更新start的位置
		reverse(strArray, start, end - 1);
		start = end + 1;
		end++;
	}
	return strArray;
}

/**
 * 反转字符串数组
 * */
function reverse(strArray, start, end) {
	let left = start, right = end;
	while (left < right) {
		[strArray[left], strArray[right]] = [strArray[right], strArray[left]];
		left++;
		right--;
	}
}


到了这里,关于算法通关村第十二关——字符串反转问题解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 不简单的字符串转换问题(算法村第十二关青铜挑战)

    709. 转换成小写字母 - 力扣(LeetCode) 给你一个字符串 s ,将该字符串中的大写字母转换成相同的小写字母,返回新的字符串。 1 = s.length = 100 解 大写字母和小写字母的值之间存在固定的差异。例如,小写字母 a 的ASCII值为 97 ,而对应的大写字母 A 的ASCII值为 65 ,两者之差恰

    2024年01月25日
    浏览(47)
  • 算法通关村第二关——链表反转

    链表反转,就是链表原来是1-2-3-4-5,经过反转处理过后变成5-4-3-2-1 处理链表反转,有两种方式,一个是建立虚拟头结点,一个是直接操作链表反转。  这是执行的流程 最核心的两行就是 直接想我要让她反转,我现在设立了虚拟头结点,那我就要让新加进这个反转链表的结点

    2024年02月13日
    浏览(36)
  • 【LeetCode】《LeetCode 101》第十二章:字符串

    思路及代码: 242 . 有效的字母异位词 思路及代码: 205. 同构字符串 思路及代码: 647. 回文子串 思路及代码: 696 . 计数二进制子串 思路及代码 : 224. 基本计算器 思路及代码: 227. 基本计算器 II 思路与代码: 28 . 找出字符串中第一个匹配项的下标 思路及代码 :409. 最长回文

    2024年02月10日
    浏览(83)
  • 算法通关村第二关——指定区间反转问题解析

    Leetcode92有这样一道题:给你单链表的头指针head和两个整数left、right,其中left=right,请你反转从位置left到位置right的链表结点,返回反转后的链表,如图所示: 这道题呢,有两种不同的解法,分别是头插法和穿针引线法,头插法就是我们前面说过的带头结点的反转,而穿针引

    2024年02月14日
    浏览(43)
  • 算法通关村第二关,终于学会反转链表!

    文章目录 一、反转链表 总结 提示:以下是本篇文章正文内容,下面案例可供参考 反转链表主要是用三个指针,一个指针指向空,一个指向head第一个节点,一个在循环做的临时变量,在循环设置这个指针不用考虑head为空的情况,然后在循环改变指向后,向前移动一步,然后

    2024年02月14日
    浏览(47)
  • 算法通关村第二关——K个一组反转

    前面有很多关于链表反转的知识,K个一组反转,就是让很多组节点进行翻转,本质也都是一样的。 现在的链表是 3-2-1-4-5-6-7-8 3-2-1已经进行了反转,现在要进行反转的是4-5-6 在这里首先计算出链表的长度,然后计算出要反转几组,现在定义pre为dummyNode,cur定义为head。 通过f

    2024年02月14日
    浏览(45)
  • 算法通关村第二关——终于学会链表反转了

     方法一:建立虚拟头结点辅助反转 创建一个虚拟头节点,获取链表中每个节点,用虚拟头节点指向这个节点,并在链表中删除, 方法二:直接操作链表实现反转 记录当前节点(cur),前驱节点(pre),后继节点(next),先将当前节点的下一个节点指向前驱节点,然后将当前节点赋给前

    2024年02月14日
    浏览(49)
  • 【算法第六天7.19】反转字符串,反转字符串||,剑指 Offer 05. 替换空格,反转字符串的单词, 左旋转字符串

    ================================================ 思路 :以中间为分界线,左右两个边界交换字符,依次向里收缩 思路 : 首先:字符串转化为字符数组 char[] res = s.toCharArray(); 最后:将数组再转回字符串 return new String(res); 1、循环以2k为单位, 2、在这个2k长的数组中进行反转,需要有首

    2024年02月16日
    浏览(63)
  • 算法刷题-字符串-反转字符串II

    简单的反转还不够,我要花式反转 力扣题目链接 给定一个字符串 s 和一个整数 k,从字符串开头算起, 每计数至 2k 个字符,就反转这 2k 个字符中的前 k 个字符。 如果剩余字符少于 k 个,则将剩余字符全部反转。 如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,

    2024年02月09日
    浏览(49)
  • 算法通关村十三关 | 数组字符串加法专题

    题目:LeetCode66,66. 加一 - 力扣(LeetCode) 我们只需要从头到尾依次运算,用常量标记是否进位,需要考虑的特殊情况是digits = [9,9,9]的时候进位,我们组要创建长度加1的数组,首位添加为1即可。         给定两个非负形式的字符串num1和num2,计算他们的和以字符串形式返

    2024年02月11日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包