バックトラック法を用いた組み合わせ合計問題の解法

39. 組み合わせ合計問題(重複選択可)

整数配列candidatesと目標値targetが与えられたとき、配列要素の和がtargetとなる全てのユニークな組み合わせを返します。各要素は無制限に再利用可能です。

入力例: candidates = [2,3,6,7], target = 7
出力例: [[2,2,3],[7]]

解法ポイント:

  • 要素の重複使用を許可するため、再帰呼び出し時にインデックスを進めない
  • 枝刈り処理で不要な探索を省略
import java.util.*;

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    LinkedList<Integer> track = new LinkedList<>();
    
    public List<List<Integer>> combinationSum(int[] nums, int target) {
        Arrays.sort(nums);
        backtrack(nums, target, 0, 0);
        return res;
    }
    
    void backtrack(int[] nums, int target, int currentSum, int start) {
        if(currentSum == target) {
            res.add(new ArrayList<>(track));
            return;
        }
        if(currentSum > target) return;
        
        for(int i = start; i < nums.length; i++) {
            track.add(nums[i]);
            backtrack(nums, target, currentSum + nums[i], i);
            track.removeLast();
        }
    }
}

40. 組み合わせ合計問題(重複選択不可)

配列要素の重複使用を禁止し、かつ解の重複も排除するバージョンです。

入力例: candidates = [10,1,2,7,6,1,5], target = 8
出力例: [[1,1,6],[1,2,5],[1,7],[2,6]]

解法ポイント:

  • 配列を事前ソート
  • 重複要素のスキップ処理
  • インデックスを進めて要素の再利用を防止
import java.util.*;

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    LinkedList<Integer> track = new LinkedList<>();
    
    public List<List<Integer>> combinationSum2(int[] nums, int target) {
        Arrays.sort(nums);
        backtrack(nums, target, 0, 0);
        return res;
    }
    
    void backtrack(int[] nums, int target, int currentSum, int start) {
        if(currentSum == target) {
            res.add(new ArrayList<>(track));
            return;
        }
        if(currentSum > target) return;
        
        for(int i = start; i < nums.length; i++) {
            if(i > start && nums[i] == nums[i-1]) continue;
            
            track.add(nums[i]);
            backtrack(nums, target, currentSum + nums[i], i+1);
            track.removeLast();
        }
    }
}

タグ: バックトラック 組み合わせ問題 Java アルゴリズム

8月1日 05:05 投稿