合并不等长的排序数组
Merging sorted arrays of unequal length
我有一个项目需要我合并两个排序的数组(a 和 b)并将结果放入一个长度为 a.length + b.length 的新数组中。
我正在跟踪我在所有 3 个数组中的位置计数器,并且我的数组长度不相等。我的约定是,如果一个数组先于另一个数组用完,代码只会将另一个数组的其余部分转储到结果数组中。
不幸的是,我可以检查另一个数组是否仍然包含元素的唯一方法是查看 for 循环。
谁能帮帮我?这应该是一个相对容易的修复,但我想不出解决方案。
public class Two {
public static void main(String[] args) {
//sample problem
int[] var_a = {2,3,5,5,8,10,11,17,18,20};
int[] var_b = {5,6,7,8,14,15,17};
final int a_size = 10;
final int b_size = 7;
final int c_size = 17;
int[] var_c = new int[17];
int aCount = 0;
int bCount = 0;
int cCount = 0;
for (cCount = 0; cCount < c_size; cCount++) {
//b runs out before a runs out
if ((bCount == b_size) && (aCount <= a_size)) {
//dump rest of var_a into var_c
var_c[cCount] = var_a[aCount];
aCount++;
}
//PROBLEM: bCount is equal to bSize, and is triggering the break.
//a runs out before b runs out
else if ((aCount == a_size) && (bCount <= b_size)) {
//dump rest of var_b into var_c
var_c[cCount] = var_b[bCount];
bCount++;
}
if ((aCount >= a_size) || (bCount >= b_size) || (cCount >= c_size)) {break;}
if (var_a[aCount] < var_b[bCount]) {
var_c[cCount] = var_a[aCount];
aCount++;
} else if (var_a[aCount] > var_b[bCount]) {
var_c[cCount] = var_b[bCount];
bCount++;
} else if (var_a[aCount] == var_b[bCount]) {
var_c[cCount] = var_a[aCount];
aCount++;
cCount++;
var_c[cCount] = var_b[bCount];
bCount++;
}
}
for (int i : var_c) {
System.out.print(i + " ");
}
}
}
您可以遍历单个数组的索引,而不是遍历合并数组的索引,以确保您永远不会越界:
int aCount = 0;
int bCount = 0;
int cCount = 0;
while (aCount < var_a.length && bCount < var_b.length) {
if (var_a[aCount] <= var_b[bCount]) {
var_c[cCount++] = var_a[aCount++];
} else {
var_c[cCount++] = var_b[bCount++];
}
}
// now add what remains of var_a or var_b
while (aCount < var_a.length)
var_c[cCount++] = var_a[aCount++];
while (bCount < var_b.length)
var_c[cCount++] = var_b[bCount++];
此问题的常见解决方案是将单个循环替换为三个循环:
- 第一个循环合并两个数组,直到其中一个用完元素
- 第二个循环将数组
A
的剩余元素转储到输出数组中
- 第三个循环将数组
B
的剩余元素转储到输出数组 中(如果有的话)
这个结构可以让合并循环变得更简单:
while (aCount != var_a.length() && b.Count != var_b.length()) {
... // merge
}
while (aCount != var_a.length()) {
var_c[cCount++] = var_a[aCount++];
}
while (bCount != var_b.length()) {
var_c[cCount++] = var_b[bCount++];
}
注意最后两个循环最多执行一个。还要注意使用length()
方法来确定数组的长度。比设置a_size
、b_size
等靠谱
此代码应遵循
的简单逻辑
- 将所有 3 个 a_counter、b_counter、c_c
的计数器初始化为 0
- 现在直到 a_c 或 b_counter 分别小于 a_size 和 b_size
- 将 a[a_counter] 与 b[b_counter] 进行比较,并将较小的添加到 c 的 c[c_c倒数]
- 增加c_c计数器,以及上面选择的
- 重复
- 一旦跳出循环,a或b之一就结束了
- 如果b结束,继续向c添加a的所有剩余元素;或 b 如果 a 结束
我相信你不需要代码,只需要改进逻辑;所以不给代码。
这可能是您想要的:
void doArrayThing(){
//the two arrays containing the elements
int[] array1 = {1, 3, 5, 2, 7, 5};
int[] array2 = {3, 6, 2, 8};
//the length of the 2 arrays
int arrayLength1 = array1.length;
int arrayLength2 = array2.length;
//the length of both the arrays
int containerArrayLength = arrayLength1 + arrayLength2;
//the array that holds all the elements
int[] container = new int[containerArrayLength];
//a for loop that adds the first array elements
for(int i = 0; i < arrayLength1; i++){
//add the elements of the first array
container[i] = array1[i];
}
//the for loop that adds the second array elements
for(int i = 0; i < arrayLength2; i++){
//add the second array elements on top of the first
container[i + arrayLength1] = array2[i];
}
for(int i = 0; i < containerArrayLength; i++){
//print all the elements
System.out.println(container[i]);
}
}
它的作用:
它遍历第一个数组并添加数字,然后遍历第二个数组并将元素添加到第一个数组元素之上。
你的算法看起来基本正确。没有 运行 通过确切的代码,我认为你的问题主要是你有太多的平等,即几乎每一个比较你有等于,小于等于,大于等于。
如果 a==b,则 a<=b 和 a>=b。因此,太多的 if 语句匹配。密切关注具体索引应该是什么,并将您的案例限制在它们应该是什么。
我已经重写了您的代码(抱歉,没有编辑器,所以它可能无法开箱即用)这应该会给您一个很好的主意。
public class Two
{
public static void main(String[] args)
{
//sample problem
int[] arrayA = {2,3,5,5,8,10,11,17,18,20};
int[] arrayB = {5,6,7,8,14,15,17};
final int sizeA = arrayA.length();
final int sizeB = arrayB.length();
final int sizeC = sizeA+sizeB;
int[] arrayC = new int[sizeC];
int countA = 0;
int countB = 0;
int countC = 0;
for (countC = 0; countC < sizeC; countC++)
{
// if a has run out, fill with b
if (countA == sizeA && countB < sizeB)
{
arrayC[countC] = arrayB[countB];
countB++;
}
// if b has run out, fill with a
else if (countA < sizeA && countB == sizeB)
{
arrayC[countC] = arrayA[countA];
countA++;
}
// countA < sizeA && countB < sizeB because
// if countA == sizeA && countB == sizeB then also countC == sizeC
// and the for-loop would have stopped.
else
{
// mind, if arrayA[countA] == arrayB[countB] then first
// a will be added and on the next pass b will be added
if (arrayA[countA] <= arrayB[countB])
{
arrayC[countC] = arrayA[countA];
countA++;
}
else
{
arrayC[countC] = arrayB[countB];
countB++;
}
}
}
}
}
我有一个项目需要我合并两个排序的数组(a 和 b)并将结果放入一个长度为 a.length + b.length 的新数组中。 我正在跟踪我在所有 3 个数组中的位置计数器,并且我的数组长度不相等。我的约定是,如果一个数组先于另一个数组用完,代码只会将另一个数组的其余部分转储到结果数组中。
不幸的是,我可以检查另一个数组是否仍然包含元素的唯一方法是查看 for 循环。
谁能帮帮我?这应该是一个相对容易的修复,但我想不出解决方案。
public class Two {
public static void main(String[] args) {
//sample problem
int[] var_a = {2,3,5,5,8,10,11,17,18,20};
int[] var_b = {5,6,7,8,14,15,17};
final int a_size = 10;
final int b_size = 7;
final int c_size = 17;
int[] var_c = new int[17];
int aCount = 0;
int bCount = 0;
int cCount = 0;
for (cCount = 0; cCount < c_size; cCount++) {
//b runs out before a runs out
if ((bCount == b_size) && (aCount <= a_size)) {
//dump rest of var_a into var_c
var_c[cCount] = var_a[aCount];
aCount++;
}
//PROBLEM: bCount is equal to bSize, and is triggering the break.
//a runs out before b runs out
else if ((aCount == a_size) && (bCount <= b_size)) {
//dump rest of var_b into var_c
var_c[cCount] = var_b[bCount];
bCount++;
}
if ((aCount >= a_size) || (bCount >= b_size) || (cCount >= c_size)) {break;}
if (var_a[aCount] < var_b[bCount]) {
var_c[cCount] = var_a[aCount];
aCount++;
} else if (var_a[aCount] > var_b[bCount]) {
var_c[cCount] = var_b[bCount];
bCount++;
} else if (var_a[aCount] == var_b[bCount]) {
var_c[cCount] = var_a[aCount];
aCount++;
cCount++;
var_c[cCount] = var_b[bCount];
bCount++;
}
}
for (int i : var_c) {
System.out.print(i + " ");
}
}
}
您可以遍历单个数组的索引,而不是遍历合并数组的索引,以确保您永远不会越界:
int aCount = 0;
int bCount = 0;
int cCount = 0;
while (aCount < var_a.length && bCount < var_b.length) {
if (var_a[aCount] <= var_b[bCount]) {
var_c[cCount++] = var_a[aCount++];
} else {
var_c[cCount++] = var_b[bCount++];
}
}
// now add what remains of var_a or var_b
while (aCount < var_a.length)
var_c[cCount++] = var_a[aCount++];
while (bCount < var_b.length)
var_c[cCount++] = var_b[bCount++];
此问题的常见解决方案是将单个循环替换为三个循环:
- 第一个循环合并两个数组,直到其中一个用完元素
- 第二个循环将数组
A
的剩余元素转储到输出数组中 - 第三个循环将数组
B
的剩余元素转储到输出数组 中(如果有的话)
这个结构可以让合并循环变得更简单:
while (aCount != var_a.length() && b.Count != var_b.length()) {
... // merge
}
while (aCount != var_a.length()) {
var_c[cCount++] = var_a[aCount++];
}
while (bCount != var_b.length()) {
var_c[cCount++] = var_b[bCount++];
}
注意最后两个循环最多执行一个。还要注意使用length()
方法来确定数组的长度。比设置a_size
、b_size
等靠谱
此代码应遵循
的简单逻辑- 将所有 3 个 a_counter、b_counter、c_c 的计数器初始化为 0
- 现在直到 a_c 或 b_counter 分别小于 a_size 和 b_size
- 将 a[a_counter] 与 b[b_counter] 进行比较,并将较小的添加到 c 的 c[c_c倒数]
- 增加c_c计数器,以及上面选择的
- 重复
- 一旦跳出循环,a或b之一就结束了
- 如果b结束,继续向c添加a的所有剩余元素;或 b 如果 a 结束 我相信你不需要代码,只需要改进逻辑;所以不给代码。
这可能是您想要的:
void doArrayThing(){
//the two arrays containing the elements
int[] array1 = {1, 3, 5, 2, 7, 5};
int[] array2 = {3, 6, 2, 8};
//the length of the 2 arrays
int arrayLength1 = array1.length;
int arrayLength2 = array2.length;
//the length of both the arrays
int containerArrayLength = arrayLength1 + arrayLength2;
//the array that holds all the elements
int[] container = new int[containerArrayLength];
//a for loop that adds the first array elements
for(int i = 0; i < arrayLength1; i++){
//add the elements of the first array
container[i] = array1[i];
}
//the for loop that adds the second array elements
for(int i = 0; i < arrayLength2; i++){
//add the second array elements on top of the first
container[i + arrayLength1] = array2[i];
}
for(int i = 0; i < containerArrayLength; i++){
//print all the elements
System.out.println(container[i]);
}
}
它的作用:
它遍历第一个数组并添加数字,然后遍历第二个数组并将元素添加到第一个数组元素之上。
你的算法看起来基本正确。没有 运行 通过确切的代码,我认为你的问题主要是你有太多的平等,即几乎每一个比较你有等于,小于等于,大于等于。
如果 a==b,则 a<=b 和 a>=b。因此,太多的 if 语句匹配。密切关注具体索引应该是什么,并将您的案例限制在它们应该是什么。
我已经重写了您的代码(抱歉,没有编辑器,所以它可能无法开箱即用)这应该会给您一个很好的主意。
public class Two
{
public static void main(String[] args)
{
//sample problem
int[] arrayA = {2,3,5,5,8,10,11,17,18,20};
int[] arrayB = {5,6,7,8,14,15,17};
final int sizeA = arrayA.length();
final int sizeB = arrayB.length();
final int sizeC = sizeA+sizeB;
int[] arrayC = new int[sizeC];
int countA = 0;
int countB = 0;
int countC = 0;
for (countC = 0; countC < sizeC; countC++)
{
// if a has run out, fill with b
if (countA == sizeA && countB < sizeB)
{
arrayC[countC] = arrayB[countB];
countB++;
}
// if b has run out, fill with a
else if (countA < sizeA && countB == sizeB)
{
arrayC[countC] = arrayA[countA];
countA++;
}
// countA < sizeA && countB < sizeB because
// if countA == sizeA && countB == sizeB then also countC == sizeC
// and the for-loop would have stopped.
else
{
// mind, if arrayA[countA] == arrayB[countB] then first
// a will be added and on the next pass b will be added
if (arrayA[countA] <= arrayB[countB])
{
arrayC[countC] = arrayA[countA];
countA++;
}
else
{
arrayC[countC] = arrayB[countB];
countB++;
}
}
}
}
}