【2013年408真题】线性表

已知一个整数序列A=(a0,a1,…,an-1),其中0≤ai<n(0≤i<n)。若存在ap1=ap2=…=apm=x且m>n/2(0≤pk<n,1≤k≤m),则称x为A的主元素。例如A=(0,5,5,3,5,7,5,5),则5为主元素;又如A=(0,5,5,3,5,1,5,7),则A中没有主元素。

假设A中的n个元素保存在一个一维数组中,请设计一个尽可能高效的算法,找出A的主元素。若存在主元素,则输出该元素;否则输出-1

【测试样例】{0,5,5,3,5,7,5,5}
【输出结果】5

【测试样例】{0,5,5,3,5,1,5,7}
【输出结果】-1

算法思路一

  1. 选取候选的主元素:依次扫描数组中的数,将第一个遇到的数tmp保存在c中,记录tmp出现的次数为1;继续扫描,若下一个数仍等于tmp,则计数+1,否则计数-1,当计数减到0时,将遇到的下一个整数保存到c中,计数重新记为1,开始新一轮计数,重复上述过程,直到扫描完全部数组元素。
  2. 判断c是否为真正的主元素:再次扫描数组,统计c出现的次数,若大于n/2,则为主元素;否则不存在主元素

上述算法的时间复杂度为O(n),采用空间复杂度为O(1)

​int findMainElem(int R[],int n)
{
    int i,c,count=1;//count为计数工具,记录候选主元素出现的次数
    c=R[0];
    for(i=1;i<n;i++)
        if(R[i]==c)
            count++;
        else
            if(count>0)
                count--;
            else
            {
                c=R[i];
                count=1;
            }
    if(count>0)
        for(i=count=0;i<n;i++)//统计候选主元素实际出现的次数
            if(R[i]==c)
                count++;
    if(count>n/2)
        return c;
    else return -1;
}

算法思路二

  1. 使用快速排序对数组元素进行排序,为减少时间复杂度
  2. 新建标志位统计元素出现的个数,从第1个元素开始遍历数组,若和前一元素相同则标志数组元素在之前基础上+1,若不同,则置为0;其中使用max暂存最大值

上述算法的时间复杂度为O(nlog2n),采用空间复杂度为O(1)

//附加快速排序代码
int Partition(int R[],int low,int high)
{
    int pivot=R[low];
    while(low<high)
    {
        while(low<high&&R[high]>=pivot)
            --high;
        R[low]=R[high];
        while(low<high&&R[low]<=pivot)
            ++low;
        R[high]=R[low];
    }
    R[low]=pivot;
    return low;
}
void QuickSort(int R[],int low,int high)
{
    if(low<high)
    {
        int pivotpos=Partition(R,low,high);
        QuickSort(R,low,pivotpos-1);
        QuickSort(R,pivotpos+1,high);
    }
}
int findMainElem2(int R[],int n)
{
     int i,max,tmp;
     int c=0;
     QuickSort(R,0,n-1);
     int a=R[0];
     for(i=1;i<n;i++)
     {
         if(R[i]!=R[i-1])
         {
             if(max<c)//始终维持max为最大值
             {
                 tmp=R[i-1];//tmp暂存候选主元素的值
                 max=c-1;
             }
              c=0;
         }
         else
         {
             c++;//统计量增加
             max=c;
             tmp=R[i];
         }
     }
     if(max+1>n/2)//由于第一次出现时置为0,所以最终比较结果时需要+1
        return tmp;
    else 
        return -1;
}

 

题目描述中给出了两个序列pushed和poped,分别表示入栈和出栈的序列。题目要求判断给定的出栈序列是否可能是由对应的入栈序列执行出栈操作得到的。 解决这个问题的思路可以使用模拟栈的方式。我们遍历入栈序列,将元素依次入栈,并在每次入栈后检查栈顶元素是否与当前出栈序列的第一个元素相等。如果相等,则将栈顶元素出栈,并将出栈序列的指针向后移动一位。最后,如果栈为空,则说明出栈序列是由对应的入栈序列执行出栈操作得到的。 下面是C++代码实现: ```cpp #include <iostream> #include <stack> #include <vector> using namespace std; bool validateStackSequences(vector<int>& pushed, vector<int>& popped) { stack<int> st; int n = pushed.size(); int j = 0; // 出栈序列指针 for (int i = 0; i < n; i++) { st.push(pushed[i]); while (!st.empty() && st.top() == popped[j]) { st.pop(); j++; } } return st.empty(); } int main() { int q; // 询问次数 cin >> q; while (q--) { int n; // 序列长度 cin >> n; vector<int> pushed(n); vector<int> popped(n); for (int i = 0; i < n; i++) { cin >> pushed[i]; } for (int i = 0; i < n; i++) { cin >> popped[i]; } if (validateStackSequences(pushed, popped)) { cout << "Yes" << endl; } else { cout << "No" << endl; } } return 0; } ``` 这段代码中,我们使用了一个栈st来模拟入栈和出栈的过程。遍历入栈序列pushed,将元素依次入栈,并在每次入栈后检查栈顶元素是否与当前出栈序列popped的第一个元素相等。如果相等,则将栈顶元素出栈,并将出栈序列的指针向后移动一位。最后,如果栈为空,则说明出栈序列是由对应的入栈序列执行出栈操作得到的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值