qt的c++算法问题

有一个qvector容器里面有1000个数,现在我要去里面去n个数,n个数包含了第一个数和最后一个数,还有三个特殊索引id的数,最后取到的n个数放到一个qvector容器中,怎样使我比较均衡的从中取到n个数,主要要求取数比较均衡,而且取的数的顺序要按在原来的数中顺序排列,不是升序的数,取数要求均衡,不能随机

你自己分个区间呗,数字放在容器的时候得做个排序,拿区间包含的特殊索引id的数来创新的容器,把新容器合并成一个新的就行

  1. 先确定第一个数和最后一个数,加入结果qvector。
  2. 然后确定3个特殊索引的数,也加入结果qvector。
  3. 计算除去上面5个数外,还需要取出的数n - 5。
  4. 生成随机索引序列,长度为n - 5。
  5. 根据随机索引序列从qvector中取出数加入结果qvector。
#include <QVector>
#include <random>

QVector<int> pickNumbers(QVector<int>& vec, int n) {
    QVector<int> res;
    res.push_back(vec.first());     // 第一个数
    res.push_back(vec.last());      // 最后一个数
    
    int id1 = 5, id2 = 8, id3 = 123;   // 3个特殊索引
    res.push_back(vec[id1]);
    res.push_back(vec[id2]); 
    res.push_back(vec[id3]);
    
    int left = n - res.size();      // 还需要选择的数
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(0, vec.size() - 1);
    
    for (int i = 0; i < left; i++) {
        int idx = dis(gen);
        res.push_back(vec[idx]);
    }
    
    return res;
}

方向不对,努力白费 , 题干审错了 , 白费半小时 (现在取出 和删除我都有了 ^_^)
如有帮助给个采纳 谢谢!

效果如图

img

分析

首先定义一个新的qvector容器,用于存放取出的n个元素。
计算需要取出的中间部分元素的数量,这里假设为m = n - 5。
计算每个元素之间的平均间隔,也就是:(容器长度 - 2) / m。
根据计算出的平均间隔,从第二个元素开始,每隔指定的间隔取一个元素,直到取出m个元素为止。将这些元素加入到新的qvector容器中。
将第一个数、最后一个数和三个特殊索引id的数加入到新的qvector容器中。
对新的qvector容器进行排序,以保证取出的元素按照原来在容器中出现的顺序排列。
返回新的qvector容器

代码

我让 n= 10 , 根据你的需要自己改就行

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main() {
    const int vecSize = 1000;
    vector<int> vec(vecSize);
    // 初始化qvector容器
    for (int i = 0; i < vecSize; ++i) {
        vec[i] = i;
    }

    int n = 10;      // 需要取出的元素数量,包括第一个数、最后一个数和三个特殊索引id的数
    int m = n - 5;   // 需要取出的中间部分元素的数量
    // 计算每个元素之间的平均间隔
    int avgGap = (vecSize - 2) / m;
    // 定义新的qvector容器,用于存放取出的n个元素
    vector<int> newVec;
    // 将第一个数加入到新的qvector容器中
    newVec.push_back(vec[0]);
    // 输出原始qvector容器的元素
    cout << "原始qvector容器的元素为:";
    for (int i = 0; i < vecSize; ++i) {
        cout << vec[i] << " ";
    }
    cout << endl;
    // 从第二个元素开始,每隔avgGap取一个元素,直到取出m个元素为止
    for (int i = 1, cnt = 0; cnt < m; ++cnt, i += avgGap) {
        newVec.push_back(vec[i]);
    }
    // 将最后一个数加入到新的qvector容器中
    newVec.push_back(vec[vecSize - 1]);
    // 将三个特殊索引id的数加入到新的qvector容器中
    newVec.push_back(vec[3]);
    newVec.push_back(vec[5]);
    newVec.push_back(vec[7]);
    // 对新的qvector容器进行排序,以保证取出的元素按照原来在容器中出现的顺序排列
    sort(newVec.begin(), newVec.end());
    // 输出取出的元素
    cout << "取出的" << n << "个元素为:";
    for (int i = 0; i < newVec.size(); ++i) {
        cout << newVec[i] << " ";
    }
    cout << endl;

    return 0;
}


确定每个数的权重。将1000个数看作一个序列,除了第一个数和最后一个数以外,其他数的权重为1。第一个数和最后一个数的权重为2。三个特殊索引id的数的权重为0,即不参与取数。
计算总权重。将序列中所有数的权重相加,得到总权重sum。
计算每个数的概率。将每个数的权重除以总权重sum,得到每个数被选中的概率p。
计算每个数被选中的次数。将n乘以每个数的概率p,得到每个数被选中的次数count。
从序列中按照顺序依次取出每个数,每次取出count次,直到取出n个数。
以下是基于Qt的参考代码实现:

// 假设qvector容器为vec,包含1000个数
QVector<int> vec(1000);

// 假设n为需要取出的数的个数
int n;

// 假设特殊索引id的数的位置分别为pos1、pos2、pos3
int pos1, pos2, pos3;

// 计算每个数的权重
QVector<int> weight(vec.size(), 1);
weight[0] = weight.back() = 2;
weight[pos1] = weight[pos2] = weight[pos3] = 0;

// 计算总权重
int sum = std::accumulate(weight.begin(), weight.end(), 0);

// 计算每个数被选中的概率
QVector<double> p(vec.size());
std::transform(weight.begin(), weight.end(), p.begin(), [=](int w) { return static_cast<double>(w) / sum; });

// 计算每个数被选中的次数
QVector<int> count(vec.size());
std::transform(p.begin(), p.end(), count.begin(), [=](double prob) { return static_cast<int>(n * prob); });

// 循环取数
QVector<int> result;
result.reserve(n);
int i = 0;
while (result.size() < n) {
    int num = vec[i];
    for (int j = 0; j < count[i]; ++j) {
        result.append(num);
    }
    ++i;
    if (i >= vec.size()) {
        i = 0;
    }
}

// 取出的n个数按照原来的顺序排列
// result中的数依次为:第一个数、其他数、最后一个数、特殊索引id的数

在以上代码中,首先根据每个数的位置,计算每个数的权重。然后根据权重计算每个数被选中的概率,以及每个数被选中的次数。接着我们循环遍历原序列,依次取出每个数,并按照每个数被选中的次数count,将该数添加到结果序列result中。最后,我们可以得到一个包含n个数的结果序列result,其中取数比较均衡,且按照原来的顺序排列。

希望能够帮助你,感谢您的采纳

为了从原始 QVector 中均衡地选取 n 个数并保持它们在原始 QVector 中的顺序,我们可以按以下几个步骤实现:

定义一个新的 QVector 容器用于存放选取的 n 个数。

计算平均间隔:取整数间隔 int step = (原始容器大小 - 特殊索引数量 - 2) / (n - 特殊索引数量 - 2)。

添加第一个数和三个特殊索引 id 的数到新的 QVector 容器中。

按照间隔 step 来挑选剩余的数字:

int currentIndex = 0;
for (int i = 1; i < n - 特殊索引数量; ++i) {
    currentIndex += step;
    新容器.push_back(原始容器[currentIndex]);
}

添加最后一个数到新 QVector 容器中。

返回新 QVector 容器。

这个方法可以在保持原有数据顺序的前提下,较为均衡地从原始 QVector 中选取 n 个数。需要注意的是,由于间隔 step 取整数,所以间隔可能不是完全相等的,但是这样可以确保选取结果尽可能接近要求。

基于new bing的编写,有帮助望采纳!:
可以使用以下算法来实现从qvector容器中均衡地取到n个数:

  • 首先确定三个特殊索引id对应的数的位置,将其加入待取元素列表中。
  • 将qvector容器中除去前面和后面特殊索引id的数之外的所有元素随机排序。
  • 从随机排序后的列表中顺序取出n-3个元素,并加入待取元素列表中。
  • 将待取元素列表按原qvector容器中的顺序排列,即可得到均衡地从中取到n个数的结果。

以下是用C++代码实现上述算法的示例:

#include <QVector>
#include <random>
#include <algorithm>

QVector<int> balancedSampling(const QVector<int>& data, int n, int idx1, int idx2, int idx3) {
    QVector<int> res;
    int size = data.size();
    
    // 添加三个特殊索引id对应的数
    res.append(data[idx1]);
    res.append(data[idx2]);
    res.append(data[idx3]);
    
    // 随机排序剩余元素
    QVector<int> tempData(data);
    tempData.remove(idx1);
    tempData.remove(idx2-1);
    tempData.remove(idx3-2);
    std::random_device rd;
    std::mt19937 g(rd());
    std::shuffle(tempData.begin(), tempData.end(), g);
    
    // 顺序添加剩余元素
    for (int i = 0; i < n-3; i++) {
        res.append(tempData[i]);
    }
    
    // 按原序列顺序排列结果
    QVector<int> result;
    for (int i = 0; i < size; i++) {
        if (res.contains(data[i])) {
            result.append(data[i]);
        }
    }
    
    return result;
}


示例中,参数data为待取样数据,n为需要取出的元素个数,idx1、idx2、idx3为特殊索引id对应的下标。函数返回均衡采样结果。

1.首先将qvector容器中的三个特殊索引id的数(假设为a、b、c)存起来。
2.将剩下的n-3个数平均地分成m段,每段选取int((1000-2)/(n-3))个数,不足的部分平均分配到前m个段中。
3.每次遍历剩余的数字时,检查当前的下标是否在已经选好的m个段中,如果是则跳过,否则将该数字添加到结果中。要注意特殊索引id的位置,需要放在第一个、中间一个和最后一个位置。


#include <vector>
#include <algorithm>

std::vector<int> selectNumbers(const std::vector<int>& nums, int n, int id1, int id2, int id3) {
    std::vector<int> result;
    // 将特殊索引id的数先存起来
    int a = nums[id1], b = nums[id2], c = nums[id3];
    result.push_back(a);
    int m = n - 3;
    int segNum = std::min(m, 1000 - 2);  // 决定划分的段数,最多为1000-2
    int segSize = (1000 - 2) / segNum;   // 计算每段应该选择的数量
    int rem = (1000 - 2) % segNum;       // 计算余数,平均分配到前面的rem个段中
    std::vector<bool> selected(segNum, false);
    // 遍历剩余的数字,按照划分好的段数和数量进行选择
    for (int i = 1; i <= 1000 - 2; ++i) {
        if (i - 1 == id1 || i - 1 == id2 || i - 1 == id3) {
            continue;
        }
        int segId = std::min(i / segSize, segNum - 1);  // 计算当前数字所在段的下标
        if (!selected[segId]) {
            int segRem = rem > 0 ? std::min(1, rem--) : 0;
            for (int j = 0; j < segSize + segRem; ++j) {
                if (!selected[segId] && j == segSize) {
                    selected[segId] = true;
                }
                if (i - 1 == id1 || i - 1 == id2 || i - 1 == id3) {
                    continue;
                }
                result.push_back(nums[i - 1]);
            }
        }
    }
    result.push_back(b);
    result.push_back(c);
    return result;
}

回答部分参考、引用ChatGpt以便为您提供更准确的答案:

为了从包含1000个数的 qvector 容器中均衡地取出 n 个数,并且保持原始顺序,您可以按照以下步骤进行操作:

  1. 确定每个特殊索引的位置:首先,找到这三个特殊索引在 qvector 容器中的位置,分别记为 i1、i2 和 i3。
  2. 计算每个部分的大小:根据要求,总共需要取出 n 个数,其中已经包括了第一个数和最后一个数,还有三个特殊索引的数。因此,剩下需要从 qvector 中取出的数的数量为 n - 5。将这个数量除以 3,并向下取整,得到每个部分应该取出的数的数量,记为 k。
  3. 均衡地取出数:从 qvector 容器中按照以下顺序取出数:第一个数,然后从 i1 的位置开始,取出 k 个数;接下来取出 i2 对应的数,再从 i2+1 的位置开始,取出 k 个数;最后取出 i3 对应的数,再从 i3+1 的位置开始,取出 k 个数;最后取出最后一个数。将这些取出的数按照原来的顺序放入新的 qvector 容器中。

通过按照上述步骤操作,您可以实现从 qvector 容器中均衡取出 n 个数,并且保持原始顺序。

请注意,具体实现可能因为编程语言和环境的不同而有所差异,您可以根据自己的需求和情况进行相应的调整和修改。

chatgpt
您可以通过以下步骤来实现从原始 QVector 中均衡地获取 n 个数:

计算特殊索引 id 的位置,以确保它们包含在 n 个数中。

计算剩余可用的位置数量,即 1000 - 3(特殊索引 id 的数量)。

计算每个特殊索引 id 前后可用的位置数量,即 (n-3)/2。

从每个特殊索引 id 开始,向前和向后获取相同数量的位置,直到获取了 n 个数。

将获取的 n 个数按照它们在原始 QVector 中的顺序排序。

下面是一个示例代码:


QVector<int> originalVector = ...; // 原始 QVector
QVector<int> resultVector; // 存储结果的 QVector
int n = ...; // 需要获取的数的数量

// 特殊索引 id 的位置
int id1 = 10;
int id2 = 500;
int id3 = 900;

// 计算剩余可用的位置数量
int availablePositions = originalVector.size() - 3;

// 计算每个特殊索引 id 前后可用的位置数量
int positionsPerIndex = (n - 3) / 2;

// 从每个特殊索引 id 开始,向前和向后获取相同数量的位置,直到获取了 n 个数
for (int i = 0; i < n; i++) {
    if (i == 0) {
        resultVector.append(originalVector[id1]);
    } else if (i == n - 3) {
        resultVector.append(originalVector[id2]);
    } else if (i == n - 2) {
        resultVector.append(originalVector[id3]);
    } else {
        int index = id1 - positionsPerIndex + i;
        if (index < 0) {
            index = id2 - (i - id1 + positionsPerIndex);
        }
        if (index >= originalVector.size()) {
            index = id2 + (i - id1 + positionsPerIndex);
        }
        resultVector.append(originalVector[index]);
    }
}

// 将获取的 n 个数按照它们在原始 QVector 中的顺序排序
std::sort(resultVector.begin(), resultVector.end(), [&](int a, int b) {
    return std::find(originalVector.begin(), originalVector.end(), a) <
           std::find(originalVector.begin(), originalVector.end(), b);
});

请注意,这只是一个示例代码,您可能需要根据您的具体要求进行修改。

参考ChatGPT Plus版本
您可以通过以下方式实现从一个 QVector 容器中均衡地选取n个数:

#include <QVector>
#include <algorithm>

QVector<int> getBalancedSubset(const QVector<int>& original, int n, int id1, int id2, int id3) {
    QVector<int> subset;
    subset.reserve(n);

    int size = original.size();
    int step = size / (n - 4); // 计算每个普通索引之间的间隔

    // 加入特殊索引id的数
    subset.append(original[id1]);
    subset.append(original[id2]);
    subset.append(original[id3]);

    // 根据间隔,均衡地选择普通索引
    for (int i = 1; i <= n - 4; i++) {
        int index = i * step;
        subset.append(original[index]);
    }

    return subset;
}

int main() {
    QVector<int> original(1000); // 假设原始容器有1000个数,初始值为0

    // 初始化原始容器,假设每个元素的值为其索引
    for (int i = 0; i < original.size(); i++) {
        original[i] = i;
    }

    int n = 10; // 需要选取的总数
    int id1 = 0; // 特殊索引1
    int id2 = 100; // 特殊索引2
    int id3 = 500; // 特殊索引3

    QVector<int> balancedSubset = getBalancedSubset(original, n, id1, id2, id3);

    // 打印结果
    for (int i = 0; i < balancedSubset.size(); i++) {
        qDebug() << balancedSubset[i];
    }

    return 0;
}

在上述代码中,getBalancedSubset 函数接收原始容器 original、需要选取的总数 n,以及三个特殊索引 id1id2id3。函数首先在结果子集中加入这三个特殊索引对应的数值。然后,根据每个普通索引之间的间隔,均衡地选择普通索引对应的数值,加入到结果子集中。最后,返回结果子集。

main 函数中,我提供了一个简单的示例,展示了如何调用 getBalancedSubset 函数来获取均衡的子集。您可以根据需要修改输入的原始容器、需要选取的总数和特殊索引的值,并对结果进行进一步处理或打印输出。

请注意,上述代码假设特殊索引的值是有效的,未做范围检查。在实际应用中,您可能需要添加相应的错误处理逻辑。另外,该示例仅为演示目的,并未考虑容器越界、边界情况等。在实际使用中,请根据具体需求进行适当的检查和处理。