一、递归与分治
1、算法思想
- 对k个子问题分别求解,如果子问题的规模仍然不够小,则再划分为k个子问题。 如此递归地进行下去,直到问题规模足够小,很容易求出其解为止。
- 将求出的小规模问题的解合并成一个更大规模的问题的解,自底向上逐步求出原来问题的解。
- 分治法的设计思想是,将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。
2、递归的概念
- 直接或者间接地调用自身的算法称为递归算法;用函数自身给出定义的函数称为递归函数。
- 分治法产生的子问题往往是原问题的较小模式,这就为使用递归技术提供了方便。原问题与子问题的唯一区别是输入规模不同。
- 在这种情况下,反复应用分治手段,可以使子问题与原问题类型一致而其规模却不断缩小,最终使子问题缩小到很容易直接求出其解。
- 分治与递归像一对孪生兄弟,经常同时应用在算法设计之中,并由此产生许多高效算法。
3、 分治的基本过程
- Divide:将问题的规模变小
- Conquer:递归的处理小规模问题(只需递归调用即可)
- Combine:将小规模问题的解合并为原始问题的解
这其中的重点是问题的分解和解的合并操作。
分解的要点是:
a.分解的条件要互斥;
b.分解后的所有条件加在一起,能够覆盖原始问题的所有情况。
二、LeetCode例题
1、restore-ip-addresses
(1)问题描述
现在有一个只包含数字的字符串,将该字符串重新存储成IP地址的形式,返回所有可能的情况。
例如:
给出的字符串为"25525511135",
返回[“255.255.11.135”, “255.255.111.35”]. (顺序没有关系)
Given a string containing only digits, restore it by returning all
possible valid IP address combinations. For example:
Given"25525511135",
return[“255.255.11.135”, “255.255.111.35”]. (Order does not matter)
(2)思路分析1
有效IP地址的条件有:
- 每段地址均小于等于255;
- 共有四段地址
递归方法:
- 取某段的地址,可能是1位、2位、3位
- 判断第一段地址是否有效,若有效,取下一段地址
- 将某段地址与下一段地址按输出格式连接起来
边界条件:
- 当字符串空或者超过四段时,出错,返回
- 当子段首位为0,且长度大于1,出错,break
- 当子段数字大于255,或子段长度不足1,2,3时,出错,break
- 当下一段字符串为空,且下一段有效IP地址为空,且当前已是第四段时,将连接好的IP地址压入结果容器中
(3)牛客网测试代码
class Solution {
public:
vector<string> restoreIpAddresses(string s) {
vector<string> strArray = subIPAddress(s, 4);
return strArray;
};
//递归函数
vector<string> subIPAddress(string s, int cont) {
vector<string> result;
//子串为空或者IP分为四段时停止递归
if (s.empty() || !cont)
return result;
for (int i = 1; i <= 3; ++i) {
string str = s.substr(0, i);
//当子段首位为0,且长度大于1,出错,break
//当子段数字大于255,或子段长度不足1, 2, 3时,出错,break
if ('0' == str[0] && str