[英]Is it possible to implement an algorithm to find the nth to last element of a singly linked list using recursion in java
我知道您可以通過使用計數器在每次通過鏈表中的節點時遞增來簡單地迭代解決這個問題; 還創建一個數組列表並設置在其中的每個節點找到的數據。 一旦您找到鏈表的尾部,只需從數組列表中的元素總數中減去第 N 項,您就可以返回答案。 但是,有人如何使用遞歸來執行此操作? 是否有可能,如果有,請顯示代碼以顯示您的天才:)。
注意:我知道你不能在 Java 中返回兩個值(但在 C/C++ 中,你可以使用指針:])
編輯:這是我在網上找到的一個簡單問題,但我添加了遞歸部分以使其成為對自己的挑戰,我發現這可能無法使用 Java。
訣竅是在遞歸之后做這項工作。 私有方法中的數組基本上用作對可變整數的引用。
class Node {
Node next;
int data;
public Node findNthFromLast(int n) {
return findNthFromLast(new int[] {n});
}
private Node findNthFromLast(int[] r) {
Node result = next == null ? null : next.findNthFromLast(r);
return r[0]-- == 0 ? this : result;
}
}
作為一般規則,任何可以用循環完成的事情也可以用任何合理語言的遞歸完成。 解決方案的優雅可能大不相同。 這是一個相當java慣用的版本。 為簡潔起見,我省略了常用的訪問器函數。
這里的想法是遞歸到列表的末尾並在遞歸展開時增加一個計數器。 當計數器達到期望值時,返回該節點。 否則返回空值。 非空值一直返回到頂部。 一次下降,一次上升。 最少的爭論。 無意不尊重亞當,但我認為這更簡單。
注意:OP 關於 Java 只能返回一個值的聲明是正確的,但由於該值可以是任何對象,因此您可以根據需要返回帶有字段或數組元素的對象。 然而,這里不需要。
public class Test {
public void run() {
Node node = null;
// Build a list of 10 nodes. The last is #1
for (int i = 1; i <= 10; i++) {
node = new Node(i, node);
}
// Print from 1st last to 10th last.
for (int i = 1; i <= 10; i++) {
System.out.println(i + "th last node=" + node.nThFromLast(i).data);
}
}
public static void main(String[] args) {
new Test().run();
}
}
class Node {
int data; // Node data
Node next; // Next node or null if this is last
Node(int data, Node next) {
this.data = data;
this.next = next;
}
// A context for finding nth last list element.
private static class NthLastFinder {
int n, fromLast = 1;
NthLastFinder(int n) {
this.n = n;
}
Node find(Node node) {
if (node.next != null) {
Node rtn = find(node.next);
if (rtn != null) {
return rtn;
}
fromLast++;
}
return fromLast == n ? node : null;
}
}
Node nThFromLast(int n) {
return new NthLastFinder(n).find(this);
}
}
好的,我認為這應該可以解決問題。 這是在C++
但它應該很容易轉換為Java
。 我也沒有測試。
Node *NToLastHelper(Node *behind, Node *current, int n) {
// If n is not yet 0, keep advancing the current node
// to get it n "ahead" of behind.
if (n != 0) {
return NToLastHelper(behind, current->next, n - 1);
}
// Since we now know current is n ahead of behind, if it is null
// the behind must be n from the end.
if (current->next == nullptr) {
return behind;
}
// Otherwise we need to keep going.
return NToLastHelper(behind->next, current->next, n);
}
Node *NToLast(Node *node, int n) {
// Call the helper function from the head node.
return NToLastHelper(node, node, n);
}
編輯:如果要返回最后一個節點的值,只需將其更改為:
int NToLast(Node *node, int n) {
// Call the helper function from the head node.
return NToLastHelper(node, node, n)->val;
}
如果 node 為空,此代碼將嚴重失敗。
遞歸函數:
int n_to_end(Node *no, int n, Node **res)
{
if(no->next == NULL)
{
if(n==0)
*res = no;
return 0;
}
else
{
int tmp = 1 + n_to_end(no->next, n, res);
if(tmp == n)
*res = no;
return tmp;
}
}
包裝函數:
Node *n_end(Node *no, int n)
{
Node *res;
res = NULL;
int m = n_to_end(no, n, &res);
if(m < n)
{
printf("max possible n should be smaller than or equal to: %d\n", m);
}
return res;
}
調用函數:
int main()
{
List list;
list.append(3);
list.append(5);
list.append(2);
list.append(2);
list.append(1);
list.append(1);
list.append(2);
list.append(2);
Node * nth = n_end(list.head, 6);
if(nth!=NULL)
printf("value is: %d\n", nth->val);
}
此代碼已使用不同的輸入進行了測試。 雖然它是 C++ 版本,但您應該能夠弄清楚邏輯:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.