Determine the return value type of writing recursive functions and backtracking functions

Encountering such a question on Likou is not difficult in itself. DFS solved it in one go, but it triggered my thinking about the definition of return value type of recursive functions.

Topic description and problem introduction

The title and class definitions are as shown below:

// Definition for a Node.
class Node {
public:
    int val;
    Node* left;
    Node* right;

    Node() {}

    Node(int _val) {
        val = _val;
        left = NULL;
        right = NULL;
    }

    Node(int _val, Node* _left, Node* _right) {
        val = _val;
        left = _left;
        right = _right;
    }
};

my thinking

From an intuitive perspective, the question requires outputting the kth largest value, so would it be better to define a dfs function and the return value of this function should be of type int?

However, looking at the solution to the problem, the common way to write the solution to Gaozan's problem is to define the dfs function as void, or to define a global variable to store the result, as shown in the figure below

class Solution {
public: 
    int res;
    int kthLargest(TreeNode* root, int k) {
        dfs(root,k);
        return res;
    }
    void dfs(TreeNode* root ,int &k) //传引用 这里需要保证所有dfs函数共用一个k 
    {
        if(!root) return;
        dfs(root->right,k); //右
        k--;
        if(!k) res = root->val; //根
        dfs(root->left,k); //左
    }
};

Or this way, put the result in the parameter list and modify it recursively. Remember to quote the parameter type.

class Solution {
public: 
    int kthLargest(TreeNode* root, int k) {
        dfs(root,k);
        return res;
    }
    void dfs(TreeNode* root ,int &k,int& res) //传引用 这里需要保证所有dfs函数共用一个k 
    {
        if(!root) return;
        dfs(root->right,k); //右
        k--;
        if(!k) res = root->val; //根
        dfs(root->left,k); //左
    }
};

So can the return value be defined as int? That's okay, but it's more abstract to understand, because every time a recursion is called, a return value is generated, which means that when a tree is executed, it will return many int values. Which of these values ​​represent the answer? Which values ​​can be discarded? Or is the answer the sum or operation result of these return values? These are all issues to consider. For this question, at most one int value is the answer to the question, and other return values ​​should be ignored. The modified code is shown below:

class Solution {
public: 
    int kthLargest(TreeNode* root, int k) {
        return dfs(root, k);
    }

    int dfs(TreeNode* root, int& k) {
        if (!root) return -1; // Return -1 to indicate no valid kth element found.
        
        int rightResult = dfs(root->right, k); // Explore right subtree
        
        // If kth element is found in the right subtree, return it.
        if (k == 0) return rightResult;
        
        k--; // Decrement k since we are now visiting the current node.
        
        // If kth element is found in the current node, return it.
        if (k == 0) return root->val;
        
        return dfs(root->left, k); // Explore left subtree if kth element is not found yet.
    }
};

The explanation of this code is to traverse the right-middle-left subtree and return the answer when the k-th value is traversed. Otherwise, continue traversing, return dfs(root -> left, k), until a suitable return value can be found. The process is not very clear at first glance, but the running results are indeed the same.

Summarize

Whether the return value of a recursive function should be used voiddepends on the specific needs and implementation of the function. In many cases, recursive functions do not need to return a value because their purpose is to solve a problem through recursive calls rather than return a specific result. In this case, using voidas return value type is appropriate.

One advantage of using voida recursive function that returns a value is simplicity, because there is no need to deal with the return value, which reduces the complexity and potential errors of the code. The answer can be placed in a private variable, or in the parameters of the recursive function, so that the code is more readable. It is highly readable and easy to modify and debug later.

To find the kth largest element in a binary search tree, you need to find and return the kth largest element value. In this case we might use a similar intreturn value type. As shown above, int return value can achieve the effect.

To determine the appropriate return value type, consider the following factors:

  1. Nature of the problem : Depending on the nature of the problem, determine whether a specific result needs to be returned. Some problems require getting results from recursion and some don't.

  2. Purpose of the function : Determine what the main goal of the recursive function is. If the main goal is to solve a problem and there is no need to return a specific result, then voidreturning a value is appropriate.

  3. Code Complexity : Sometimes, handling return values ​​in a recursive function can increase the complexity of the code. If you can avoid using return values, you can make your code more concise and readable.

  4. Global variables or reference parameters : In some cases, you can use global variables or reference parameters to get the results of a recursive function without using the return value.

It is recommended that novices like me should not be fancy and write down the process and logic honestly. If you make a mistake, you can debug it. Intuition is the most important thing.

 

Guess you like

Origin blog.csdn.net/weixin_43694670/article/details/132009282