部分排序问题 @

题目 @

解题思路 @

看到题目后,有一种简单想法就是将所有 k 位的部分排序后得到的整体序列全部存起来,然后对每一个序列比较,筛除相同的序列,得到不同序列,但如果 n 与 k 的值足够大,需要使用更多的数组存储序列,时间复杂度与空间复杂度都非常高,因此必须想到一个更好的解题思路,以下是我的解题思路。

本题中,由于 k 的值不同,所以每次选择的部分排序也不同,可能存在两次或多次进行部分排序后,整体的序列排序相同。因此需要考虑在什么情况下,两次或两次以上部分排序得到的整体的序列排序也相同,因为序列相同只进行一次计算。

由于每次可以从任意位置 i(i=0,1,2,3…n)取 k 位,然后对 k 位进行升序排序,那么如果 i+1 位置开始取 k 位并进行升序排序得到的序列,和前一个位置的升序排序序列得到的序列的的交集相等,则说明这两个经过部分排序的序列得到的整体序列顺序也相等,因此说明两个序列重复,重复的序列只计算一次,如果不等说明两个序列不重复,则序列种类 +1。

代码如下 @

void Sort(int *num, int x) {        //冒泡排序
    int lenth = x;                    //数组大小
    int temp;
    for (int i = 0; i < lenth - 1; i++) {                //冒泡排序(将数组元素升序排序)
        for (int j = 0; j < lenth - 1 - i; j++) {
            if (*(num + j) > *(num + j + 1)) {
                temp = *(num + j);
                *(num + j) = *(num + j + 1);
                *(num + j + 1) = temp;
            }
        }
    }
}
int IsEqual(int a[], int b[], int k) {        //判断是否相等
    Sort(a, k); Sort(b, k);
    for (int i = 0; i < k - 1; i++) {
        if (a[i] == b[i + 1]) continue;
        else return false;
    } return true;
}
int main() {
    int max;                        //输入序列长度
    cout << "输入序列长度" << endl;
    cin >> max;
    int k;
    cout << "输入k" << endl;
    cin >> k;

    int *temp = (int*)malloc(sizeof(int)*k);        //临时数组,负责存储从i位起k个数据,部分排序序列
    int *temp1 = (int*)malloc(sizeof(int)*k);        //负责保存上一个部分排序序列
    for (int i = 0; i < k; i++) {                    //初始化
        temp1[i] = 0;
        temp[i] = 0;
    }

    int *number = (int*)malloc(sizeof(int)*max);    //输入序列
    cout << "序列赋值" << endl;
    for (int i = 0; i < max; i++) {
        cin >> number[i];
    }

    int sortNum = 0;        //初始序列排列种类数量
    int fl = 0;                //移位次数
    for (int i = 0; i + k < max; i++) fl++;

    int lock = 0;
    for (int i = 0; i <= fl; i++) {
        int b = 0;
        for (int j = i; j < i + k; j++) {                //每次截取k位数据
            if (b < k) {
                temp[b++] = number[j];
            }
        }
        int isTrue = IsEqual(temp, temp1, k);
        if (isTrue) {        //判断前后两次部分排序序列的交集是否相等
            if (lock != 1) {
                sortNum++; lock = 1;
            }
        }
        else if (!isTrue) {
            sortNum++; lock = 0;
        }
        for (int l = 0; l < k; l++) {
            temp1[l] = temp[l];
        }
    } cout << "结果为:" << sortNum - 1 << endl;
    system("pause");
    return 0;
}