【问题标题】:c++ function return the smallest positive integer in a vectorc ++函数返回向量中的最小正整数
【发布时间】:2018-04-09 09:26:46
【问题描述】:

我正在使用下面的代码,它返回向量中的最小正整数。我得到了代码here。我的问题是有理由将大小传递给函数,你可以不在函数体中计算它吗?

第二个if() 测试是为了什么?我不明白这个 if 语句是如何工作的?

#include <vector>
using namespace std;
int rec_min_pos(const vector<int> & nums, int size) {
    if (size < 1) {
        return INT_MAX;
    }
    if(nums[size-1] > 0){
        return min(nums[size-1], rec_min_pos(nums, size-1));
    }
    else{
        return rec_min_pos(nums, size-1);
    }
}

【问题讨论】:

  • size 参数应该命名为 index 或其他名称。这很令人困惑,因为它与向量的大小没有任何关系。
  • 向量知道它们有多大。但请注意,该函数是递归的,它不会每次都对整个向量进行操作。
  • size 参数可能可以命名为last_elem,这是必要的,因为该函数以递归方式而不是循环工作。它实际上不是向量的大小,而是函数将搜索最小正元素的向量部分(第一次调用应该是完整大小,递归调用会查找更小的部分)。第二个 if 检查最后一个元素是否为负数,否则返回向量下一部分中找到的最佳值。
  • 当您忽略 size 参数并改用 nums.size() 时发生了什么?你从中学到了什么?哦,是的,当您在调试器中单步执行程序时看到了什么?
  • 顺便说一句,编写这样的递归函数不是很明智。更喜欢涉及std::min_element 和合适谓词的东西。 (例如[](int lhs, int rhs){ return std::tie(!std::signbit(lhs), lhs) &lt; std::tie(!std::signbit(rhs), rhs) }.

标签: c++ algorithm vector


【解决方案1】:

第二个if 语句检查元素的正数,因为函数应返回最小的正数整数。

您的函数是递归的,'size' 参数实际上是要测试的最后一个元素的索引的加一。这允许一个简单的递归函数设计,但需要一个额外的参数。在函数接口中明确说明这些点可能会更好

inline int recursive_min_positive(const int*arr, size_t i)
{
    return 
        i==0? std::numeric_limits<int>::max() :
        arr[i-1]<=0? recursive_min_positive(arr,i-1) :
        std::min(arr[i-1],recursive_min_positive(arr,i-1) ;
}

int min_positive(std::vector<int> const&arr)
{
    return recursive_min_positive(arr.data(), arr.size());
}

递归函数设计通常很优雅,但效率低下(尽管编译器倾向于展开递归)。在这里,非递归实现实际上更短更清晰。

int min_positive(std::vector<int> const&arr)
{
    int result = std::numeric_limits<int>::max();
    for(auto val : arr)
        if(0 < val  &&  val < result) result = val;
    return result;
}

【讨论】:

    【解决方案2】:

    除了所有的 cmets:你可以像这样重载函数:

    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    
    // Original function with size argument
    int rec_min_pos(const vector<int> & nums, int size) {
      if (size < 1) {
        return INT_MAX;
      }
      if (nums[size - 1] > 0) {
        return min(nums[size - 1], rec_min_pos(nums, size - 1));
      }
      else {
        return rec_min_pos(nums, size - 1);
      }
    }
    
    // Overloaded rec_min_pos function
    int rec_min_pos(const vector<int> & nums) {
        // here we just call the original rec_mon_pos function
        return rec_min_pos(nums, nums.size());
    }
    
    int main()
    {
      vector<int> v{ 9,2,7,3,7,5,6 };
      cout << rec_min_pos(v);  // call the overloaded function
    }
    

    输出:

    2
    

    【讨论】:

    • 谢谢你的建议,这不编译你正在传递 2 个参数 return rec_min_pos(nums, nums.size());?
    • @arcoxiatom 我将截取的代码更改为完整的可编译示例。
    【解决方案3】:

    与递归函数无关,但扩展了我的评论:

    int min_positive(std::vector<int> & nums)
    {
        auto elem = std::min_element(nums.begin(), nums.end(), 
            [](int lhs, int rhs){ return std::tie(std::signbit(lhs), lhs) < std::tie(std::signbit(rhs), rhs); }
        );
        if ((elem == nums.end()) || std::signbit(*elems)) { return MAX_INT; }
        return *elem;
    }
    

    这里我们定义了一个比较函数,将正数排序在负数之前,然后按值排序。我们使用三个参数std::min_element,它将在nums 中找到一个迭代器。

    第一个检查处理一个空的nums,第二个检查每个值都是负数,这两者都被原始忽略,返回MAX_INT

    【讨论】:

      猜你喜欢
      • 2021-11-22
      • 1970-01-01
      • 1970-01-01
      • 2017-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-02
      • 1970-01-01
      相关资源
      最近更新 更多