[LeetCode] Permutation in String 字符串中的全排列
Given two strings s1 and s2, write a function to return true if s2 contains the permutation of s1. In other words, one of the first string's permutations is the substring of the second string.
Example 1:
Input:s1 = "ab" s2 = "eidbaooo"
Output:True
Explanation: s2 contains one permutation of s1 ("ba").
Example 2:
Input:s1= "ab" s2 = "eidboaoo"
Output: False
Note:
- The input strings only contain lower case letters.
- The length of both given strings is in range [1, 10,000].
这道题给了两个字符串s1和s2,问我们s1的全排列的字符串任意一个是否为s2的字串。虽然题目中有全排列的关键字,但是跟之前的全排列的题目的解法并不一样,如果受思维定势影响比较深的话,很容易遍历s1所有全排列的情况,然后检测其是否为s2的子串,这种解法是非常不高效的,估计OJ不会答应。 这道题的正确做法应该是使用滑动窗口Sliding Window的思想来做,可以使用两个哈希表来做,或者是使用一个哈希表配上双指针来做。我们先来看使用两个哈希表来做的情况,我们先来分别统计s1和s2中前n1个字符串中各个字符出现的次数,其中n1为字符串s1的长度,这样如果二者字符出现次数的情况完全相同,说明s1和s2中前n1的字符互为全排列关系,那么符合题意了,直接返回true。如果不是的话,那么我们遍历s2之后的字符,对于遍历到的字符,对应的次数加1,由于窗口的大小限定为了n1,所以每在窗口右侧加一个新字符的同时就要在窗口左侧去掉一个字符,每次都比较一下两个哈希表的情况,如果相等,说明存在,参见代码如下:
解法一:
class Solution {
public:
bool checkInclusion(string s1, string s2) {
int n1 = s1.size(), n2 = s2.size();
vector<int> m1(), m2();
for (int i = ; i < n1; ++i) {
++m1[s1[i]]; ++m2[s2[i]];
}
if (m1 == m2) return true;
for (int i = n1; i < n2; ++i) {
++m2[s2[i]];
--m2[s2[i - n1]];
if (m1 == m2) return true;
}
return false;
}
};
下面这种解法是利用一个哈希表加上双指针,我们还是先统计s1中字符的出现次数,然后遍历s2中的字符,对于每个遍历到的字符,我们在哈希表中对应的字符次数减1,如果次数次数小于0了,说明该字符在s1中不曾出现,或是出现的次数超过了s1中的对应的字符出现次数,那么我们此时移动滑动窗口的左边界,对于移除的字符串,哈希表中对应的次数要加1,如果此时次数不为0,说明该字符不在s1中,继续向右移,直到更新后的次数为0停止,此时到达的字符是在s1中的。如果次数大于等于0了,我们看此时窗口大小是否为s1的长度,若二者相等,由于此时窗口中的字符都是在s1中存在的字符,而且对应的次数都为0了,说明窗口中的字符串和s1互为全排列,返回true即可,参见代码如下:
解法二:
class Solution {
public:
bool checkInclusion(string s1, string s2) {
int n1 = s1.size(), n2 = s2.size(), left = ;
vector<int> m();
for (char c : s1) ++m[c];
for (int right = ; right < n2; ++right) {
if (--m[s2[right]] < ) {
while (++m[s2[left++]] != ) {}
} else if (right - left + == n1) return true;
}
return n1 == ;
}
};
下面这种解法也是用一个哈希表外加双指针来做的,跟上面的解法思路大体相同,写法有些不同,不变的还是统计s1中字符出现的次数,不一样的是我们用一个变量cnt来表示还需要匹配的s1中的字符的个数,初始化为s1的长度,然后遍历s2中的字符,如果该字符在哈希表中存在,说明匹配上了,cnt自减1,哈希表中的次数也应该自减1,然后如果cnt减为0了,说明s1的字符都匹配上了,如果此时窗口的大小正好为s1的长度,那么说明找到了s1的全排列,返回true,否则说明窗口过大,里面有一些非s1中的字符,我们将左边界右移,同时将移除的字符串在哈希表中的次数自增1,如果增加后的次数大于0了,说明该字符是s1中的字符,我们将其移除了,那么cnt就要自增1,参见代码如下:
解法三:
class Solution {
public:
bool checkInclusion(string s1, string s2) {
int n1 = s1.size(), n2 = s2.size(), cnt = n1, left = ;
vector<int> m();
for (char c : s1) ++m[c];
for (int right = ; right < n2; ++right) {
if (m[s2[right]]-- > ) --cnt;
while (cnt == ) {
if (right - left + == n1) return true;
if (++m[s2[left++]] > ) ++cnt;
}
}
return false;
}
};
类似题目:
参考资料:
https://discuss.leetcode.com/topic/87856/sliding-window-o-n-c
https://discuss.leetcode.com/topic/87845/java-solution-sliding-window
https://discuss.leetcode.com/topic/87861/c-java-clean-code-with-explanation
https://discuss.leetcode.com/topic/87884/8-lines-slide-window-solution-in-java
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] Permutation in String 字符串中的全排列的更多相关文章
- [LeetCode] 567. Permutation in String 字符串中的全排列
Given two strings s1 and s2, write a function to return true if s2 contains the permutation of s1. I ...
- String 字符串中含有 Unicode 编码时,转为UTF-8
1.单纯的Unicode 转码 String a = "\u53ef\u4ee5\u6ce8\u518c"; a = new String(a.getBytes("UTF ...
- 将string字符串中的换行符进行替换
/** * 方法名称:replaceBlank * 方法描述: 将string字符串中的换行符进行替换为"" * */ public static String replaceBl ...
- [LeetCode] Add Bold Tag in String 字符串中增添加粗标签
Given a string s and a list of strings dict, you need to add a closed pair of bold tag <b> and ...
- LeetCode 557:反转字符串中的单词 III Reverse Words in a String III
公众号:爱写bug(ID:icodebugs) 给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序. Given a string, you need to reve ...
- 434 Number of Segments in a String 字符串中的单词数
统计字符串中的单词个数,这里的单词指的是连续的非空字符.请注意,你可以假定字符串里不包括任何不可打印的字符.示例:输入: "Hello, my name is John"输出: 5 ...
- [CareerCup] 1.1 Unique Characters of a String 字符串中不同的字符
1.1 Implement an algorithm to determine if a string has all unique characters. What if you cannot us ...
- String:(字符串)中常用的方法
package stringyiwen; //字符串中常用的方法public class StringTest03 { public static void main(String[] args) { ...
- Leetcode434.Number of Segments in a String字符串中的单词数
统计字符串中的单词个数,这里的单词指的是连续的不是空格的字符. 请注意,你可以假定字符串里不包括任何不可打印的字符. 示例: 输入: "Hello, my name is John" ...
随机推荐
- Matlab绘图基础——用print函数保存图片(Print figure or save to file)
print(figure_handle,'formats','-rnumber','filename') %将图形保存为png格式,分辨率为number的(默认为72),最好指定的分辨率大一点,否则 ...
- poj 3696 The Luckiest Number
The Luckiest Number 题目大意:给你一个int范围内的正整数n,求这样的最小的x,使得:连续的x个8可以被n整除. 注释:如果无解输出0.poj多组数据,第i组数据前面加上Case ...
- 生产者/消费者问题的多种Java实现方式
实质上,很多后台服务程序并发控制的基本原理都可以归纳为生产者/消费者模式,而这是恰恰是在本科操作系统课堂上老师反复讲解,而我们却视而不见不以为然的.在博文<一种面向作业流(工作流)的轻量级可复用 ...
- SpringBoot12 QueryDSL01之QueryDSL介绍、springBoot项目中集成QueryDSL
1 QueryDSL介绍 1.1 背景 QueryDSL的诞生解决了HQL查询类型安全方面的缺陷:HQL查询的扩展需要用字符串拼接的方式进行,这往往会导致代码的阅读困难:通过字符串对域类型和属性的不安 ...
- Oracle修改字段类型方法小技巧
有一个表名为tb,字段段名为name,数据类型nchar(20). 1.假设字段数据为空,则不管改为什么字段类型,可以直接执行:alter table tb modify (name nvarchar ...
- CSS3 box-shadow 属性
定义和用法box-shadow 属性向框添加一个或多个阴影. 默认值: none继承性: no版本: CSS3JavaScript 语法: object.style.boxShadow="1 ...
- Linux安装java环境教程
前言: 本教程基于jdk 1.8,但是此教程适用于jdk1.7等版本. 教程正文: 1.1. 登录Oracle官网下载jdk1.8安装包(gz结尾) 这里可以用"wget + 下载地址&qu ...
- C#简单入门
公司给的一个小的practice C# vs2017 Stage 1 (cmd)1. Parse the dll (reflection)2. Write all the public methods ...
- Python变量赋值的秘密
在Python中,我们令一个变量等于另外一个变量时,并不是把值传递给它,而是直接把指向的地址更改了.我们想要查看一个变量在内存中的地址,可以通过id(变量) 来查看.我们通过一个小例子来看看这个有趣的 ...
- 搭建一个web服务下载HDFS的文件
需求描述 为了能方便快速的获取HDFS中的文件,简单的搭建一个web服务提供下载很方便快速,而且在web服务器端不留临时文件,只做stream中转,效率相当高! 使用的框架是SpringMVC+HDF ...