面试题48:最长不含重复字符的子字符串
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。假设字符串中只包含从’a’到’z’的字符。
用f(i)表示以i位置字符结尾的最长不含重复字符的子字符串的长度,则所求的就是i从0~n-1中最大的一个f(i)。
在遍历数组时,记录每个字符最后一次出现的位置。
①当i号字符之前没有出现过时,f(i)=f(i-1)+1。
②当之前出现过,且不在f(i-1)指示的子串里出现时,即出现位置到i位置的距离 d>f(i-1),f(i)=f(i-1)+1。
③当之前出现过,且就在f(i-1)指示的子串中时,即d<=f(i-1),这时候f(i)=d。
#include<bits/stdc++.h>
using namespace std;
//输入数组的string常引用,输出满足条件的最大的f(i)的值
int longestSubstringWithoutDuplication(const string& str) {
int curLength = 0;//当前找到的长度,即当前的f(i)
int maxLength = 0;//到当前为止,最大的f(i)
int* position = new int[26];//存26个字母"上一次出现的位置下标"
for(int i = 0; i < 26; ++i)
position[i] = -1;//初始化为-1,表示"之前没出现过"
for(int i = 0; i < str.length(); ++i) {//遍历字符串
int prevIndex = position[str[i] - 'a'];//该位置字符上一次出现的位置下标
if(prevIndex < 0 || i - prevIndex > curLength)//情况①或②
++curLength;//f(i)=f(i-1)+1
//反复出现这种情况时,curLength是单调增加的
//所以不需要担心漏记录了中间出现的某些比两边大的长度
//不可能出现,因为是单调增加的(单调减少就不行)
//这时不对maxLength做无用的更新,因为更新了也会被后面的更新覆盖掉
else {//情况③
if(curLength > maxLength)//更新最大f(i)
maxLength = curLength;
curLength = i - prevIndex;//f(i)=d
}
position[str[i] - 'a'] = i;
}
//最终更新一次最大f(i),因为可能以情况①或者②结束
if(curLength > maxLength)
maxLength = curLength;
delete[] position;
return maxLength;
}
int main() {
string ok="abcacfrar";
printf("%d\n",longestSubstringWithoutDuplication(ok));//4
return 0;
}
面试题49:丑数
我们把只包含因子2、3和5的数称作丑数(Ugly Number)。求按从小到大的顺序的第1500个丑数。例如6、8都是丑数,但14不是,因为它包含因子7。习惯上我们把1当做第一个丑数。
传统解法是把输入的数字不断除以2、3、5,最后得到1就是丑数。用空间可以换时间,将已经得到的丑数从小到大打表;如需计算,表中下一个丑数就是:
m
i
n
(
2
×
T
2
,
3
×
T
3
,
5
×
T
5
)
min(2 \times T_2,3 \times T_3,5 \times T_5)
min(2×T2,3×T3,5×T5)
其中
T
k
T_k
Tk表示当前丑数表中的某个数,这个数乘以k后大于丑数表中最大数,且是满足该条件的所有数中最小的一个。
#include<bits/stdc++.h>
using namespace std;
//三个数找最小
int Min(int number1, int number2, int number3) {
int min = (number1 < number2) ? number1 : number2;//min(n1,n2)
min = (min < number3) ? min : number3;//min(min(n1,n2),n3)
return min;
}
//输入要寻找的丑数在顺序丑数表中是第几个,计算并返回该丑数
int GetUglyNumber_Solution(int index) {
if(index <= 0)//输入合法性
return 0;
int *pUglyNumbers = new int[index];//第index个丑数下标为index-1
pUglyNumbers[0] = 1;//1是最小的丑数
int nextUglyIndex = 1;//下一个要找的丑数在丑数表中下标
//初始化T2,T3,T5的地址,都是&pUglyNumbers[0]
int *pMultiply2 = pUglyNumbers;
int *pMultiply3 = pUglyNumbers;
int *pMultiply5 = pUglyNumbers;
//一直找,找完下标为index-1的,当nextUglyIndex=index时停止
while(nextUglyIndex < index) {
//min(T2,T3,T5)
int min = Min(*pMultiply2 * 2, *pMultiply3 * 3, *pMultiply5 * 5);
pUglyNumbers[nextUglyIndex] = min;//就是下一个丑数
//更新下次T2(的地址):T2*2要刚好大过当前表中最大丑数
while(*pMultiply2 * 2 <= pUglyNumbers[nextUglyIndex])
++pMultiply2;
//更新下次T3(的地址):T3*3要刚好大过当前表中最大丑数
while(*pMultiply3 * 3 <= pUglyNumbers[nextUglyIndex])
++pMultiply3;
//更新下次T5(的地址):T5*5要刚好大过当前表中最大丑数
while(*pMultiply5 * 5 <= pUglyNumbers[nextUglyIndex])
++pMultiply5;
++nextUglyIndex;//下次循环要找的丑数下标+1
}
//要找的丑数就是pUglyNumbers[index-1]
int ugly = pUglyNumbers[nextUglyIndex - 1];
delete[] pUglyNumbers;
return ugly;
}
int main() {
cout<<GetUglyNumber_Solution(1500)<<endl;//859963392
return 0;
}