【笔试题】模拟笔试题

来源:互联网 发布:南风知我意 七微 编辑:程序博客网 时间:2024/05/22 03:38

题目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;}