C++重学日记 2022年8月3日

119 阅读3分钟

第一题

image.png

分析:整数序列 A中,如果有m个数相等,m>n/2,则这个数就是主元。

解一

1)找出数组里面的数量最多的数,看他是不是数量大于数组长度的一半。 用map来记录数组元素的出现次数。

最后判断 最多的元素个数是否大于n/2

2)代码

#include<iostream>
#include "map"

using namespace std;

int findMainElement(int a[], int n);

int main() {
    int a[] = {1, 2, 3, 2, 2, 4, 2, 3};
    int b[] = {1, 2, 3, 2, 2, 4, 2};
    cout << findMainElement(a, 8) << endl;
    cout << findMainElement(b, 7) << endl;
}

int findMainElement(int a[], int n) {
    int now_most = a[0];
    int now_most_count = 1;
    map<int, int> count_map;
    for (int i = 0; i < n; ++i) {
        int now_count = 0;
        if (count_map.count(a[i]) == 0) {
            now_count = 1;
            count_map.insert(pair<int, int>(a[i], now_count));
        } else {
            now_count = count_map.at(a[i]) + 1;
            count_map[a[i]] = now_count;
        }
        if (now_count > now_most_count) {
            now_most = a[i];
            now_most_count = now_count;
        }
    }
    if (now_most_count > n / 2) {
        return now_most;
    } else {
        return -1;
    }
}

输出结果:-12

3)时间复杂度:O(n),空间复杂度:O(n)

解二

1)不用map,利用增减count数值,两个循环,可减少空间复杂度

设置两个变量num,count。

count初始为1,将第一个数存到num,遍历数组,下一个数与当前数相同,则count+1,否则count-1。直到count=0,就换成下一个数,直到遍历到最后还一个为止。

判断num是不是主元,遍历统计num出现的次数,如果大于n/2,num为主元,如果小于n/2,则没有主元。

ps:count降到0的时候,说明当前数在已遍历的数组元素中不是主元了,并且在已遍历的数组元素中,其他的也不是,所以就要在后续数组元素中 换成其他的数重新计数。

未命名绘图.png

2)代码

#include<iostream>

using namespace std;

int findMainElement(int a[], int n);

int main() {
    int a[] = {1, 2, 3, 2, 2, 4, 2, 3};
    int b[] = {1, 2, 3, 2, 2, 4, 2};
    cout << findMainElement(a, 8) << endl;
    cout << findMainElement(b, 7) << endl;
}

int findMainElement(int a[], int n) {
    int num = a[0];
    int count = 0;
    for (int i = 0; i < n; ++i) {
        if (count == 0) {
            num = a[i];
            count++;
        } else {
            num == a[i] ? count++ : count--;
        }
    }
    if (count == 0) {
        return -1;
    } else {
        int c = 0;
        for (int i = 0; i < n; ++i) {
            if (num == a[i]) {
                c++;
            }
        }
        if (c > n / 2) {
            return num;
        } else {
            return -1;
        }
    }
}

输出结果:-12

3)时间复杂度:O(n),空间复杂度:O(1)

第二题

image.png

分析:既然要求时间上高效,则要用空间换时间

1)如果这个n个数是含1~n的不重复序列,则不含有的最小正整数为n+1

否则,这个最小正整数,就小于n

假设输入一个A数组

我们声明一个B数组,长度为n,且初始化都为0

遍历A,假设A中某个值为m,就让B[m-1]=1,小于等于0,或者大于n都不处理,直到A遍历完为止

再遍历B,第一个值为0的下标为s,则返回s+1,如果全都为1,则返回n+1

2)代码

#include<iostream>
#include "map"

using namespace std;

int findMinPosInt(int a[], int n);

int main() {
    int a[] = {1, 2, 9, 2, 2, 4, 2, -2};
    int b[] = {1, -1, 3, 2, 2, 7, 2};
    cout << findMinPosInt(a, 8) << endl;
    cout << findMinPosInt(b, 7) << endl;
}

int findMinPosInt(int a[], int n) {
    int b[n];
    memset(b, 0, sizeof(int) * n);
    for (int i = 0; i < n; ++i) {
        if (a[i] > 0 || a[i] <= n) {
            b[a[i] - 1] = 1;
        }
    }
    for (int i = 0; i < n; ++i) {
        if (b[i] == 0) {
            return i + 1;
        }
    }
    return n + 1;
}

3)时间复杂度O(n),空间复杂度:O(n)

第三题

image.png

分析:a,b,c三个数组,都是升序的

image.png

所以我们只要找到最相近的两个数,并且保证另一个集合里面有在这两个数中间的的数即可

1)

用一个数记录D=ab+ac+bcD = |a-b|+|a-c|+|b-c|的大小

a、将三个数组 同时遍历

b、找出最小的数,将他所在数组往后遍历,如果D变的更小就更新一下(这一步是为了找更小的D)

c、以此循环,直到三个数都遍历到最后

此时D就记录了最小的结果

2)代码

#include<iostream>

using namespace std;

int findMinTrip(int A[], int n, int B[], int m, int C[], int p);

int main() {
    int a[] = {1, 2, 2, 2, 4};
    int b[] = {-11, 11, 16, 21,};
    int c[] = {-19, 19, 39};
    int int_size = sizeof(int);
    cout << findMinTrip(a, sizeof(a) / int_size, b, sizeof(b) / int_size, c, sizeof(c) / int_size) << endl;
}

bool min_in_3(int a, int b, int c) {//a 是否是三个数中的最小值
    if (a <= b && a <= c) {
        return true;
    } else {
        return false;
    }
}

int findMinTrip(int A[], int n, int B[], int m, int C[], int p) {
    int i = 0, j = 0, k = 0, D_min = INT_MAX, D;

    while (i < n && j < m && k < p && D_min > 0) {

        D = abs(A[i] - B[j]) + abs(B[j] - C[k]) + abs(C[k] - A[i]);

        if (D < D_min) {
            D_min = D;
        }

        if (min_in_3(A[i], B[j], C[k])) {
            i++;
        } else if (min_in_3(B[j], C[k], A[i])) {
            j++;
        } else k++;
    }
    return D_min;

}

输出结果:30

3)时间复杂度:O(n),O(1)