你有 4 张写有 1 到 9 数字的牌。你需要判断是否能通过 *,/,+,-,(,) 的运算得到 24。

示例 1:

输入: [4, 1, 8, 7]
输出: True
解释: (8-4) * (7-1) = 24
示例 2:

输入: [1, 2, 1, 2]
输出: False
注意:

除法运算符 / 表示实数除法,而不是整数除法。例如 4 / (1 - 2/3) = 12 。
每个运算符对两个数进行运算。特别是我们不能用 - 作为一元运算符。例如,[1, 1, 1, 1] 作为输入时,表达式 -1 - 1 - 1 - 1 是不允许的。
你不能将数字连接在一起。例如,输入为 [1, 2, 1, 2] 时,不能写成 12 + 12 。

思路:这道题比较经典并且好想的算法肯定是回溯了,但是我真的不想用回溯了,于是写了个分治的版本过了这道题哈哈

坑点:因为除法是实数除法,因此如果不保存分数形式进行运算的话一定要考虑精度损失!

class Solution {
	
	private int[] arr;
	private boolean mark;
	private boolean[] flag;
	private List<Double> ans;
	
    public boolean judgePoint24(int[] nums) {
        
    	mark=false;
    	arr=new int[nums.length];
    	flag=new boolean[nums.length];
    	ans=new ArrayList<>();
    	
    	dfs(nums,0);
    	
    	return mark;
    }
    
    private void dfs(int[] nums,int index) {
    	if(mark) return;
    	if(index==nums.length) {
    		ans.addAll(work(arr,0,arr.length-1));
    		for(int i=0;i<ans.size();i++)
    			if(Math.abs(ans.get(i)-24.0)<1e-6) {
    				mark=true;
    				break;
    			}
    		return;
    	}
    	for(int i=0;i<nums.length;i++) {
    		if(flag[i]) continue;
    		flag[i]=true;
    		arr[index]=nums[i];
    		dfs(nums,index+1);
    		flag[i]=false;
    	}
    }
    
    private List<Double> work(int[] nums,int l,int r) {
    	
    	List<Double> res=new ArrayList<>();
    	if(l==r) {res.add(nums[l]*1.0); return res; }
    	
    	for(int i=l;i<r;i++) {
    		res.addAll(work1(work(nums,l,i),work(nums,i+1,r),'+'));
    		res.addAll(work1(work(nums,l,i),work(nums,i+1,r),'-'));
    		res.addAll(work1(work(nums,l,i),work(nums,i+1,r),'*'));
    		res.addAll(work1(work(nums,l,i),work(nums,i+1,r),'/'));
    	}
    	
    	return res;
    }
  
    private List<Double> work1(List<Double> list1,List<Double> list2,char c){
    	
    	List<Double> res=new ArrayList<>();
    	for(int i=0;i<list1.size();i++)
    		for(int j=0;j<list2.size();j++) {
    			if(c=='+') res.add(list1.get(i)+list2.get(j));
    			else if(c=='-') res.add(list1.get(i)-list2.get(j));
    			else if(c=='*') res.add(list1.get(i)*list2.get(j));
    			else if(c=='/' && list2.get(j)!=0) res.add(list1.get(i)*1.0/list2.get(j));
    		}
    	
    	return res;
    }
}