深度搜素——搜索嵌套

51 篇文章 1 订阅
12 篇文章 0 订阅

搜索问题,扩展节点的时候会iterate一个link集合,一般就是一个for 循环,但有的时候,这个集合并不能直接得到,而是另一个搜索问题,比如n个数分k组问题的一种解法是:问题分成k个步骤,每个步骤确定一个组,具体一个组可分的方案的candidate集合就不是直接可以用for来iterate的,而是另一个搜索问题——子集问题。这就引出一个重点,iterate不光可以额用for,也可以用搜索,搜索本来就是在枚举,只不过枚举出一个解不是print输出,而是用来作为外层搜索的一个扩展节点,另外一点,搜索的结果体现在哪?side effect,搜索一般是通过side effect体现状态、结果的。

更新:

嵌套搜索的思路只是一个看问题的角度,把维度拆开来一个一个看。也可以有另一种更general的角度:二元(多元)搜索。每一次递归就是一次状态转移,一般的,这个状态是一个变量,其他的变量都是伴随状态;多元搜索的意思是状态是一个组合(x, y),类似二维平面上的搜索,看下面终极版搜索。

 

def group(A, k):
    groups, n, used = [[] for _ in xrange(k)], len(A), set()

    def grouping(t, start):
        if t == k:
            if len(used) == n: print groups
            return
        if start == n: return
        if start in used: grouping(t, start + 1)
        else:
            groups[t].append(A[start])
            used.add(start)

            def select(i, startIndex):
                grouping(t + 1, start + 1)
                for j in xrange(startIndex, n):
                    if j in used: continue
                    used.add(j)
                    groups[t].append(A[j])
                    select(i + 1, j + 1)
                    used.remove(j)
                    groups[t].pop()

            select(start + 1, start + 1)
            groups[t].pop()
            used.remove(start)
    grouping(0, 0)

 第二个版本

def group(A, k):
    groups, n, used = [[] for _ in xrange(k)], len(A), set()
    def grouping(t, start):
        if t == k:
            if len(used) == n: print groups
            return
        if start == n: return
        if start in used: grouping(t, start + 1)
        else:
            def select(i, startIndex):
                grouping(t + 1, start + 1)
                for j in xrange(startIndex, n):
                    if j in used: continue
                    used.add(j)
                    groups[t].append(A[j])
                    select(i + 1, j + 1)
                    used.remove(j)
                    groups[t].pop()
            select(start, start)
    grouping(0, 0)

递归问题法:

def group(A, k):
    if k == 1:return [[A[:]]]
    if k == len(A): return [map(lambda x: [x], A)]
    last = A.pop()
    groupings = group(A, k - 1)
    for grouping in groupings: grouping.append([last])
    for grouping in group(A, k):
        for g in grouping:
            g.append(last)
            groupings.append(deepcopy(grouping))
            g.pop()
    A.append(last)
    return groupings

终极版本:

def group(A, k):
    groups, used = [[] for _ in xrange(k)], set()
    def grouping(g, start):
        if g == k:
            if len(used) == len(A): print groups
        else:
            if len(groups[g]) > 0: grouping(g + 1, g + 1)
            for i in xrange(start, len(A)):
                if i in used: continue
                groups[g].append(A[i])
                used.add(i)
                grouping(g, i + 1)
                groups[g].pop()
                used.remove(i)
    grouping(0, 0)

 

还有一个例子:leetcode 282 expression add operators,给一串数字加操作符凑一个给定的值。问题的划分:每一步取若干数字作为一个数,参与计算,下一步取剩下的,取完为止。每一步按取几个数字作为数又分多种情况,同时确定了一个数之后按进行什么运算分又有4种情况。这里扩展节点是一个双重循环,先枚举取几个数字作为操作数,再枚举4种运算。

 

 

vector<string> addOperators(string num, int target) {
	vector<string> ans;
	function<void(int, long long, long long, string)> dfs = [&](int i, long long eval, long long pre, string s)->void {
		if (i == num.size())  {
			if (target == eval) ans.push_back(s);
		}
		else {
			for (int j = i; j < num.size(); ++j) {
				if (num[i] == '0' && j > i) break;
				string cur = num.substr(i, j - i + 1);
				long long value = stol(cur);
				if (i == 0) {
					dfs(j + 1, value, value, cur);
				}
				else {
					dfs(j + 1, eval + value, value, s + "+" + cur);
					dfs(j + 1, eval - value, -value, s + "-" + cur);
					dfs(j + 1, eval - pre + value * pre, value * pre, s + "*" + cur);
				}
			}
		}
	};
	dfs(0, 0, 0, "");
	return ans;
}

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值