【问题标题】:How can I check a LinkedList for several values after eachother?如何逐个检查链接列表中的多个值?
【发布时间】:2018-05-07 15:25:29
【问题描述】:

我想制作一个以简单方式分配电影院座位的应用程序。

我有一个 LinkedList,其中随机填充 0“有座位”或 1“有座位”。这个 LinkedList 是由变量 int 'seatsTotal' 生成的,LinkedList 然后用 Math.random 函数填充 1 或 0。

这个想法是,用户提供一个变量,即他们想要预订多少个座位,之后,一个(可能是递归的)方法将寻找(例如)5 个标有 0(可用)的座位。

如果在彼此之后(相邻)没有 5 个可用座位,则该方法必须寻找 4 个可用座位和 1 个单独的座位。如果没有 4 个席位,应用程序将寻找 3 个席位和 2 个席位等。

我的第一个问题是;我知道我可以使用 LinkedList.contains() 检查某个值是否存在,但我如何检查(例如)0 是否连续出现 5 次?

我的第二个问题是;如果没有 5 个座位​​可用,我将不得不寻找 4 个座位和 1 个座位(例如),我该如何处理?

我真的很困惑,非常感谢您的帮助。

public class Main {

    static int seatCount = 10;
    int verzoekAantal = 3;
    int consecutiveLength = 0; // Consecutive free seats length
    int index = 0;
    int startIndex = -1; // Store the start of consecutive free seats
    LinkedList<Seat> consecutiveList = new LinkedList<>(); // Store startIndex -> length

    public static void main(String[] args) {
//        System.out.println(Arrays.toString(fillList(seatCount).toArray()));
        System.out.println(fillSeats(3).toString());
    }

    //Deze methode geeft via de Math package een willekeurig getal, 1 (bezet) of 0 (vrij)
    static int giveRandomAvailability() {
        return intValue(Math.random() * 2);
    }


    //Deze methode creëert een LinkedList van grootte 'seatCount' en vult de plaatsen een voor een met 0 of 1 op willekeur
    static LinkedList fillList(int seats){
        LinkedList<Seat> list = new LinkedList<Seat>();
        seats = seatCount;

        for(int i = 0; i < seats; i++){
            Seat seat = new Seat();
            seat.availability = giveRandomAvailability();
            seat.seatNumber = (i + 1);
            list.add(seat);
        }

        return list;
    }

    static Map fillSeats(int n){
        LinkedList<Seat> newList = fillList(seatCount);
        int consecutiveLength = 0; // Consecutive free seats length
        int index = 0;
        int startIndex = -1; // Store the start of consecutive free seats
        int remConsecutiveLength = 0;
        System.out.println(newList.toString());
        Map<Integer, Integer> consecutiveMap = new HashMap<>(); // Store startIndex -> length

        for (Seat seat : newList) {
            if (seat.IsFree()) {
                if (startIndex < 0) {
                    startIndex = index;
                }
                consecutiveLength ++;
            } else {
                consecutiveMap.put(startIndex + 1, consecutiveLength);
                if (consecutiveLength >= n) {
                    System.out.println("SEATS FOUND, " + n + " seats available counting from " + (seat.seatNumber - n));
                }

//                if(consecutiveLength > remConsecutiveLength) {
//                    remConsecutiveLength = consecutiveLength;
//                }
                startIndex = -1;
                consecutiveLength = 0;
            }
            index++;
        }
        if (startIndex >= 0) {
            consecutiveMap.put(startIndex + 1, consecutiveLength);
        }
//                    if (remConsecutiveLength < n) {
//                    while(n > 1) {
//                        System.out.println("Looking for seats which are not next to eachother");
//                        n--;
//                        fillSeats(n);
//                    }
//                }
        Map<Integer, Integer> treeMap = new TreeMap<Integer, Integer>(consecutiveMap);
        return treeMap;
    }
}

【问题讨论】:

  • 对于问题的第一部分,您可以迭代链表。对于第二部分,这要复杂得多,我相信在开发能够提供最佳体验的座位算法方面已经做了很多工作。
  • @TimBiegeleisen 谢谢蒂姆。是的,毫无疑问,有很多很棒的算法可以解决这个问题,不过我的可以保持简单。
  • 创建一个方法并传递您希望彼此相邻的最大数量的座位,然后让您的方法在列表中返回这些座位。如果该方法找不到五个,它将返回它在遍历列表时找到的下一个最大数字
  • 您如何使用简单的LinkedList 处理行?任何给定的空间都不是单排,无限宽(甚至是圆形的剧院)。所以找到 N 个连续的 0 并不能说明太多,除非你知道它们在同一行。然后,当您想找到一些细分时,优先选择在空间上靠得很近的座位,而不是随机座位。
  • @KevinO 我很确定您可以编写条件逻辑来检查您是否在计算同一排的座位。

标签: java algorithm linked-list


【解决方案1】:

回答你问题的第一部分:

如果你想找到 n 个连续的空座位,你必须遍历你的 LinkedList 并计算空闲座位,直到你找到 n 个连续的空座位,或者你遍历所有座位。

public List<Seat> findNConsecutiveEmptySeats(List<Seat> seats, int n) {
    List<Seat> freeSeats = new LinkedList<Seat>();
    for(Seat s : seats) {
        if(s.isEmpty()) {
            freeSeats.add(s);
        } else {
            freeSeats.clear();
        }
        if(freeSeats.size() >= n) {
            break;
        }
     }
     if(freeSeats.size() < n) {
        freeSeats.clear();
     }
     return freeSeats;
}

要回答问题的第二部分,您需要使用 n=5 调用上一个方法。如果返回的列表包含 5 个席位,那么您找到了它们,请返回。如果它包含一个空列表,则使用 n=4 然后 n=1 调用该方法。等等……

public List<Seat> findNEmptySeats(List<Seat> seats, int n) {
    List<Seats> freeSeats = findNConsecutiveEmptySeats(seats, n);
    if(freeSeats.size() == n) {
        return freeSeats;
    }
    freeSeats = findConsecutiveEMptySeats(seats, n-1);
    freeSeats.addAll(findConsecutiveEMptySeats(seats, 1));
    if(freeSeats.size() == n) {
        return freeSeats;
    }
    freeSeats = findConsecutiveEMptySeats(seats, n-2);
    freeSeats.addAll(findConsecutiveEMptySeats(seats, 2));
    if(freeSeats.size() == n) {
        return freeSeats;
    }

    ...

}

注意:这段代码不完整,比如找n-1个座位后,需要先把找到的座位去掉再找1个座位,否则你可以退回一个已经找到的座位。

【讨论】:

  • 谢谢!我会尝试这种方法,并让您知道它是否对我有用。
【解决方案2】:

您需要找到连续的座位并将这些物品存放起来。

假设您将座位信息存储在 Seat 类中,我们将 List&lt;Seat&gt; seats 作为输入。 n 是您要查找的座位数。

int consecutiveLength = 0; // Consecutive free seats length
int index = 0;
int startIndex = -1; // Store the start of consecutive free seats
Map<Integer, Integer> consecutiveMap = new HashMap<>(); // Store startIndex -> length

for (Seat seat : seats) {
  if (seat.isFree()) {
    if (startIndex < 0) {
      startIndex = index;
    }
    consecutiveLength ++;
  } else {
    consecutiveMap.put(startIndex, consecutiveLength);
    if (consecutiveLength == n) {
      // Found, do something here
    }
    // Reset
    startIndex = -1;
    consecutiveLength = 0;
  }
  index++;
}

在此之后,您可以访问consecutiveMap 中的所有consecutiveLength

您也可以通过在上面的else 块中测试consecutiveLength == n 立即返回。

通过访问consecutiveLength 的每个数字,您可以选择子选项(4 个连续 + 1 个单,等等)

编辑

运行代码后,您的 consecutiveMap 将如下所示

{1 -> 1, 3 -> 4, 8 ->1, ...}

上面写着:在索引 1 处,有 1 个连续席位。

在索引 3 处,有 4 个连续席位。 ....

您通过consecutiveMap.values()访问列表中的连续长度

它会给你{1, 4, 1, 2, ...}

你的问题被简化为:在一个数组中选择几个项目,使它们的总和为n。您甚至可以对它们进行排序以从较大的连续长度到较小的连续长度。

这很简单。

你也可以在这里暴力破解,因为每排的座位数不是很大。

【讨论】:

  • 谢谢,这正是我想要的。它似乎很好地找到了可用的座位。但是,我不明白如何使用此代码处理非连续座位预订(例如 4 + 1)。你能解释一下吗?
  • 我是否可以假设 n 是此处预订所需的座位数量?
  • 明白了很多,谢谢,我一定会试一试的。
  • 您的代码运行良好,但如果 n = 5 并且没有 5 个连续的可用席位,我仍然不知道如何“重试”该方法。你能帮我解决这个问题吗?我将编辑我的问题,以便您查看我的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-16
  • 2021-10-06
  • 2012-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多