[LeetCode] Find And Replace in String 在字符串中查找和替换
To some string S, we will perform some replacement operations that replace groups of letters with new ones (not necessarily the same size).
Each replacement operation has 3 parameters: a starting index i, a source word x and a target word y. The rule is that if x starts at position i in the original string S, then we will replace that occurrence of x with y. If not, we do nothing.
For example, if we have S = "abcd" and we have some replacement operation i = 2, x = "cd", y = "ffff", then because "cd" starts at position 2 in the original string S, we will replace it with "ffff".
Using another example on S = "abcd", if we have both the replacement operation i = 0, x = "ab", y = "eee", as well as another replacement operation i = 2, x = "ec", y = "ffff", this second operation does nothing because in the original string S[2] = 'c', which doesn't match x[0] = 'e'.
All these operations occur simultaneously. It's guaranteed that there won't be any overlap in replacement: for example, S = "abc", indexes = [0, 1], sources = ["ab","bc"] is not a valid test case.
Example 1:
Input: S = "abcd", indexes = [0,2], sources = ["a","cd"], targets = ["eee","ffff"]
Output: "eeebffff"
Explanation: "a" starts at index 0 in S, so it's replaced by "eee".
"cd" starts at index 2 in S, so it's replaced by "ffff".
Example 2:
Input: S = "abcd", indexes = [0,2], sources = ["ab","ec"], targets = ["eee","ffff"]
Output: "eeecd"
Explanation: "ab" starts at index 0 in S, so it's replaced by "eee".
"ec" doesn't starts at index 2 in the original S, so we do nothing.
Notes:
0 <= indexes.length = sources.length = targets.length <= 1000 < indexes[i] < S.length <= 1000- All characters in given inputs are lowercase letters.
这道题给了我们一个字符串S,并给了一个坐标数组,还有一个源字符串数组,还有目标字符串数组,意思是若某个坐标位置起,源字符串数组中对应位置的字符串出现了,将其替换为目标字符串。题目真的是好长,但好在给了两个例子可以帮助我们很好的理解题意。此题的核心操作就两个,查找和替换,需要注意的是,由于替换操作会改变原字符串,但是我们查找始终是基于最初始的S,比如例子2中,当完成了第一次替换后,S变为了 "eeecd",好像此时 "ec" 出现了,但仍然不能替换,因为一切查找都是基于最原始的那个S。那么正向的替换可能会产生这样的问题,我们注意到题目中有个限制条件,就是说不会有重叠产生,比如 "abc",如果让在0位置上查找 "ab" 了,就不会让在1位置上查找 "bc",这样的话,其实我们可以从后往前开始查找替换,因为不会有重叠,所以后面替换了的字符不会影响到前面。首先我们需要给indexes数组排个序,因为可能不是有序的,但是却不能直接排序,这样会丢失和sources,targets数组的对应关系,这很麻烦。所以我们新建了一个保存pair对儿的数组,将indexes数组中的数字跟其位置坐标组成pair对儿,加入新数组v中,然后给这个新数组按从大到小的方式排序,这样我们既排了序,又保存了对应关系,岂不美哉!
下面就要开始遍历新数组v了,对于遍历到的pair对儿,取出第一个数字,保存到i,表示S中需要查找的位置,取出第二个数字,然后根据这个位置分别到sources和targets数组中取出源字符串和目标字符串,然后我们在S中的i位置,向后取出和源字符串长度相同的子串,然后比较,若正好和源字符串相等,则将其替换为目标字符串即可,参见代码如下:
解法一:
class Solution {
public:
string findReplaceString(string S, vector<int>& indexes, vector<string>& sources, vector<string>& targets) {
vector<pair<int, int>> v;
for (int i = ; i < indexes.size(); ++i) {
v.push_back({indexes[i], i});
}
sort(v.rbegin(), v.rend());
for (auto a : v) {
int i = a.first;
string s = sources[a.second], t = targets[a.second];
if (S.substr(i, s.size()) == s) {
S = S.substr(, i) + t + S.substr(i + s.size());
}
}
return S;
}
};
我们也可以使用TreeMap来代替需要排序的数组,由于TreeMap默认的是最小堆,而我们需要的是最大堆,只要在定义上加一个greater就行了,其他部分基本没有任何的区别,参见代码如下:
解法二:
class Solution {
public:
string findReplaceString(string S, vector<int>& indexes, vector<string>& sources, vector<string>& targets) {
map<int, int, greater<int>> m;
for (int i = ; i < indexes.size(); ++i) {
m[indexes[i]] = i;
}
for (auto a : m) {
int i = a.first;
string s = sources[a.second], t = targets[a.second];
if (S.substr(i, s.size()) == s) {
S = S.substr(, i) + t + S.substr(i + s.size());
}
}
return S;
}
};
再来看一种稍有不同的解法,之前的两种解法都是直接在S上替换,这里我们新建一个结果res字符串,这里还是使用HashMap来保存映射对,但是稍有不同的是,我们并不是无脑的添加所有的映射对儿,而是先做个check,只要当发现可以查找到源字符串位置的时候,才添加映射对儿,这样就排除了所有不能替换的情况。然后我们遍历原字符串S,对于每个遍历到的位置,我们都到HashMap中查找,如果发现需要替换,我们就把目标字符串提取出来,加入结果res中,注意此时i也需要加上源字符串的长度。若不需要替换,则直接将字符加入结果res中,然后i移动到下一个位置,参见代码如下:
解法三:
class Solution {
public:
string findReplaceString(string S, vector<int>& indexes, vector<string>& sources, vector<string>& targets) {
string res = "";
unordered_map<int, int> m;
for (int i = ; i < indexes.size(); ++i) {
if (S.substr(indexes[i], sources[i].size()) == sources[i]) {
m[indexes[i]] = i;
}
}
for (int i = ; i < S.size();) {
if (m.count(i)) {
res += targets[m[i]];
i += sources[m[i]].size();
} else {
res.push_back(S[i]);
++i;
}
}
return res;
}
};
我们也可以使用STL自带的replace函数来完成替换操作,有点偷懒啊~
解法四:
class Solution {
public:
string findReplaceString(string S, vector<int>& indexes, vector<string>& sources, vector<string>& targets) {
map<int, pair<int, string>, greater<int>> m;
for (int i = ; i < indexes.size(); ++i) {
if (S.substr(indexes[i], sources[i].size()) == sources[i]) {
m[indexes[i]] = {sources[i].size(), targets[i]};
}
}
for (auto a : m) {
S.replace(a.first, a.second.first, a.second.second);
}
return S;
}
};
参考资料:
https://leetcode.com/problems/find-and-replace-in-string/
https://leetcode.com/problems/find-and-replace-in-string/discuss/134758/Java-O(n)-solution
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] Find And Replace in String 在字符串中查找和替换的更多相关文章
- hiho1482出勤记录II(string类字符串中查找字符串,库函数的应用)
string类中有很多好用的函数,这里介绍在string类字符串中查找字符串的函数. string类字符串中查找字符串一般可以用: 1.s.find(s1)函数,从前往后查找与目标字符串匹配的第一个位 ...
- [LeetCode] Reverse Words in a String 翻转字符串中的单词
Given an input string, reverse the string word by word. For example, Given s = "the sky is blue ...
- [LeetCode] Unique Substrings in Wraparound String 封装字符串中的独特子字符串
Consider the string s to be the infinite wraparound string of "abcdefghijklmnopqrstuvwxyz" ...
- [LeetCode] Reverse Vowels of a String 翻转字符串中的元音字母
Write a function that takes a string as input and reverse only the vowels of a string. Example 1:Giv ...
- leetcode——Reverse Words in a String 旋转字符串中单词顺序(AC)
题目例如以下: Given an input string, reverse the string word by word. For example, Given s = "the sky ...
- 将一个字符串中的空格替换成“%20”(C、Python)
将一个字符串中的空格替换成“%20” C语言: /* ----------------------------------- 通过函数调用,传地址来操作字符串 1.先计算出替换后的字符串的长度 2.从 ...
- 实现字符串的查找和替换 分类: c/c++ 2014-10-09 22:33 469人阅读 评论(0) 收藏
在字符串中查找目标字符串并将其替换为指定字符串,返回替换的次数.接口为 int find_str_replace(char *&str,const char *find_str,const c ...
- 《剑指offer面试题4》替换空格——实现函数把字符串中每个空格替换成“%20”
思路: 例如把we are happy这个字符串中所有空格替换成"%20",最直接的做法是从头开始扫苗,遇到空格就替换,并且把空格后面的字符都顺序后移.复杂度O(n^2). 重要思 ...
- sh_17_字符串的查找和替换
sh_17_字符串的查找和替换 hello_str = "hello world" # 1. 判断是否以指定字符串开始 print(hello_str.startswith(&qu ...
随机推荐
- LeetCode第十七题-电话号码的字母组合
Letter Combinations of a Phone Number 问题简介: 给定包含2-9的数字的字符串,返回该数字可能表示的所有可能的字母组合. 下面给出了数字到字母的映射(就像在电话按 ...
- 20175214 《Java程序设计》第9周学习总结
20175214 <Java程序设计>第9周学习总结 本周学习任务总结 1.根据<java2实用教程>和蓝墨云学习视频学习第十一章: 2.尝试将课本重点内容用自己的话复述手打: ...
- webpack 打包报错:One CLI for webpack must be installed. These are recommended choices, delivered as separate packages
webpack 打包报错: One CLI for webpack must be installed. These are recommended choices, delivered as sep ...
- Java数据类型与运算符
Java 基本数据类型 Java 的两大数据类型: 内置数据类型 引用数据类型 内置数据类型 Java语言提供了八种基本类型.六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型. b ...
- vue请求网络图片403错误,图片有占位但是显示不出来解决办法
在index.html 增加一个meta标签 <meta name="referrer" content="no-referrer" />
- 马拉车算法——边界拓展时加限制hdu4513
#include<bits/stdc++.h> using namespace std; #define maxn 500005 int n,p[maxn],s[maxn],s_new[m ...
- 2018-2019-2 网络对抗技术 20165206 Exp6 信息搜集与漏洞扫描
- 2018-2019-2 网络对抗技术 20165206 Exp6 信息搜集与漏洞扫描 - 实验任务 (1)各种搜索技巧的应用 (2)DNS IP注册信息的查询 (3)基本的扫描技术:主机发现.端口 ...
- ansible字符串处理(一)
[root@node-1 test]# ansible-playbook hba_card_check.yml PLAY [compute[0]] ************************** ...
- C++多态及其实现原理
1. 多态的定义:多态含义为一个事物有多种形态.在C ++程序设计中,多态性是指具有不同功能的函数可以用同一个函数名,这样就可以用一个函数名调用不同内容的函数,主要分为静态多态和动态多态: 静态 ...
- [FJWC2018]全排列
题解: 考虑长度为k的时候的贡献 即取出一些元素然后给他们排个顺序然后问你有多少排法 假设排法为ans 那么应该就是$C(n,k)*C(n,k)*(n-k)!*(n-k)!*(n-k+1)*ans$ ...