递归基础练习

判断数组 a 中是否包含了数值 x

bool IsContained(int a[], int n, int x)
{
    bool ret = false;

    if(n > 0)
    {
        ret = (a[n - 1] == x) || IsContained(a, n - 1, x);
    }

    return ret;
}

判断数组 a 是否有序

bool IsOrdered(int a[], int n, bool min2max = true)
{
    bool ret = true;

    if(n > 1)
    {
        ret = (min2max ? (a[n - 1] >= a[n - 2]) : (a[n - 1] <= a[n - 2])) && IsOrdered(a, n - 1, min2max);
    }

    return ret;
}

查找数组 a 中的最大值

常规解法如下:

int MaxInArray(int a[], int begin, int end)
{
    int ret = -9999;

    if(begin == end)
    {
        ret = a[begin];
    }
    else
    {
        int bv = a[begin];
        int rv = MaxInArray(a, begin + 1, end);

        ret = (bv > rv) ? bv : rv;
    }

    return ret;
}

int MaxInArray(int a[], int n)
{
    return MaxInArray(a, 0, n - 1);
}

这种解法的递归深度更深,它的空间复杂度更高

优化后的解法如下:

int MaxInArray(int a[], int begin, int end)
{
    int ret = -9999;

    if(begin == end)
    {
        ret = a[begin];
    }
    else
    {
        int mid = (begin >> 1) + (end >> 1) + (begin & end & 1);  // 防止 begin + end 溢出,等价于 begin + (end - begin) / 2

        int lmax = MaxInArray(a, 0, mid);
        int rmax = MaxInArray(a, mid + 1, end);

        ret = (lmax > rmax) ? lmax : rmax;
    }

    return ret;
}

int MaxInArray(int a[], int n)
{
    return MaxInArray(a, 0, n - 1);
}

它的递归深度为常规解法的一半,它的空间复杂度更低。

求一个字符串的所有子集

DynamicArray<String> SubSet(String set)
{
    DynamicArray<String> ret;

    /* 当 set 为空时,只有一个空集 */
    if(set.length() == 0)
    {
        ret.resize(1);

        ret[0] = "";
    }
    /* 当 set 只有一个元素时,它的子集为空集和包含这一个元素的集合 */
    else if(set.length() == 1)
    {
        ret.resize(2);

        ret[0] = "";
        ret[1] = set;
    }
    /* 当 set 大于一个元素时 */
    else
    {
        ret = SubSet(set.sub(1));  // 求出除了第一个元素的这个字符串的所有子集
        ret.resize(ret.length() * 2);  // 将当前元素并入子集当中,所以这个数组要扩大到原来的2倍

        /* 将 set 的第一个元素并入子集中,并将并入的集合放入数组空余位置处 */
        for(int i = 0, j = ret.length() / 2; j < ret.length(); i++, j++)
        {
            ret[j] = String(set[0]) + ret[i];
        }
    }

    return ret;
}

删除无序链表中的重复结点

思路如下图所示:

template<typename T>
class WorkList : public LinkList<T>
{
protected:
    typedef typename LinkList<T>::Node  Node;

    /* 删除链表中的重复结点 */
    void rmdup(Node* head)
    {
        if(head != nullptr)
        {
            rmdup(head->next);  // 删除除去当前结点的子链表中的重复结点
            rmdup(head, head->value);  // 通过当前结点删除子链表中存在与当前结点值相同的结点
        }
    }

    /* head 为头结点(待删除链表的前一个结点),通过 val 删除相同值的结点 */
    void rmdup(Node* head, int val)
    {
        while(head->next != nullptr)
        {
            if(head->next->value == val)
            {
                Node* toDel = head->next;

                head->next = toDel->next;
                delete toDel;
            }
            else
            {
                head = head->next;
            }
        }
    }

public:
    void rmdup()
    {
        rmdup(this->m_header.next);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值