我正在尝试为一个问题陈述创建一个程序,该程序是一个数组游戏,其中2个人正在玩给定数组的游戏,其中人物A先行,而人物B交替玩。
由于玩家执行以下操作,因此每回合数组的长度减少1: 1.如果数组的长度为奇数,则从数组中删除中间数字。 2.如果长度是偶数,则玩家可以选择删除中间两个元素之一。
已删除元素的值将添加到当前玩家的分数中。 最后,获胜者由得分最高的人决定。如果两个人的得分都相同,则我们允许A人作为该游戏的发明者获胜。 两名球员都发挥最佳状态。
我为此编写了一个代码,但是在我的代码中,我实际上是在每个循环条件下修改现有数组,这是一项繁重的操作,需要更多的内存和时间。如果输入太大,我的程序将花费2秒钟以上的时间来运行。有什么方法可以优化下面的代码,从而避免修改/重新创建数组。
class TestClass {
public static void main(String args[]) throws Exception {
Scanner s = new Scanner(System.in);
int n = s.nextInt();
int arr[] = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = s.nextInt();
}
boolean aTurn = true;
int aScore = 0, bScore = 0;
int middle = 0;
while (n > 0) {
int point = 0;
int position = 0;
int size = arr.length;
if (size % 2 == 0) {
middle = size / 2;
if (arr[middle - 1] > arr[middle]) {
point = arr[middle - 1];
position = middle - 1;
} else {
point = arr[middle];
position = middle;
}
} else {
middle = (size) / 2;
if (middle == 0) {
point = arr[0];
position = 0;
} else {
point = arr[middle];
position = middle;
}
}
arr = removeElement(arr, position);
n--;
if (aTurn) {
aScore += point;
aTurn = false;
} else {
bScore += point;
aTurn = true;
}
}
if (aScore == bScore) {
System.out.println("Person_A 0");
} else if (aScore > bScore) {
System.out.println("Person_A " + (aScore - bScore));
} else {
System.out.println("Person_B " + (bScore - aScore));
}
}
public static int[] removeElement(int[] original, int element) {
int[] n = new int[original.length - 1];
System.arraycopy(original, 0, n, 0, element);
System.arraycopy(original, element + 1, n, element, original.length - element - 1);
return n;
}
}
答案 0 :(得分:1)
基本上,您需要的是一个数组,该数组之间可以有一个孔/间隙,并且每一步中的间隙都增加1。只能从间隙的任一端除去元素,而不能从任何随机位置除去。
com.yourcompany.product_name
使用此数据结构,您的代码如下。
//an array which has a gap in between and
//elements can be removed from either end of the gap.
private static final class GapArray
{
private final int[] array;
private int gapStart;
private int gapLength;
private GapArray(int[] array)
{
this.array = array;
this.gapStart = array.length;
}
int get(int index)
{
checkBounds(index);
if (index < gapStart)
{
return array[index];
}
else
{
return array[index + gapLength];
}
}
private void checkBounds(int index)
{
if (index < 0 || index >= size())
{
throw new ArrayIndexOutOfBoundsException(index);
}
}
//index is either just before start of the gap or just after end of gap.
int remove(int index)
{
checkBounds(index);
if (gapLength == 0)
{
gapStart = index;
gapLength++;
return array[gapStart];
}
else
{
if (index == gapStart - 1)
{
gapStart--;
gapLength++;
return array[gapStart];
}
else if (index == gapStart)
{
int value = array[gapStart + gapLength];
gapLength++;
return value;
}
else
{
throw new IllegalArgumentException("elements can be removed either end of the gap only");
}
}
}
int size()
{
return array.length - gapLength;
}
}
答案 1 :(得分:0)
还有另一种解决方案,该解决方案使用动态编程,并且可以反向进行。开始反向玩游戏。因此,在这种情况下,将从末端删除元素。实际上,您不必删除元素,只需维护新起点和终点的索引即可。尝试测试这个。
private static int[] method2(int[] arr)
{
boolean evenSize = arr.length % 2 == 0;
Score score = new Score(evenSize ? 1 : 0);
int start = 0;
int end = arr.length;
while (start < end)
{
if (start + 1 == end)
{
score.addPoints(arr[start]);
start++;
}
else
{
if (arr[start] < arr[end - 1])
{
score.addPoints(arr[start]);
start++;
score.addPoints(arr[end - 1]);
end--;
}
else
{
score.addPoints(arr[end - 1]);
end--;
score.addPoints(arr[start]);
start++;
}
}
}
return score.score;
}
private static class Score
{
int[] score = new int[2];
int turn;
Score(int turn)
{
this.turn = turn;
}
void addPoints(int point)
{
score[turn] += point;
turn = (turn + 1) % 2;
}
}