# 子集和组合一个概念:不可选之前的数字;排列是所有元素都参与,用数组标记哪些数字本次是否用过
# 子集
def ziji(nums):
res = []
trace = []
def traceback(start, trace):
res.append(trace.copy()) # copy
for i in range(start, len(nums)):
trace.append(nums[i])
traceback(i + 1, trace) # i + 1
trace.pop()
traceback(0, trace)
return res
# 组合:元素无重复不可复选
def zuhe(nums, target):
res = []
trace = []
def traceback(start, trace):
if len(trace) == target:
res.append(trace.copy()) # copy
return
for i in range(start, len(nums)):
trace.append(nums[i])
traceback(i + 1, trace) # i + 1
trace.pop()
traceback(0, trace)
return res
# 排列
def pailie(nums, target):
# 不能重复数字,顺序不同则不同
res = []
trace = []
used = [0] * len(nums) # 标记数组
def traceback(trace):
if len(trace) == target:
res.append(trace.copy()) # copy
return
for i in range(len(nums)):
if used[i]: continue # 重点
trace.append(nums[i])
used[i] = 1
traceback(trace)
used[i] = 0
trace.pop()
traceback(trace)
return res
nums = [4, 23, 2]
# print("ziji: ", ziji(nums))
# print(zuhe([1, 2, 3, 4], 3))
# print(pailie([1, 2, 3], 2))
# 数组带有重复数字的子集
def ziji2(nums):
nums.sort()
res = []
trace = []
def traceback(start, trace):
res.append(trace.copy()) # copy
for i in range(start, len(nums)):
# 需要剪枝
if i > 0 and nums[i] == nums[i - 1]:
continue
trace.append(nums[i])
traceback(i + 1, trace) # i + 1
trace.pop()
traceback(0, trace)
return res
# print(ziji([1,2,3]))
# print(ziji2([1,2,3,2,2]))
def ziji3(nums, target):
# 带有重复数字的数组,目标和为target的子集
nums.sort()
res = []
trace = []
def traceback(start, trace):
if sum(trace) == target:
res.append(trace.copy())
return
# 可以剪枝:如果目前和已经超过 target(前提:整个数组都是正数),没必要再往下了
for i in range(start, len(nums)):
# 需要剪枝
if i > 0 and nums[i] == nums[i - 1]:
continue
trace.append(nums[i])
traceback(i + 1, trace) # i + 1
trace.pop()
traceback(0, trace)
return res
# print(ziji3([1,2,2,3], 4))
# 排列:数组有重复数字,不可复选
def pailie2(nums, target):
nums.sort()
res = []
trace = []
used = [0] * len(nums) # 标记数组
def traceback(trace):
if len(trace) == target:
res.append(trace.copy()) # copy
return
for i in range(len(nums)):
if used[i] or (i > 0 and nums[i] == nums[i - 1]): continue # 重点
trace.append(nums[i])
used[i] = 1
traceback(trace)
used[i] = 0
trace.pop()
traceback(trace)
return res
# print(pailie2([1,2,2,3], 2))
def ziji4(nums, target):
# 数组:不重复,可复选,目标和为target的子集
res = []
trace = []
def traceback(trace):
if sum(trace) > target: # 大于 target 就没必要往下了
return
if sum(trace) == target:
res.append(trace.copy())
return
for i in range(len(nums)):
trace.append(nums[i])
traceback(trace)
trace.pop()
traceback(trace)
return res
print(ziji4([1,2,3], 4))