题目1
请你实现一个简单的字符串替换函数,原串中需要替换的占位符为“%s”。请按照参数列表的顺序替换占位符。弱参数列表的字符大于占位符个数,则将剩下的参数字符添加到字符串的结尾。
测试用例:”A%sC%sE” 7,{‘B’,’D’,’F’}
返回: “ABCDEF”
遍历字符串,如果遇到%s,则添加参数里面的值,如果没有遇到添加字符串中的值。
string FormatString(const string& str, int n, const vector<char>& arg, int m)
{
// 预开空间,避免增容,提高效率
string formatStr;
formatStr.reserve(str.size());
size_t pos = 0;
//遍历字符串
for (size_t i = 0; i < n; ++i)
{
if (str[i] == '%' && i + 1 < n && str[i + 1] == 's')
{
assert(pos < m);
formatStr.push_back(arg[pos++]);
++i;
}
else
{
formatStr.push_back(str[i]);
}
}
while (pos < m)
{
formatStr.push_back(arg[pos++]);
}
return formatStr;
}
void TestFormatString()
{
string str = "A%sC%sE";
vector<char> arg;
arg.push_back('B');
arg.push_back('D');
arg.push_back('F');
string formatStr = FormatString(str, 7, arg, 3);
cout << formatStr << endl;
formatStr = FormatString(str, 7, arg, 2);
cout << formatStr << endl;
}
题目2
给定两个有序数组 arr1和arr2,再给定一个整数k,返回两个数组的所有数中的第k小的数,要求:如果arr1的长度为N,arr2的长度为, 时间复杂度要求为O(log(min(M,N)))
分析:两个有序数组,找第k小的数。并且时间复杂要求小,所以不能常规的遍历方法查找。
可以范围查找,在arr1中取range1 = min(kth/2, len1),
arr2中取范围 range2 = kth - range1
这样就取了k个数 arr1[0,range1) + arr2[0,range2) 是两个数组的前k个数。
如果arr1[range1 -1] == arr2[range 2-1],表明这个数就是第k个数。
如果arr1[range1-1] < arr2[range2-1],则排除arr1[0,range1)这一部分,然后就排除了range1个数。然后再剩余的数中找前k-range1个数。
如果 arr1[range1-1] > arr2[range2-1],则排除arr2[0,range2)这一部分,然后就排除了range2个数。然后再剩余的数中找前k-range2个数。
int FindKthNum(int* arr1, int len1, int* arr2, int len2, int kth)
{
assert(kth >= 0 && len1 + len2 >= kth);
// 保证arr1是数据少的那一个
if (len1 > len2)
return FindKthNum(arr2, len2, arr1, len1, kth);
if (len1 == 0)
return arr2[kth - 1];
if (kth == 1)
return min(arr1[0], arr2[0]);
int range1 = min(kth / 2, len1), range2 = kth - range1;
// arr1[0,range1) + arr2[0,range2) 是两个数组的前k个数
// 1.arr1[range1-1] == arr2[range2-1],则这个两个数其中一个就是第k个
// 2.arr1[range1-1] < arr2[range2-1],则排除arr1[0,range1)这一部分
// 3.arr1[range1-1] > arr2[range2-1],则排除arr2[0,range2)这一部分
if (arr1[range1 - 1] == arr2[range2 - 1])
{
return arr1[range1 - 1];
}
else if (arr1[range1 - 1] < arr2[range2 - 1])
{
return FindKthNum(arr1 + range1, len1 - range1, arr2, len2, kth - range1);
}
else //(arr1[range1-1] > arr2[range2-1])
{
return FindKthNum(arr1, len1, arr2 + range2, len2 - range2, kth - range2);
}
}
void TestFindKthNum()
{
int a1[5] = { 1, 2, 3, 4, 5 };
int a2[3] = { 3, 4, 5 };
vector<int> arr1(a1, a1 + 5);
vector<int> arr2(a2, a2 + 3);
cout << FindKthNum(a1, 5, a2, 3, 1) << endl;
int a11[3] = { 1, 2, 3 };
int a22[4] = { 3, 4, 5, 6 };
vector<int> arr11(a11, a11 + 3);
vector<int> arr22(a22, a22 + 4);
cout << FindKthNum(a11, 3, a22, 4, 4) << endl;
}
题目3
春节期间小明使用微信收到很多个红包,非常开心。在查看领取红包记录时发现,某个红包金额出现的次数超过了红包总数的一半。请帮小明查找该红包金额。要求时间复杂度为O(n)
分析:就是给定一个数组,在数组中出现次数超过一半的数字,没找到返回0。且时间复杂度为O(n)。
有两种方法,第1种就是给定两个变量,一个记录value值,一个记录count次数,因为某个值出现次数超过一半。
方法2:就是借助哈希表保存每个数字出现的次数。
还可以借助鸽巢排序。
题目4
根据unix时间戳计算时间,不分大小月,每月30天,每年按360天计算,开始时间为1970/01/01 00:00:00 输入秒数,显示时间。
举例:输入10,输出1970/01/01 00:00:10
输入12345678 输出 1970/05/23 21:21:18
方法1:考虑使用计数思想,秒合法了,则算出了最终时间
string CalculationDate(long long second)
{
int year = 1970, month = 1, day = 1;
int hour = 0, minute = 0;
// 考虑使用计数思想,秒合法了,则算出了最终时间
while (second > 60)
{
second -= 60;
minute += 1;
if (minute == 60)
{
minute = 0;
hour += 1;
if (hour == 24)
{
hour = 0;
day += 1;
if (day == 31)
{
day = 1;
month += 1;
if (month == 13)
{
month = 1;
year += 1;
}
}
}
}
}
char buff[] = "1970/01/01 00:00:10";
sprintf(buff, "%d/%02d/%02d %02d:%02d:%02d", year, month, day, hour, minute, second);
return buff;
}
方法2:考虑直接去整的思想
string CalculationDate_OP(long long second)
{
int year = 1970, month = 1, day = 1;
int hour = 0, minute = 0;
// 考虑直接去整的思想
long long minuteSecond = 60;
long long hourSecond = 60 * minuteSecond;
long long daySecond = 24 * hourSecond;
long long monthSecond = 30 * daySecond;
long long yearSecond = 12 * monthSecond;
if (second > yearSecond)
{
int x = second / yearSecond;
year += x;
second -= x*yearSecond;
}
if (second > monthSecond)
{
int x = second / monthSecond;
month += x;
second -= x*monthSecond;
}
if (second > daySecond)
{
int x = second / daySecond;
day += x;
second -= x*daySecond;
}
if (second > hourSecond)
{
int x = second / hourSecond;
hour += x;
second -= x*hourSecond;
}
if (second > minuteSecond)
{
int x = second / minuteSecond;
minute += x;
second -= x*minuteSecond;
}
char buff[] = "1970/01/01 00:00:10";
sprintf(buff, "%d/%02d/%02d %02d:%02d:%02d", year, month, day, hour, minute, sec
ond);
return buff;
}