假设数组A:1,2,3,1,1,3。不同的整数应在数组B中:1,2,3。然后,函数应打印:[1,1][1,2][1,3][2,1][2,2][2,3][3,1][3,2][3,3]。
我试图解决不重复的整数问题,但没有递归
#include <iostream>
#include <algorithm>
using namespace std;
void uniqueNumber(int A[], int n, int B[], int &dimB ){
sort(A, A+n);
for( int i = 0; i < n; i++ ){
if( A[i] == A[i+1] ){
continue;
}
else {
B[dimB++] = A[i];
}
}
}
但问题是我必须以递归的方式解决它,有什么想法吗?
递归只是另一种循环方式。它通常是一种干净的方法,尽管它通常不会像实际的那样优化
或,而
循环并且除了尾部递归算法之外,它可以通过堆栈内存,除非数据大小很小,或者算法是对数或更好。这是一种线性算法(遍历数组),所以我不喜欢递归用于真正的解决方案,尽管这是一个很好的学习练习。
重要的是,使用递归时要考虑以下几点:数据的结构,不变量是什么(也就是说,在递归发生时,可以依靠什么保持为真),以及何时应该停止(“基本”情况)。
当您递归“遍历”数据时,通常一次只查看一个元素或一小块数据,以逐步构建解决方案。
有时,您必须在开始递归之前直接处理一些特殊情况。这对于处理不属于递归所需不变量的情况是必要的,例如当没有足够的数据来满足数据的预期“形状”时。
给定您的界面:
void uniqueNumber(int A[], int n, int B[], int &dimB );
我们已经知道了一些事情。首先,这不是一个好的界面。:)数组不是函数的安全参数,很容易出错。其次,dimB是一个“out”参数,除非有必要,否则不支持它(因为我们可以将大小作为函数返回值返回)第三,我们不知道B的大小,但必须假设它至少与A一样大。(这是该接口的另一个安全问题。)
但假设函数签名是固定的,这就是我们必须处理的。那么我们想要什么呢?
目标:按排序顺序找到每个写入B的唯一数字,并更新dimB以告诉调用者有多少项目写入B。
所以基本上我们想这样做:
A[i]
)与之前的值(A[i-1]
)不同,则将当前值附加到B,并增加dimB 上面的不变量是:
主要步骤将是:
>
否则我们的不变量就会满足:我们至少有一个元素。第一个元素保证不在B中,所以排序A,然后立即将A[0]添加到B中,然后开始递归。当A的大小正好为1时,也可以处理这种情况。递归将立即返回。
通常,递归算法由两个函数编写:第一个函数处理特殊情况并进行其他设置,然后调用第二个函数进行递归工作,知道所有特殊情况都已处理。
考虑到上述因素后,这里是uniqueNumbers函数:
void uniqueNumber(int A[], int n, int B[], int &dimB ) {
if (n > 0) {
std::sort(A, A+n);
B[dimB++] = A[0];
detail::uniqueNumberRec(1, A, n, B, dimB);
}
}
由于递归帮助函数不是直接调用的,而是实现细节,我把它放在细节
命名空间中,这是记录用户不应该直接调用它的常见做法,它也有助于将混乱排除在全局命名空间之外。
那么递归函数是做什么的呢?
它采用当前索引和初始函数采用的参数,这是上述描述的直接结果:
namespace detail {
void uniqueNumberRec(int curIdx, int A[], int n, int B[], int &dimB ) {
// Base case: stop when we reach the end
if (curIdx == n) {
return;
}
// if current element differs from previous, include it in answer
if (A[curIdx] != A[curIdx-1]) {
B[dimB++] = A[curIdx];
}
// recurse onto next element in sequence, so increment curIdx
uniqueNumberRec(curIdx + 1, A, n, B, dimB);
}
} // namespace detail
重要的是要注意传递到递归函数(从initail函数)的初始索引是1
,而不是0
,因为我们已经将第一个元素添加到输出中,所以已经过去了。
只要我们知道反复调用的curIdx 1最终将达到n,我们就知道递归将取得进展并将终止。我们已经在第一个函数中验证了n为正。
有几件事值得注意:
同样值得注意的是:代码中有一个bug:
if( A[i] == A[i+1] ){
如果i是A中的最后一项,则A[i 1]读取超出界限。这是不可接受的。这就是为什么我在确保有前一个之后,阅读了前一个。
编译器资源管理器示例:https://godbolt.org/z/8z3cf5Tab
我可以提供你的问题的解决方案,使用算法深度优先搜索。
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
void showContentSet(std::set<int>& input)
{
for(auto iterator=input.begin(); iterator!=input.end(); ++iterator)
{
std::cout<<*iterator<<", ";
}
return;
}
void dfs(int current, int previous, std::vector<int>& first, std::set<int>& second, std::vector<int>& visited)
{
if(visited[current]==1)
{
return;
}
visited[current]=1;
for(int next=(current+1); next<first.size(); ++next)
{
if(next==previous)
{
continue;
}
if(first[next]==first[current])
{
continue;
}
else
{
second.insert(first[current]);
second.insert(first[next]);
}
dfs(next, current, first, second, visited);
}
if(current==0)
{
for(auto& item : second)
{
for(auto& itemSet : second)
{
std::cout<<"["<<item<<", "<<itemSet<<"]"<<", ";
}
}
}
return;
}
void solve()
{
const int maximumSize=20;
std::vector<int> visited(maximumSize, 0);
std::vector<int> inputVector={1, 2, 3, 1, 1, 3};
std::set<int> inputSet;
dfs(0, -1, inputVector, inputSet, visited);
return;
}
int main()
{
solve();
return 0;
}
结果如下:
[1, 1], [1, 2], [1, 3], [2, 1], [2, 2], [2, 3], [3, 1], [3, 2], [3, 3],
我是新的编码和需要作出曼德尔布罗特函数。对于那些不知道的人来说,Mandelbrot集合是一组复数。从本质上讲,你可以从一个复数开始,然后把它平方,然后把它加到原来的复数中。例如,如果我使用数字1,集合将是0、1、2、5、26。。。我从0,1,(1^2)1=2,(2^2)1=5,(5^2)1=26得到这个值。现在,我的递归函数应该使用两个输入来求这个集合的和:一个数字n,它是我们进入集合的距离。例
主要内容:斐波那契数列,数字阶乘,多个函数组成递归很对编程语言都支持递归函数,Go语言也不例外,所谓递归函数指的是在函数内部调用函数自身的函数,从数学解题思路来说,递归就是把一个大问题拆分成多个小问题,再各个击破,在实际开发过程中,递归函数可以解决许多数学问题,如计算给定数字阶乘、产生斐波系列等。 构成递归需要具备以下条件: 一个问题可以被拆分成多个子问题; 拆分前的原问题与拆分后的子问题除了数据规模不同,但处理问题的思路是一样的; 不能无限制的
递归,就是在运行的过程中调用自己。 语法格式如下: func recursion() { recursion() /* 函数调用自身 */ } func main() { recursion() } Go 语言支持递归。但我们在使用递归时,开发者需要设置退出条件,否则递归将陷入无限循环中。 递归函数对于解决数学上的问题是非常有用的,就像计算阶乘,生成斐波那契数列等。 阶乘 以下实
主要内容:递归的进入,递归的退出,递归的条件,更多关于递归函数的内容一个函数在它的函数体内调用它自身称为 递归调用,这种函数称为 递归函数。执行递归函数将反复调用其自身,每调用一次就进入新的一层,当最内层的函数执行完毕后,再一层一层地由里到外退出。 递归函数不是C语言的专利, Java、 C#、 JavaScript、 PHP 等其他编程语言也都支持递归函数。 下面我们通过一个求阶乘的例子,看看递归函数到底是如何运作的。阶乘 n! 的计算公式如下: 根据公式编写如
我或多或少只是在学习C语言,我被分配了一个简单的任务,处理双链表、动态数据分配和递归。我创建了一个只有10个整数的数组,我试图使用递归将这些整数放入一个排序的双链表中。我在向链表中插入节点时遇到了一些问题;我想我已经搞定了第一个节点,但我不确定其他节点是否有意义。现在我也遇到了一个分割错误。。。谢谢你的帮助!
我有一个很难处理的任务。 我试图编写一个递归函数(完全没有循环),给定一个数组及其长度,它将打印一对子数组,每个子数组的和将是整个数组和的一半。换句话说,数组被分成两组整数,以便它们的和相等。 例如,给定数组{1,2,2,0,5},函数应输出{1,2,2}{0,5} 我必须递归地做,用一个只得到数组本身及其大小的函数。我也只允许使用一个额外的递归函数来解决这个问题。 任何想法或想法都将受到最大的赞