【笔试题】模拟笔试题

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

猜你喜欢

转载自blog.csdn.net/wenqiang1208/article/details/77340326