#2207 字符串中最多数目的子字符串 |
前缀和加求和问题(贪心的思想),注意pattern中pattern[0]==pattern[1]这种个情况
class Solution {
public long maximumSubsequenceCount(String text, String pattern) {
int ctf=0,ctl=0;//ctf统计pattern[0]的个数,ctl统计pattern[1]的个数
char[]array=pattern.toCharArray();
char a=array[0],b=array[1];
long ans=0;
char[]t=text.toCharArray();
for(char i:t){
if(i==a) ctf++;
if(i==b){//当i=b时,就有ctf个组合方式。就是对每个b加上当前a的个数
ctl++;//记录b的个数,为了最后比较a的个数和b的个数,添加能产生最大的那个
ans+=ctf;
}
}
return a==b?ans:ans+Math.max(ctf,ctl);
}
}
#1109 航班预订统计 |
首先我想了2分钟感觉可以直接模拟暴力求解,就没往前缀和方面想(的确,脑子里也没有差分数组相关知识!)
class Solution {
public int[] corpFlightBookings(int[][] bookings, int n) {
int[]ans=new int[n];
for(int i=0;i<bookings.length;i++){
int start=bookings[i][0]-1;
int end=bookings[i][1]-1;
int id=bookings[i][2];
for(int j=start;j<=end;j++){ans[j]+=id;}
}
return ans;
}
}
前缀和加差分数组(前后两个变量的差值组成的数组)要搞清差分数组的性质,差分数组其实你在start的地方加上变量一次,后边的因为累加的原因都加上了这个变量,但end+1的地方没有加变量,所以要在end+1的地方减去变量一次!
class Solution {
public int[] corpFlightBookings(int[][] bookings, int n) {
int[]res=new int[n];
for(int[]booking:bookings){
res[booking[0]-1]+=booking[2];//差分数组开头加上变量
if(booking[1]<n){
res[booking[1]]-=booking[2];//end+1要减去这个变量(因为这个变量只加在start到end中)
}
}
for(int i=1;i<n;i++){
res[i]+=res[i-1];
}
return res;
}
}
首先想法是,统计每个位置前后0的个数和1的位数,因为只可能是(‘010’或‘101’)这两种情况。
一开始是想用两个前缀和统计0和1,后来才发现这个建筑类型只有0和1两种类型其实,统计一个0的数量,完全可以通过长度相减知道1的个数(非‘0’即‘1’)代码如下;
class Solution {
public long numberOfWays(String s) {
int n=s.length();
long ways=0L;
int[]prevZero=new int[n];
prevZero[0]=s.charAt(0)=='0'?1:0;
for(int i=1;i<n;i++){
prevZero[i]=prevZero[i-1]+(s.charAt(i)=='0'?1:0);//统计0的前缀和
}
for(int i=1;i<n-1;i++){
if(s.charAt(i)=='0'){
ways+=(i-prevZero[i-1])*(n-1-i-(prevZero[n-1]-prevZero[i]));//第i位置1的个数就是i-0的前缀和
}else{
ways+=prevZero[i-1]*(prevZero[n-1]-prevZero[i]);
}
}
return ways;
}
}
然后看到了评论区一个十分巧妙的方法,其实就是顺序遍历一遍就可以解决的(不要太想复杂了),其实就是两种情况‘010’和‘101’,下边的方法可以用来找任意abc的顺序,代码如下:
class Solution {
public long numberOfWays(String s) {
char[]chars=s.toCharArray();
char[]char1={'0','1','0'};//两种情况
char[]char2={'1','0','1'};
return help(chars,char1)+help(chars,char2);
}
public long help(char[]chars,char[]goal){
long a=0,b=0,c=0;//a统计前边等于目标第一位的个数,b统计当前等于第二位的个数,c也就是一共能形成goal的个数
for(int i=0;i<chars.length;i++){
if(chars[i]==goal[0]) a++;
if(chars[i]==goal[1]) b+=a;//乘法原理
if(chars[i]==goal[2]) c+=b;
}
return c;
}
}
奇偶状态想到异或来进行状态判断,前缀和获取状态量。
class Solution {
public int findTheLongestSubstring(String s) {
int[]pos=new int[1<<5];//5个元音字母可以用5位二进制数来储存他们的状态
Arrays.fill(pos,-1);
pos[0]=0;
int state=0,max=0;
for(int i=0;i<s.length();i++){
char c=s.charAt(i);
if(c=='a'){
state^=(1<<0);
}else if(c=='e'){
state^=(1<<1);
}else if(c=='i'){
state^=(1<<2);
}else if(c=='o'){
state^=(1<<3);
}else if(c=='u'){
state^=(1<<4);
}
if(pos[state]>=0) max=Math.max(max,i+1-pos[state]);
else{
pos[state]=i+1;
}
}
return max;
}
}
#1248 统计「优美子数组」 |
本质是奇数和为k的子数组个数,偶数直接无视掉
class Solution {
public int numberOfSubarrays(int[] nums, int k) {
int n=nums.length;
int[]odd=new int[n+2];
odd[0]=-1;
int cnt=0,ans=0;
for(int i=0;i<n;++i){
if((nums[i]&1)!=0){
odd[++cnt]=i;
}
}
odd[++cnt]=n;
for(int i=1;i+k<=cnt;++i){
ans+=(odd[i]-odd[i-1])*(odd[i+k]-odd[i+k-1]);
}
return ans;
}
}
#528 按权重随机选择 |
前缀和+二分查找。
滑动窗口简单问题。
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int i=0,sum=0,len=0;
for(int j=0;j<nums.length;j++){
sum+=nums[j];
while(sum>=target){
len=len==0?j-i+1:Math.min(len,j-i+1);
sum-=nums[i++];
}
}
return len;
}
}
这周状态很不好,中途因为自己线性代数方面知识并不好,做了好几天矩阵题都很吃劲,所以这周也就放了前半周做的题,周五从早上5.起来就开始自暴自弃打游戏打到晚上11.,晚上在母亲的劝说下觉得自己路还很长不能摆烂,但是星期六到今天头巨痛,打游戏注意力高度集中也不出去走动导致了精神有点恍惚,一直到今天下午都没缓过来,希望我未来打游戏不是去把它当成逃避摆烂的手段,而是真正的娱乐自己。