(1) Substring with Concatenation of All Words
事实上求解的是S中包含L中所有单词的index,换句话说,假设L中单词长度为wordLen,总长为wordLen*len,从index到距离为总长的这一段包含L中所有的单词。
假设L中的单位长度为n,依次从S中取长度为n的子串,如果在L中,就记下来。需要借助hash或map,如果整个L都匹配完了,就算是一个concatenation;当匹配错误的时候,S右移一个位置。[1]
class Solution {
public:
vector<int> findSubstring(string S, vector<string> &L) {
vector<int> ret;
int n=L[0].size();
if(L.size()*n>S.size())
return ret;
unordered_map<string,int> hashtable;
for(int i=0;i<L.size();i++)
hashtable[L[i]]++;
int i=0;
unordered_map<string,int> tmp;
for(int i=0;i<=S.size()-L.size()*n;i++)
{
tmp.clear();
bool flag=true;
for(int j=i;j<i+L.size()*n;j+=n)
{
string str=S.substr(j,n);
if(hashtable.count(str)==0)
{
flag=false;
break;
}
tmp[str]++;
if(tmp[str]>hashtable[str])
{
flag=false;
break;
}
}
if(flag)
ret.push_back(i);
}
return ret;
}
};
还有一种线性时间复杂度的滑动窗口方法[2]。
(2) Median of Two Sorted Arrays
该方法的核心是将原问题转变成一个寻找第k小数的问题(假设两个原序列升序排列),这样中位数实际上是第(m+n)/2小的数。所以只要解决了第k小数的问题,原问题也得以解决。首先假设数组A和B的元素个数都大于k/2,我们比较A[k/2-1]和B[k/2-1]两个元素,这两个元素分别表示A的第k/2小的元素和B的第k/2小的元素。这两个元素比较共有三种情况:>、<和=。如果A[k/2-1]<B[k/2-1],这表示A[0]到A[k/2-1]的元素都在A和B合并之后的前k小的元素中。[3]
class Solution {
private:
double recursive(int A[], int m, int B[], int n,int k) {
if(m>n)
return recursive(B,n,A,m,k);
if(m==0)
return B[k-1];
if(k==1)
return min(A[0],B[0]);
int lenA=min(m,k/2),lenB=k-lenA;
if(A[lenA-1]<B[lenB-1])
return recursive(A+lenA,m-lenA,B,n,k-lenA);
else if(A[lenA-1]>B[lenB-1])
return recursive(A,m,B+lenB,n-lenB,k-lenB);
else
return A[lenA-1];
}
public:
double findMedianSortedArrays(int A[], int m, int B[], int n) {
int len=m+n;
if(len%2==1)
return recursive(A,m,B,n,len/2+1);
else
return (recursive(A,m,B,n,len/2)+recursive(A,m,B,n,len/2+1))/2;
}
};
任意一个整数可以表达为num=a0*2^0+a1*2^1+a2*2^2+...+an*2^n (ai=0 or 1 , 0<=i<=n),所以a除以b的结果也可以用这个式子表达。基于以上这个公式以及左移一位相当于乘以2,我们先让除数左移直到大于被除数之前得到一个最大的基。然后接下来我们每次尝试减去这个基,如果可以则结果增加加2^k,然后基继续右移迭代,直到基为0为止。因为这个方法的迭代次数是按2的幂知道超过结果,所以时间复杂度为O(logn)。[4]
代码参考于[5],注意用位运算和long long,否则int会溢出:
class Solution {
public:
int divide(int dividend, int divisor) {
long long a=abs((long long)dividend);
long long b=abs((long long)divisor);
long long ret=0;
bool flag=(dividend>0)^(divisor>0);
while(a>=b)
{
long long t=b;
for(int i=1;a>=t;t<<=1,i<<=1)
{
a-=t;
ret+=i;
}
}
return flag ? -ret :ret;
}
};
参考:
[1] http://blog.csdn.net/ojshilu/article/details/22212703
[2] http://blog.csdn.net/linhuanmars/article/details/20342851
[3] http://blog.csdn.net/yutianzuijin/article/details/11499917
[4] http://blog.csdn.net/linhuanmars/article/details/20024907
[5] http://blog.csdn.net/kenden23/article/details/16986763