文章目录
前言
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<>();
HashMap<String,Integer> need = new HashMap<>();
//把字典中的单词放到map集合当中
for(String word : words){
need.put(word,need.getOrDefault(word,0)+1);
}
int n=s.length();
int sum=words.length;//单词数
int len=words[0].length();//每个单词的长度
for(int i=0;i<n-sum*len+1;i++){ //窗口的起始位置
HashMap<String,Integer> window = new HashMap<>();
//找出sum个单词
int num =0;
while(num<sum){
String word = s.substring(i+num*len,i+(num+1)*len);
//判断该单词是否在need中
if(need.containsKey(word)){ //如果在的话,就把它放进window中
window.put(word,window.getOrDefault(word,0)+1);
if(need.get(word)<window.get(word)) break;
}else
break;
num++;
}
//判断num是否等于字典中的单词数
if(num==sum){
res.add(i);
}
}
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;
}
}