What I share today are two interview questions for autumn recruitment (from the collection of job-seeking classmates)
The two questions are from Niuke.com and leetcode, the two major question-making websites in China.
The first question (minimum covering substring)
topic statement
Given two strings s and t, it is required to find the shortest continuous substring in s that contains all the characters in t.
Data range: 0≤ ∣S∣≤100000, ∣T∣≤10000, ensure that the s and t strings only contain uppercase and lowercase English letters
Requirements: advanced: space complexity O(n), time complexity O(n)
For example:
S="XDOYEZODEYXNZ"
T="XYZ"
The shortest substring found is "YXNZ".
Note:
If there is no substring containing all the characters in t in s, return an empty string "";
there may be many substrings that meet the condition, but the title guarantees that the shortest substring that meets the condition is unique.
example
enter:
"XDOYEZODEYXNZ","XYZ"return value:
"YXNZ"
Input: "abcAbA","AA" Copy return value: "AbA"
Disintegration of ideas
It is required that all s strings contain t, and the length of the s string is required to be the smallest. We can think of using double pointer + hash to write. The double pointer is controlled in the interval of left---right, and the hash map can directly judge left-- The number of each character of -right is compared in t. If the number of each character is greater than or equal to each character in t, use left++ to shorten the length of the string. If the number of characters in left---right is less than each character in t, it means that it cannot be satisfied Due to the title conditions, right++ is required to expand the length of the string.
Every time the condition in the title is met (the number of each character of t is less than or equal to the string of s), the record takes the minimum value.
code display
#include <unordered_map>
class Solution {
public:
string minWindow(string S, string T) {
string s=S;
string t=T;
unordered_map<char, int>mp1;
unordered_map<char, int>mp2;
vector<pair<int,int>>res;
for(int i=0;i<T.size();i++)
{
mp1[t[i]]++;
}
int left=0;
int right=0;
mp2[s[0]]++;
while(right<s.size())
{
bool flag=false;
for(int i=0;i<t.size();i++) //对t中各字符数量比较
{
char ch=t[i];
if(mp1[ch]>mp2[ch])
{
flag=true;
break;
}
}
if(flag==true)
{
right++;
mp2[s[right]]++;
}
else {
mp2[s[left]]--;
res.push_back({left,right});
left++;
}
}
int index=s.size();
for(int i=0;i<res.size();i++)
{
int l=res[i].second-res[i].first+1;
index=min(index,l);
}
string st;
for(int i=0;i<res.size();i++)
{
int l=res[i].second-res[i].first+1;
if(l==index)
{
st=s.substr(res[i].first,l);
}
}
return st;
}
};
Second problem (and subarrays divisible by k)
topic statement
Given an array of integers nums
and an integer , return the number of (consecutive, non-empty) subarrays whose sum k
is divisible by an integer .k
A subarray is a contiguous portion of an array.
1 <= nums.length <= 3 * 10000
-104 <= nums[i] <= 10000
2 <= k <= 10000
example
Input: nums = [4,5,0,-2,-3,1], k = 5
Output: 7
Explanation: There are 7 subarrays whose sum is divisible by k = 5:
[4, 5, 0 , -2, -3, 1], [5], [5, 0], [5, 0, -2, -3], [0], [0, -2, -3], [-2, -3]
Input: nums = [5], k = 9 Output: 0
problem solving ideas
First of all, I have to remind you that the title here is not very clear, divisible by K means that it can be divisible by K, and the programming expression is x%k=0
The meaning of the question is to find out how many sub-arrays and the remainder of k are 0, and an O(N*N) method can be thought of almost quickly, but beyond the time limit, we can think of calculating each sub-array through the prefix sum The sum, the time complexity is O(N), define arr as the prefix and the array arr[right]-arr[left] is the sum of left---right; require (arr[right]-arr[left])%k ==0, can also be expressed as arr[right]%k==arr[left]%k. So for each arr (prefix and array), the same result after the remainder of k means that the sum of the intervals of the two boundaries can be divisible by k.
If the number of remainder 1 is 1, then the number of divisible by k is 0
If the number of remainder 1 is 2, then the number of divisible by k is 1
If the number of remainder 1 is 3, then the number of divisible by k is 3
We can save the number corresponding to each remainder by hashing each time.
code display
class Solution {
public:
int subarraysDivByK(vector<int>& nums, int k) {
unordered_map<int,int>mp;
long long ans=0;
mp[0]=1;
int arr[nums.size()];
arr[0]=nums[0];
for(int i=1;i<nums.size();i++)
{
arr[i]=arr[i-1]+nums[i];
}
for(int i=0;i<nums.size();i++)
{
int x=(arr[i])%k;
x=(x+k)%k;
ans+=mp[x];
mp[x]++;
}
return ans;
}
};
ps: If the remainder is 0:
The number is 1, then the number divisible by k is 1
The number is 2, then the number divisible by k is 3
So assign mp[0] to 1