【问题标题】:Print out and sort values inside LinkedList打印出 LinkedList 中的值并对其进行排序
【发布时间】:2022-06-11 06:26:01
【问题描述】:

我为所谓的“硬币找零问题”写了一个递归回溯算法。我将硬币值(int)存储在一个自写的 LinkedList(“ll”)中,每个 LinkedList 都存储在一个主 LinkedList(“ll_total”)中。现在,当我尝试打印主 LinkedList 中的 LinkedLists 时,我得到的只是“LinkedList@1e88b3c”。有人可以告诉我如何修改代码,以便正确打印硬币值吗?

我还希望算法选择其中存储的值最少的 LinkedList,因为它代表“硬币找零问题”的最佳硬币组合。

import java.util.Scanner;

public class CoinChange_Backtracking {
        
    static int[] coins = {3, 2, 1};
    static int index_coins = 0;
    static int counter = 0;
    static LinkedList ll = new LinkedList();
    static LinkedList ll_total = new LinkedList();
    
    
    public static void main(String[] args) {
        Scanner myInput = new Scanner(System.in);
        int amount;
        System.out.println("Put in the amount of money: ");
        amount = myInput.nextInt();
        if (amount < 101) {
            //Start recursion and display result.
            recursiveFunction(coins, amount, index_coins, ll);
            ll_total.show_ll();
        } else {
            System.out.println("The value must be less than 100!");
        }
    }

    
    public static LinkedList recursiveFunction(int[] coins, int amount, int index_coins, LinkedList ll) {
        //The current coin is being omitted. (If index_coins + 1 is still within range.)
        if ((index_coins + 1) < coins.length) {
            ll = recursiveFunction(coins, amount, index_coins + 1, ll);
            ll_total.insert_ll(ll);
            for (int i = 0; i < counter; i++) {
                ll.deleteAt(0);
            }
            counter = 0;
        }
        
        //The current coin is not being omitted. (If there is still some change left and value of change isn't lower than value of current coin.)
        if (amount != 0) {
            if (amount >= coins[index_coins]) {
                ll.insert(coins[index_coins]);
                counter++;
                ll = recursiveFunction(coins, amount - coins[index_coins], index_coins, ll);
            }
        }
        return ll;
    }
}
public class LinkedList {
    Node head;
    
    public void insert(int data) {
        Node node = new Node();
        node.data = data;
        node.next = null;
        if (head == null) {
            head = node;
        } else {
            Node n = head;
            while(n.next != null) {
                n = n.next;
            }
            n.next = node;
        }
    }
    
    public void insert_ll(LinkedList ll) {
        Node node = new Node();
        node.ll = ll;
        node.next = null;
        if (head == null) {
            head = node;
        } else {
            Node n = head;
            while(n.next != null) {
                n = n.next;
            }
            n.next = node;
        }
    }
    
    public void deleteAt(int index) {
        if(index == 0) {
            head = head.next;
        } else {
            Node n = head;
            Node n1 = null;
            for (int i = 0; i < index - 1; i++) {
                n = n.next;
            }
            n1 = n.next;
            n.next = n1.next;
            n1 = null;
        }
    }
    
    public void show() {
        Node node = head;
        while(node.next != null) {
            System.out.println(node.data);
            node = node.next;
        }
        System.out.println(node.data);
    }
    
    public void show_ll() {
        Node node = head;
        while(node.next != null) {
            System.out.println(node.ll);
            node = node.next;
        }
        System.out.println(node.ll);
    }
    
    //A toString method I tried to implement. Causes an array error.
    /*
    public String toString() {
        Node n = head.next;
        String temp = "";
        while (n != null) {
            temp = temp + n.data + " ";
            n = n.next;
        }
        return temp;
    }
    */
}
public class Node {
    int data;
    LinkedList ll;
    Node next;
}

【问题讨论】:

  • 我猜,我需要在 LinkedList 类中定义一个 toString 方法,但是当我尝试它时,我得到一个数组错误。

标签: java recursion linked-list backtracking coin-change


【解决方案1】:

回答你的问题。您正在打印链表对象,请参阅此处System.out.println(node.ll);

有几种方法可以做到这一点。一种方法是质疑您为什么要以这种方式使用NodeLinkedList?一个节点可以有一个链表,一个链表也可以有一个节点,我相信这不是你真正想要的。也许你可以让它工作,但根据我的经验,从设计的角度来看,它并不好。我觉得它很混乱,而且它是错误的重要来源。

我尝试列出一些引起我注意的点(或者我的 IDE 引起我注意的点)。

  • 您没有关闭Scanner 对象。只需在程序结束时将其关闭或使用try-with-resources
  • 如前所述,您有一个具有节点的链表和一个具有链表的节点。您在程序中没有正确使用它。我建议审查这种方法。这很容易出错。
  • 除非您有充分的理由不这样做,否则只需使用 Java 库的 LinkedList。它运行良好,可满足您的所有需求。
  • 您使用了许多静态、全局(在包范围内)变量。在这种情况下,我认为您可以避免这种情况。 coins 不需要每次都作为参数给出。它应该是一个不可变的对象。它不应该改变。
  • ...

我不确定它是否是回溯算法。它当然是树递归的。这只是一个旁注。

我想提出一个与您的解决方案相似的解决方案。我可能会以不同的方式做这件事,但是理解它可能需要时间。我尝试采用您的风格,希望对您有所帮助。我简化了程序。

为了打印结果,只需编写一个辅助函数。
链表是一个对象。每次调用递归时,您都必须制作列表的副本才能处理专用对象。否则,您会在递归不同的路径时修改同一个对象。
您可以简单地使用列表列表。列表的全局列表(在包范围内),以及每次递归时复制的列表。当您达到一个好的基本案例时,您将其添加到全局列表中。否则直接忽略。

import java.util.LinkedList;
import java.util.Scanner;

public class CoinChangeBacktracking {

  static final int[] COINS = {3, 2, 1};
  static final LinkedList<LinkedList<Integer>> changes = new LinkedList<>();

  public static void main(String[] args) {

    Scanner myInput = new Scanner(System.in);
    int amount;
    System.out.println("Put in the amount of money: ");
    amount = myInput.nextInt();
    if (amount < 101) {
      // Start recursion and display result.
      recursiveFunction(amount, 0, new LinkedList<>());
      print(changes);
    } else {
      System.out.println("The value must be less than 100!");
    }
    myInput.close();
  }

  static void recursiveFunction(int amount, int index,
                                LinkedList<Integer> list) {

    // exact change, so add it to the solution
    if (amount == 0) {
      changes.add(list);
      return;
    }

    // no exact change possible
    if (amount < 0 || index >= COINS.length) {
      return;
    }

    // explore change of amount without current coin
    recursiveFunction(amount, index + 1, new LinkedList<>(list));

    // consider current coin for change and keep exploring
    list.add(COINS[index]);
    recursiveFunction(amount - COINS[index], index, new LinkedList<>(list));
  }

  static void print(LinkedList<LinkedList<Integer>> ll) {
    for (LinkedList<Integer> list : ll) {
      for (Integer n : list) {
        System.out.print(n + ", ");
      }
      System.out.println();
    }
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-23
    • 1970-01-01
    • 2021-07-03
    • 2019-05-20
    • 2014-03-30
    • 2021-08-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多