王道上几道顺序表的小题 (下)

已知在一维数组A[m+n]中一次存放着两个线性表(a1,a2,a3,...am) 和 (b1,b2,b3,...bn)。试编写一个函数,将数组中两个顺序表的位置互换,即将(b1,b2,b3,...,bn) 放在 (a1,a2,a3,...,am)的前面

void Reverse(DataType A[], int left, int right, int arraySize){
    // 先对整个数组逆置,在分别对线性表b和线性表a进行逆置
    if(left >= right || right >= arraySize){
        return false;
    }
    int mid = (left + right) / 2;
    DataType temp;
    for(int i = 0; i < mid; ++i){
        temp = A[left + i];
        A[left + i] = A[right - i];
        A[right - i] = temp;
    }
}

void Exchange(){
    Reverse(A, 0, m+n-1, arraySize);
    Reverse(A, 0, n-1, arraySize);
    Reverse(A, n, m+n-1, arraySize);
}
  • 线性表(a1, a2, a3, ..., an)中元素递增有序且按顺序存储于计算机内,要求设计一个算法完成用时最少在表中查找数值为x的元素,若找到将其与后继元素位置相交换,若找不到将其插入表中并使表中元素仍递增有序
void SearchExchangeInsert(ElemType A[], ElemType x){
    // 使用折半查找法
    int low = 0, high = n - 1, mid;
    while(low <= high){
        mid = (low+hight)/2;
        if(A[mid] == x){
            break;
        }else if(A[mid] < x){
            low = mid + 1;
        }else{
            high = mid - 1;
        }
    }
    if(A[mid] == x && mid != n - 1){// 若最后一个元素与x相等,不存在与其后继交换的操作
        ElemType t = A[mid];
        A[mid] = A[mid + 1]; 
        A[mid + 1] = t;
    }
    if(low > high){
        for(i = n - 1; i > high; i--){
            A[i+1] = A[i];
        }
        A[i+1] = x;
    }
}
  • 设将n(n>1)个整数存放到一维数组R中。试设计一个在时间和空间两方面都尽可能高效的算法。将R中保存的序列循环左移p(0<p<n)个位置,即将R中的数据由(X0,X1,...,Xn-1)变换为(Xp,Xp+1,...,Xn-1,X0,X1,...,Xp-1)。要求:给出算法的基本设计思想根据设计思想,类C描述算法,说明时空复杂度
思路:
把这个问题看作把数组ab转为数组ba(a代表数组的前p个元素,b代表数组余下的n-p个元素),先将a逆置得到
a逆b,再将b逆置得到a逆b逆,最后将整个a逆b逆逆置为ba

void Reverse(int R[], int from, int to){
    int i, temp;
    for(i = 0; i < (to - from + 1)/2; i++){
        temp = R[from + i];
        R[from + i] = R[to - i];
        R[to - i] = temp;
    }
}

void Converse(int R[], int n int p){
    Reverse(R, 0, p-1);
    Reverse(R, p, n-1);
    Reverse(R, 0, n-1);
}

时间复杂度分别为O(p/2),O((n-p)/2),O(n/2)
故时间复杂度为O(n),空间复杂度为O(1)
  • 一个长度为L(L>=1)的升序序列S,处在第向上取整 ⌈L/2⌉的位置称为S的中位数。例如,若序列S1=(11,13,15,17,19),则S1的中位数位15,两个序列的中位数,是含它们的所有元素的升序序列的中位数。例如,S2=(2,4,6,8,20),则S1和S2的中位数是11,现有两个等长升序序列A和B,试设计一个在时间和空间两方面都尽可能高效的算法,找出两个序列A和B的中位数字。给出算法的基本设计思想根据设计思想,类C描述算法,说明时空复杂度
分别求两个序列的中位数,设为a和b,求序列A和B的中位数
若a=b,则a或b即所求中位数
若a<b,则舍弃序列A中较小的一半,同时舍弃序列B中较大的一半,两次舍弃的长度相等
若a>b,则舍弃序列A中较大的一半,同时舍弃序列B中较小的一半,两次舍弃的长度相等
在保留的两个升序序列中,重复以上过程,直到两个序列中均只含一个元素时为止,较小者即为所求中位数

int M_search(int A[], int B[], int n){
    int s1=0, d1 = n - 1, m1, s2 = 0, d2 = n-1, m2
    while(s1 != d1 || s2 != d2){
        m1 = (s1+d1)/2;
        m2 = (s2+d2)/2;
        if(A[m1] == B[m2]){
            return A[m1];
        }
        if(A[m1] < B[m2]){
            if((s1 + d1)%2 == 0){// 数量为奇数个,保留中间点
                s1 = m1;// 舍弃A中较小的部分
                d2 = m2;// 舍弃B中较大的部分
            }else{
                s1 = m1 + 1;
                d2 = m2;
            }
        }else{
            if((s2 + d2)%2 == 0){// 数量为奇数个,保留中间点
                d1 = m1;// 舍弃A中较大的部分
                s2 = m2;// 舍弃B中较小的部分
            }else{
                d1 = m1;
                s2 = m2 + 1;
            }
        }
    }
    return A[s1] < B[s2]? A[s1]:B[s2];
}
  • 已知一个整数序列A=(a0,a1,...,an-1),其中0<=ai<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。给出算法的基本设计思想根据设计思想,类C描述算法,说明时空复杂度
重复次数多于整个数组一半数量的元素即为主元素
标记一个可能的主元素,然后扫描统计出现次数,判断是否为真的主元素
记录遇到的第一个整数Num,若下次遇到的整数仍等于Num,计数+1;否则,计数-1
计数减到0的时候,将遇到的下一个整数作为Num,计数重新计为1,重复以上过程
判断标记的整数是否为真的主元素,扫描数组,统计标记整数的出现次数
int Majority(int A[], int n){
    int i, c, count = 1;
    c = A[0];    
    for(i = 1; i < n; i++){
        if(A[i] == c){
            count++;
        }else{
            if(count > 0){
                count--;
            }else{
                c = A[i];
                count = 1;
            }
        }
    }
    if(count > 0){
        for(i = count = 0; i < n; i++){
            if(A[i] == c){
                count++;
            }
        }
        if(count < n/2){
            return c;
        }
    }else{
        return -1;// 不存在主元素
    }
}
时间复杂度O(n),空间复杂度O(1)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值