文章目录
- 前言
- 一、字符串的排列(力扣567)【滑动窗口】
- 二、找到字符串中所有字母异位词(力扣438)【滑动窗口】
- 三、串联所有单词的子串(力扣30)【滑动窗口】****【hard】
- 每日一题day55:合并相似的物品(力扣2263)
- 每日一题day56:矩阵中的局部最大值(力扣2373)
前言
1、字符串的排列
2、找到字符串中所有字母异位词
3、串联所有单词的子串
4、每日一题
5、每日一题
一、字符串的排列(力扣567)【滑动窗口】
给你两个字符串 s1 和 s2 ,写一个函数来判断 s2 是否包含 s1 的排列。如果是,返回 true ;否则,返回 false 。
换句话说,s1 的排列之一是 s2 的 子串 。
class Solution {
public boolean checkInclusion(String s1, String s2) {
int left=0;
int right=0;
int[] need = new int[128];
for(int i=0;i<s1.length();i++){
need[s1.charAt(i)]++;
}
int count = s1.length();
int length = s1.length();
//滑动窗口
while(right<s2.length()){
//判断是否满足条件:
if(need[s2.charAt(right)]>0){
count--;
}
need[s2.charAt(right)]--;
if(count==0){
//缩小窗口左边界
while(left<right && need[s2.charAt(left)]<0){
//说明是可以缩小窗口的
need[s2.charAt(left)]++;
left++;
}
//不能再缩小的时候 判断一下length
if(right-left+1==length){
return true;
}
need[s2.charAt(left)]++;
left++;
count++;
}
right++;
}
return false;
}
}
二、找到字符串中所有字母异位词(力扣438)【滑动窗口】
给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。
class Solution {
public List<Integer> findAnagrams(String s, String p) {
int i=0;
int j=0;
//用来存放需要的元素
int[] need = new int[128];
for(int c=0;c<p.length();c++){
need[p.charAt(c)]++;
}
int count = p.length();
int length = p.length();
List<Integer> res = new ArrayList<>();
while(j<s.length()){
//判断是否满足条件
if(need[s.charAt(j)]>0){
count--;
}
need[s.charAt(j)]--; //把右边字符加入窗口
while(count==0){
while(i<j && need[s.charAt(i)]<0)//压缩左窗口
{
need[s.charAt(i)]++;
i++;
}
if(j-i+1==length){
//记录结果
res.add(i);
}
need[s.charAt(i)]++;
i++;
count++;
}
j++;
}
return res;
}
}
三、串联所有单词的子串(力扣30)【滑动窗口】****【hard】
给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同。
s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。
例如,如果 words = [“ab”,“cd”,“ef”], 那么 “abcdef”, “abefcd”,“cdabef”, “cdefab”,“efabcd”, 和 “efcdab” 都是串联子串。 “acdbef” 不是串联子串,因为他不是任何 words 排列的连接。
返回所有串联字串在 s 中的开始索引。你可以以 任意顺序 返回答案。
class Solution {
public List<Integer> findSubstring(String s, String[] words) {
List<Integer> res = new ArrayList<>();
// 所有单词的个数
int num = words.length;
// 每个单词的长度(是相同的)
int wordLen = words[0].length();
// 字符串长度
int stringLen = s.length();
for (int i = 0; i < wordLen; i++) {
// 遍历的长度超过了整个字符串的长度,退出循环
if (i + num * wordLen > stringLen) {
break;
}
// differ表示窗口中的单词频次和words中的单词频次之差
Map<String, Integer> differ = new HashMap<>();
// 初始化窗口,窗口长度为num * wordLen,依次计算窗口里每个切分的单词的频次
for (int j = 0; j < num; j++) {
String word = s.substring(i + j * wordLen, i + (j + 1) * wordLen);
differ.put(word, differ.getOrDefault(word, 0) + 1);
}
// 遍历words中的word,对窗口里每个单词计算差值
for (String word : words) {
differ.put(word, differ.getOrDefault(word, 0) - 1);
// 差值为0时,移除掉这个word
if (differ.get(word) == 0) {
differ.remove(word);
}
}
// 开始滑动窗口
for (int start = i; start < stringLen - num * wordLen + 1; start += wordLen) {
if (start != i) {
// 右边的单词滑进来
String word = s.substring(start + (num - 1) * wordLen, start + num * wordLen);
differ.put(word, differ.getOrDefault(word, 0) + 1);
if (differ.get(word) == 0) {
differ.remove(word);
}
// 左边的单词滑出去
word = s.substring(start - wordLen, start);
differ.put(word, differ.getOrDefault(word, 0) - 1);
if (differ.get(word) == 0) {
differ.remove(word);
}
word = s.substring(start - wordLen, start);
}
// 窗口匹配的单词数等于words中对应的单词数
if (differ.isEmpty()) {
res.add(start);
}
}
}
return res;
}
}
每日一题day55:合并相似的物品(力扣2263)
给你两个二维整数数组 items1 和 items2 ,表示两个物品集合。每个数组 items 有以下特质:
items[i] = [valuei, weighti] 其中 valuei 表示第 i 件物品的 价值 ,weighti 表示第 i 件物品的 重量 。
items 中每件物品的价值都是 唯一的 。
请你返回一个二维数组 ret,其中 ret[i] = [valuei, weighti], weighti 是所有价值为 valuei 物品的 重量之和 。
注意:ret 应该按价值 升序 排序后返回。
集合的使用
class Solution {
public List<List<Integer>> mergeSimilarItems(int[][] items1, int[][] items2) {
Map<Integer,Integer> map = new HashMap<>();
for(int[] v:items1){
map.put(v[0],map.getOrDefault(v[0],0)+v[1]);
}
for(int[] v:items2){
map.put(v[0],map.getOrDefault(v[0],0)+v[1]);
}
List<List<Integer>> res = new ArrayList<>();
//获取对象的集合
Set<Map.Entry<Integer,Integer>> entries = map.entrySet();
for(Map.Entry<Integer,Integer> entry : entries){
int k = entry.getKey();
int v = entry.getValue();
List<Integer> pair = new ArrayList<>();
pair.add(k);
pair.add(v);
res.add(pair);
}
Collections.sort(res,(a,b)->a.get(0)-b.get(0));
return res;
}
}
每日一题day56:矩阵中的局部最大值(力扣2373)
给你一个大小为 n x n 的整数矩阵 grid 。
生成一个大小为 (n - 2) x (n - 2) 的整数矩阵 maxLocal ,并满足:
maxLocal[i][j] 等于 grid 中以 i + 1 行和 j + 1 列为中心的 3 x 3 矩阵中的 最大值 。
换句话说,我们希望找出 grid 中每个 3 x 3 矩阵中的最大值。
返回生成的矩阵。
class Solution {
public int[][] largestLocal(int[][] grid) {
int h = grid.length; //高度
int w = grid[0].length; //宽度
int[][] maxLocal = new int[h-2][w-2];
for(int i=0;i<h-2;i++){
for(int j=0;j<w-2;j++){
//获取i j位置的最大值
maxLocal[i][j] = getMax(grid,i,j);
}
}
return maxLocal;
}
public int getMax(int[][] grid,int i,int j){
int max = Integer.MIN_VALUE;
for(int x=i;x<i+3;x++){
for(int y=j;y<j+3;y++){
max = Math.max(max,grid[x][y]);
}
}
return max;
}
}