1-6
If there are 105 runs to be merged using 4 taps for 3-way merges, then distributing the runs unevenly as (17, 32, 56) will require less number of passes than the even distribution (35, 35, 35).
(2分)
T
F
答案 :F
纸带4条,3路归并
17 32 56 0
0 15 39 17
15 0 24 2
13 2 22 0
11 0 20 2
9 2 18 0
7 0 16 2
5 2 14 0
3 0 12 2
1 2 10 0
0 1 9 1
1 0 8 0
0 0 7 1
0 1 6 0
0 0 5 1
0 1 4 0
0 0 3 1
0 1 2 0
0 0 1 1
0 1 0 0
进行了19步
纸带4条,3路归并
35 35 35 0
0 0 0 35
1 1 0 11
0 0 1 10
0 1 0 9
0 0 1 8
0 1 0 7
0 0 1 6
0 1 0 5
0 0 1 4
0 1 0 3
0 0 1 2
0 1 0 1
0 0 1 0
进行了13步
代码可能有错,不过对于这题来说 是跑对的
void printArr(int *arr, int len) {
for (int i = 0; i < len; i++) {
printf("%4d ", arr[i]);
}
printf("\n");
}
class MathUtil {
public:
static int onlyOneNot0(const int *arr, int len) {
int cnt = 0;
for (int i = 0; i < len; i++) {
if (arr[i] != 0)cnt++;
}
return cnt == 1;
}
// 35 : split 12 12 11 最平均分的整数,
static std::vector<int> splitKNum(int num, int k) {
using namespace std;
vector<int> v;
int ceilNum = ceil((double) num / k);
int floorNum = floor((double) num / k);
// printf("ceilNum: %d, floorNum: %d\n", ceilNum, floorNum);
// https://www.cnblogs.com/mycapple/archive/2012/08/07/2626431.html
for (int i = 0; i < k - 1; i++) {
v.emplace_back(ceilNum);
}
v.emplace_back(floorNum);
// cout << ListUtil::toString(v) << "\n";
return v;
}
};
//Polyphase Merge Sort
//纸带比way多1
class KWay {
int secondMaxIndex;
int maxIndex;
int zeroIndex;
int *arr;
int len;
public:
KWay(int *arr, int len) : arr(arr), len(len) {
}
KWay(int *arr, int len, bool simple) : arr(arr), len(len), simple(simple) {
}
int onlyOneNot0() {
int cnt = 0;
for (int i = 0; i < len; i++) {
if (arr[i] != 0) {
cnt++;
notZeroIndex = i;
}
}
// printf("notZeroIndex:%d\n", notZeroIndex);
return cnt == 1;
}
void putNums(std::vector<int> v) {
int vIndex = 0;
for (int i = 0; i < len; i++) {
if (arr[i] == 0) {
arr[i] = v[vIndex++];
} else {
arr[i] = 0;
}
}
}
void run() {
printf("纸带%d条,%d路%s归并\n", len, len - 1,simple?"简单":"");
std::string str;
int cnt = 0;
while (true) {
if (cnt > 100) {
printf("循环超出100,肯定哪里有错误了,调试下吧\n");
break;
}
// printVector(v);
printArr(arr, len);
// str += ListUtil::toString(arr, len) + "\n";
// MathUtil::onlyOneNot0(arr, len)
if (onlyOneNot0()) {
// 如果是简单归并的话 这里要分开了 如果有3个0 就把数字分成3份
if (!simple)
break;
// len-1 是k
if (arr[notZeroIndex] == 1)break;
// 0 0 0 1 这样子的 就是可以退出了 已经做好了
std::vector<int> numsAve = MathUtil::splitKNum(arr[notZeroIndex], len - 1);
// std::cout << ListUtil::toString(numsAve) << "\n";
putNums(numsAve);
}
// MaxAndSecMaxNumVector maxAndSecMaxNumVector=MaxAndSecMaxNumVector::GetSecondMaxNumberIndex(v);
// maxIndex,secMaxIndex=
// auto maxIndexAndSecMaxIndex = GetSecondMaxNumberIndexRetStruct(arr, len);
第二大的数字变成0
// 第一大的变成 - 去
// 第二大的数字
// GetSecondMaxNumberIndex();
int minIndex = getMinNot0();
if (minIndex == -1) {
// 全是0
break;
}
// 0 放最小数字
//其他不是0的位置,- 最小数字
//4 tape 出现两个0的话,那个0 就不管了
int minNum = arr[minIndex];
for (int i = 0; i < len; i++) {
if (arr[i] == 0)continue;
// if(arr[i]==arr[minIndex])continue;
arr[i] -= minNum;
// if(arr[i]==arr[minIndex])
}
arr[zeroIndex] = minNum;
// arr[maxIndex] -= arr[secondMaxIndex];
// arr[zeroIndex] = arr[secondMaxIndex];
// arr[secondMaxIndex] = 0;
cnt++;
}
printf("进行了%d步\n", cnt);
// https://www.cnblogs.com/li-ning/p/9490053.html
// std::ofstream fout;
// fout.open("kWay.csv");
// std::ofstream fout("kWay.csv");
// fout << str;
// std::cout << str << "\n";
// fout << std::flush;
// fout.close();
}
private:
// 找出一个数组最小的数字的下标 除了0的,顺便把0的下标也找了
int getMinNot0() {
int minIndex = 0;
// if (arr[0] == 0)minIndex = 1;
while (arr[minIndex]==0)minIndex++;
if(minIndex>=len){
printf("全是0,有问题\n");
return -1;
}
for (int i = 0; i < len; i++) {
if (arr[i] == 0) {
zeroIndex = i;
continue;
}
// todo
if (arr[minIndex] > arr[i]) {
minIndex = i;
}
}
// printf("min num:%d\n",arr[minIndex]);
return minIndex;
}
};
运行代码
int arr1[4]{
17, 32, 56,0};
KWay(arr1,4).run();
int arr2[4]{
35, 35, 35,0};
KWay(arr2,4, true).run();