mirror of
				https://github.com/krahets/hello-algo.git
				synced 2025-11-04 06:07:20 +08:00 
			
		
		
		
	feat: add Swift codes for subset_sum_problem article (#584)
This commit is contained in:
		@ -68,6 +68,9 @@ let package = Package(
 | 
				
			|||||||
        .executable(name: "preorder_traversal_iii_template", targets: ["preorder_traversal_iii_template"]),
 | 
					        .executable(name: "preorder_traversal_iii_template", targets: ["preorder_traversal_iii_template"]),
 | 
				
			||||||
        .executable(name: "permutations_i", targets: ["permutations_i"]),
 | 
					        .executable(name: "permutations_i", targets: ["permutations_i"]),
 | 
				
			||||||
        .executable(name: "permutations_ii", targets: ["permutations_ii"]),
 | 
					        .executable(name: "permutations_ii", targets: ["permutations_ii"]),
 | 
				
			||||||
 | 
					        .executable(name: "subset_sum_i_naive", targets: ["subset_sum_i_naive"]),
 | 
				
			||||||
 | 
					        .executable(name: "subset_sum_i", targets: ["subset_sum_i"]),
 | 
				
			||||||
 | 
					        .executable(name: "subset_sum_ii", targets: ["subset_sum_ii"]),
 | 
				
			||||||
        .executable(name: "n_queens", targets: ["n_queens"]),
 | 
					        .executable(name: "n_queens", targets: ["n_queens"]),
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    targets: [
 | 
					    targets: [
 | 
				
			||||||
@ -137,6 +140,9 @@ let package = Package(
 | 
				
			|||||||
        .executableTarget(name: "preorder_traversal_iii_template", dependencies: ["utils"], path: "chapter_backtracking", sources: ["preorder_traversal_iii_template.swift"]),
 | 
					        .executableTarget(name: "preorder_traversal_iii_template", dependencies: ["utils"], path: "chapter_backtracking", sources: ["preorder_traversal_iii_template.swift"]),
 | 
				
			||||||
        .executableTarget(name: "permutations_i", path: "chapter_backtracking", sources: ["permutations_i.swift"]),
 | 
					        .executableTarget(name: "permutations_i", path: "chapter_backtracking", sources: ["permutations_i.swift"]),
 | 
				
			||||||
        .executableTarget(name: "permutations_ii", path: "chapter_backtracking", sources: ["permutations_ii.swift"]),
 | 
					        .executableTarget(name: "permutations_ii", path: "chapter_backtracking", sources: ["permutations_ii.swift"]),
 | 
				
			||||||
 | 
					        .executableTarget(name: "subset_sum_i_naive", path: "chapter_backtracking", sources: ["subset_sum_i_naive.swift"]),
 | 
				
			||||||
 | 
					        .executableTarget(name: "subset_sum_i", path: "chapter_backtracking", sources: ["subset_sum_i.swift"]),
 | 
				
			||||||
 | 
					        .executableTarget(name: "subset_sum_ii", path: "chapter_backtracking", sources: ["subset_sum_ii.swift"]),
 | 
				
			||||||
        .executableTarget(name: "n_queens", path: "chapter_backtracking", sources: ["n_queens.swift"]),
 | 
					        .executableTarget(name: "n_queens", path: "chapter_backtracking", sources: ["n_queens.swift"]),
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										53
									
								
								codes/swift/chapter_backtracking/subset_sum_i.swift
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								codes/swift/chapter_backtracking/subset_sum_i.swift
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,53 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * File: subset_sum_i.swift
 | 
				
			||||||
 | 
					 * Created Time: 2023-07-02
 | 
				
			||||||
 | 
					 * Author: nuomi1 (nuomi1@qq.com)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 回溯算法:子集和 I */
 | 
				
			||||||
 | 
					func backtrack(state: inout [Int], target: Int, choices: [Int], start: Int, res: inout [[Int]]) {
 | 
				
			||||||
 | 
					    // 子集和等于 target 时,记录解
 | 
				
			||||||
 | 
					    if target == 0 {
 | 
				
			||||||
 | 
					        res.append(state)
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // 遍历所有选择
 | 
				
			||||||
 | 
					    // 剪枝二:从 start 开始遍历,避免生成重复子集
 | 
				
			||||||
 | 
					    for i in stride(from: start, to: choices.count, by: 1) {
 | 
				
			||||||
 | 
					        // 剪枝一:若子集和超过 target ,则直接结束循环
 | 
				
			||||||
 | 
					        // 这是因为数组已排序,后边元素更大,子集和一定超过 target
 | 
				
			||||||
 | 
					        if target - choices[i] < 0 {
 | 
				
			||||||
 | 
					            break
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // 尝试:做出选择,更新 target, start
 | 
				
			||||||
 | 
					        state.append(choices[i])
 | 
				
			||||||
 | 
					        // 进行下一轮选择
 | 
				
			||||||
 | 
					        backtrack(state: &state, target: target - choices[i], choices: choices, start: i, res: &res)
 | 
				
			||||||
 | 
					        // 回退:撤销选择,恢复到之前的状态
 | 
				
			||||||
 | 
					        state.removeLast()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 求解子集和 I */
 | 
				
			||||||
 | 
					func subsetSumI(nums: [Int], target: Int) -> [[Int]] {
 | 
				
			||||||
 | 
					    var state: [Int] = [] // 状态(子集)
 | 
				
			||||||
 | 
					    let nums = nums.sorted() // 对 nums 进行排序
 | 
				
			||||||
 | 
					    let start = 0 // 遍历起始点
 | 
				
			||||||
 | 
					    var res: [[Int]] = [] // 结果列表(子集列表)
 | 
				
			||||||
 | 
					    backtrack(state: &state, target: target, choices: nums, start: start, res: &res)
 | 
				
			||||||
 | 
					    return res
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@main
 | 
				
			||||||
 | 
					enum SubsetSumI {
 | 
				
			||||||
 | 
					    /* Driver Code */
 | 
				
			||||||
 | 
					    static func main() {
 | 
				
			||||||
 | 
					        let nums = [3, 4, 5]
 | 
				
			||||||
 | 
					        let target = 9
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let res = subsetSumI(nums: nums, target: target)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        print("输入数组 nums = \(nums), target = \(target)")
 | 
				
			||||||
 | 
					        print("所有和等于 \(target) 的子集 res = \(res)")
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										51
									
								
								codes/swift/chapter_backtracking/subset_sum_i_naive.swift
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								codes/swift/chapter_backtracking/subset_sum_i_naive.swift
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * File: subset_sum_i_naive.swift
 | 
				
			||||||
 | 
					 * Created Time: 2023-07-02
 | 
				
			||||||
 | 
					 * Author: nuomi1 (nuomi1@qq.com)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 回溯算法:子集和 I */
 | 
				
			||||||
 | 
					func backtrack(state: inout [Int], target: Int, total: Int, choices: [Int], res: inout [[Int]]) {
 | 
				
			||||||
 | 
					    // 子集和等于 target 时,记录解
 | 
				
			||||||
 | 
					    if total == target {
 | 
				
			||||||
 | 
					        res.append(state)
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // 遍历所有选择
 | 
				
			||||||
 | 
					    for i in stride(from: 0, to: choices.count, by: 1) {
 | 
				
			||||||
 | 
					        // 剪枝:若子集和超过 target ,则跳过该选择
 | 
				
			||||||
 | 
					        if total + choices[i] > target {
 | 
				
			||||||
 | 
					            continue
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // 尝试:做出选择,更新元素和 total
 | 
				
			||||||
 | 
					        state.append(choices[i])
 | 
				
			||||||
 | 
					        // 进行下一轮选择
 | 
				
			||||||
 | 
					        backtrack(state: &state, target: target, total: total + choices[i], choices: choices, res: &res)
 | 
				
			||||||
 | 
					        // 回退:撤销选择,恢复到之前的状态
 | 
				
			||||||
 | 
					        state.removeLast()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 求解子集和 I(包含重复子集) */
 | 
				
			||||||
 | 
					func subsetSumINaive(nums: [Int], target: Int) -> [[Int]] {
 | 
				
			||||||
 | 
					    var state: [Int] = [] // 状态(子集)
 | 
				
			||||||
 | 
					    let total = 0 // 子集和
 | 
				
			||||||
 | 
					    var res: [[Int]] = [] // 结果列表(子集列表)
 | 
				
			||||||
 | 
					    backtrack(state: &state, target: target, total: total, choices: nums, res: &res)
 | 
				
			||||||
 | 
					    return res
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@main
 | 
				
			||||||
 | 
					enum SubsetSumINaive {
 | 
				
			||||||
 | 
					    /* Driver Code */
 | 
				
			||||||
 | 
					    static func main() {
 | 
				
			||||||
 | 
					        let nums = [3, 4, 5]
 | 
				
			||||||
 | 
					        let target = 9
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let res = subsetSumINaive(nums: nums, target: target)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        print("输入数组 nums = \(nums), target = \(target)")
 | 
				
			||||||
 | 
					        print("所有和等于 \(target) 的子集 res = \(res)")
 | 
				
			||||||
 | 
					        print("请注意,该方法输出的结果包含重复集合")
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										58
									
								
								codes/swift/chapter_backtracking/subset_sum_ii.swift
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								codes/swift/chapter_backtracking/subset_sum_ii.swift
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,58 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * File: subset_sum_ii.swift
 | 
				
			||||||
 | 
					 * Created Time: 2023-07-02
 | 
				
			||||||
 | 
					 * Author: nuomi1 (nuomi1@qq.com)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 回溯算法:子集和 II */
 | 
				
			||||||
 | 
					func backtrack(state: inout [Int], target: Int, choices: [Int], start: Int, res: inout [[Int]]) {
 | 
				
			||||||
 | 
					    // 子集和等于 target 时,记录解
 | 
				
			||||||
 | 
					    if target == 0 {
 | 
				
			||||||
 | 
					        res.append(state)
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // 遍历所有选择
 | 
				
			||||||
 | 
					    // 剪枝二:从 start 开始遍历,避免生成重复子集
 | 
				
			||||||
 | 
					    // 剪枝三:从 start 开始遍历,避免重复选择同一元素
 | 
				
			||||||
 | 
					    for i in stride(from: start, to: choices.count, by: 1) {
 | 
				
			||||||
 | 
					        // 剪枝一:若子集和超过 target ,则直接结束循环
 | 
				
			||||||
 | 
					        // 这是因为数组已排序,后边元素更大,子集和一定超过 target
 | 
				
			||||||
 | 
					        if target - choices[i] < 0 {
 | 
				
			||||||
 | 
					            break
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // 剪枝四:如果该元素与左边元素相等,说明该搜索分支重复,直接跳过
 | 
				
			||||||
 | 
					        if i > start, choices[i] == choices[i - 1] {
 | 
				
			||||||
 | 
					            continue
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // 尝试:做出选择,更新 target, start
 | 
				
			||||||
 | 
					        state.append(choices[i])
 | 
				
			||||||
 | 
					        // 进行下一轮选择
 | 
				
			||||||
 | 
					        backtrack(state: &state, target: target - choices[i], choices: choices, start: i + 1, res: &res)
 | 
				
			||||||
 | 
					        // 回退:撤销选择,恢复到之前的状态
 | 
				
			||||||
 | 
					        state.removeLast()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 求解子集和 II */
 | 
				
			||||||
 | 
					func subsetSumII(nums: [Int], target: Int) -> [[Int]] {
 | 
				
			||||||
 | 
					    var state: [Int] = [] // 状态(子集)
 | 
				
			||||||
 | 
					    let nums = nums.sorted() // 对 nums 进行排序
 | 
				
			||||||
 | 
					    let start = 0 // 遍历起始点
 | 
				
			||||||
 | 
					    var res: [[Int]] = [] // 结果列表(子集列表)
 | 
				
			||||||
 | 
					    backtrack(state: &state, target: target, choices: nums, start: start, res: &res)
 | 
				
			||||||
 | 
					    return res
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@main
 | 
				
			||||||
 | 
					enum SubsetSumII {
 | 
				
			||||||
 | 
					    /* Driver Code */
 | 
				
			||||||
 | 
					    static func main() {
 | 
				
			||||||
 | 
					        let nums = [4, 4, 5]
 | 
				
			||||||
 | 
					        let target = 9
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let res = subsetSumII(nums: nums, target: target)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        print("输入数组 nums = \(nums), target = \(target)")
 | 
				
			||||||
 | 
					        print("所有和等于 \(target) 的子集 res = \(res)")
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user