2013年的408算法题

10 篇文章 0 订阅

0 结果

在这里插入图片描述

在这里插入图片描述

1 题目

2 思路

2.1 思路1(暴力解:双重枚举)

双重枚举判断每个元素是否是主元素。

#include <cstdio>
#include <cstdlib>

const int n = 8;

int ans(int A[], int n){
    int cnt;
    for(int i = 0;i < n;i++){
        cnt = 0;
        for(int j = 0; j < n;j++){
            if(A[i] == A[j]) cnt++;
            if(cnt > n/2) return A[i];
        }
    }
    return -1;
}

int main(){
    int A[] = {0,5,5,3,5,1,5,7};//{0,5,5,3,5,7,5,5};
    printf("A:");
    for (int i = 0; i < n; ++i) {
        printf("%d ", A[i]);
    }
    printf("\n%d", ans(A, n));

    return  0;
}

时间复杂度: O ( n 2 ) O(n^2) O(n2)
空间复杂度: O ( 1 ) O(1) O(1)

2.2 思路2(较优解:排序)

对原序列使用快速排序得到升序序列后,扫描一趟数组,如果同值元素左右相距距离大于n/2,则存在主元;反之,则不存在。

#include <cstdio>
#include <cstdlib>
#include <algorithm>

void Qsort(int A[], int L, int R){
    if(L >= R) return;
    int pivot , i = L, j = R;
    std::swap(A[L], A[rand()%(R - L + 1) + L]);
    pivot = A[L];//比较基准元素
    while (i < j){
        while(i < j && A[j] > pivot) j--;
        while(i < j && A[i] <= pivot) i++;
        if(i < j) std::swap(A[i], A[j]);
    }
    std::swap(A[i], A[L]);
    Qsort(A, L, i - 1);
    Qsort(A, i + 1, R);
}

int ans(int A[], int n){
    Qsort(A, 0, n - 1);
    int L = 0;//同值最左边的元素位置
    for(int i = 0;i < n;i++){
        if(A[i] != A[L]){//遇到新元素A[i]
            if(i - L > n/2)
                return A[L];
            L = i;
        }

    }
    return -1;
}

int main(){
    int A[] = {0,5,5,3,5,7,5,5};//{0,5,5,3,5,1,5,7};
    int n = sizeof(A)/sizeof(A[0]);
    printf("A:");
    for (int i = 0; i < n; ++i) {
        printf("%d ", A[i]);
    }
    printf("\n%d", ans(A, n));

    return  0;
}

时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)
空间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)

2.3 思路3(较优解:空间换时间)

使用hash映射打表,每出现一次次数加1,如果次数有超过n/2,则存在主元素,反之,则不存在。(缺点:需要辅助数组)。

#include <cstdio>
#include <cstring>

int ans(int A[], int n){
    int cnt[n];
    memset(cnt, 0, sizeof(cnt));
    for(int i = 0;i < n;i++)//统计数字出现的次数
        cnt[A[i]]++;
    for(int i = 0;i < n;i++){//寻找主元
        if(cnt[i] > n/2)
            return i;
    }
    return -1;
}

int main(){
    int A[] = {0,5,5,3,5,1,5,7};//{0,5,5,3,5,7,5,5};
    int n = sizeof(A)/sizeof(A[0]);
    printf("A:");
    for (int i = 0; i < n; ++i) {
        printf("%d ", A[i]);
    }
    printf("\n%d", ans(A, n));

    return  0;
}

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

2.4. 思路4(最优解:技巧——两两抵消)

两两相互抵消。如果数组中存在大于一般的相同元素,首先假设第一个元素为主元素的候选元素【统计个数为1】,如果目前元素统计的个数大于0,遇到相同的数字——个数加1,不同的数字——个数减1;当元素统计的个数为0时,将遇到的数字变更为候选的主元素。循环结束时,遍历整个数组来统计候选主元素在数组中的个数,如果大于n/2,则存在主元素,反之则不存在。

#include <cstdio>
#include <cstdlib>

int ans(int A[], int n){
    int num = A[0], cnt = 1;
    for (int i = 1; i < n; ++i) {
        if(A[i] == num){
            cnt++;
        }else{
            if(cnt > 0){
                cnt--;
            }else{
                num = A[i];
                cnt = 1;
            }
        }
    }
    cnt = 0;
    for (int j = 0; j < n; ++j) {
        if(num == A[j]){
            cnt++;
        }
    }
    if(cnt > n/2){
        return num;
    }else{
        return -1;
    }
}

int main(){
    int A[] = {0,5,5,3,5,1,5,7};//{0,5,5,3,5,7,5,5};
    int n = sizeof(A)/sizeof(A[0]);
    printf("A:");
    for (int i = 0; i < n; ++i) {
        printf("%d ", A[i]);
    }
    printf("\n%d", ans(A, n));

    return  0;
}

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

附录

408历年真题算法题解析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

繁星蓝雨

如果觉得文章不错,可以请喝咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值