你有 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;
}
}