Algorithm 给定一个列表和一个限制,使用递归/回溯算法查找最大和

Algorithm 给定一个列表和一个限制,使用递归/回溯算法查找最大和,algorithm,data-structures,recursion,backtracking,Algorithm,Data Structures,Recursion,Backtracking,这不是一个家庭作业,只是一个关于递归的自我练习。:) 问题是:() 给定一个整数列表L和一个限制n,求不超过限制n的最大和(L,n)。 例如,L=[7,30,8,22,6,1,14],极限n=19,那么最大和(L,n)=16。因为最大组合是7+8+1=16 我想出了经典的回溯算法来解决这个问题: public static int maxSum(List<Integer> L, int limit){ boolean[] used = new boolean[

这不是一个家庭作业,只是一个关于递归的自我练习。:)

问题是:()

给定一个整数列表L和一个限制n,求不超过限制n的最大和(L,n)。 例如,L=[7,30,8,22,6,1,14],极限n=19,那么最大和(L,n)=16。因为最大组合是7+8+1=16

我想出了经典的回溯算法来解决这个问题:

    public static int maxSum(List<Integer> L, int limit){
        boolean[] used = new boolean[L.size()];
        int[] max = {0};
        rec(L, limit, 0, used, max);
        return max[0];
    }

    public static boolean rec(List<Integer> L, int limit, int cur, boolean[] used, int[] max){
        if(cur > limit){
            return false;
        } 

        for(int i=0; i<L.size(); i++){
            if(!used[i]){
                used[i] = true;
                if(rec(L, limit, cur+L.get(i), used, max)){
                    max[0] = Math.max(max[0], cur+L.get(i));
                }
                used[i] = false;
            }
        }
        return true;
    }
公共静态整数最大和(列表L,整数限制){
boolean[]used=新的boolean[L.size()];
int[]max={0};
rec(L,极限,0,已使用,最大值);
返回最大值[0];
}
公共静态布尔rec(列表L,整数限制,整数cur,使用的布尔[],整数[]最大值){
如果(当前>限制){
返回false;
} 

对于(inti=0;i当然有可能,每个循环都可以用递归代替

for(int i = 0; i < size; i++) {
  // some code goes here
}
第一个电话是:

iterate(0, size);

这将为每个
i
0..size
执行一些代码当然有可能,每个循环都可以用递归替换

for(int i = 0; i < size; i++) {
  // some code goes here
}
第一个电话是:

iterate(0, size);

这将为每个
i
0..size
执行一些代码当然有可能,每个循环都可以用递归替换

for(int i = 0; i < size; i++) {
  // some code goes here
}
第一个电话是:

iterate(0, size);

这将为每个
i
0..size
执行一些代码当然有可能,每个循环都可以用递归替换

for(int i = 0; i < size; i++) {
  // some code goes here
}
第一个电话是:

iterate(0, size);

这将为每个
i
0..size

执行一些代码基于@Deximat的建议,我重写了代码以删除for循环,它就工作了

        public static int maxSum2(List<Integer> L, int limit){
            boolean[] used = new boolean[L.size()];
            int[] max = {0};
            rec2(L, limit, 0, used, max, 0);
            return max[0];
        }

        public static boolean rec2(List<Integer> L, int limit, int cur, boolean[] used, int[] max, int index){
            if(cur > limit){
                return false;
            }

            if(index == L.size()){
                return true;
            }
            if(!used[index]){
                used[index] = true;
                if(rec2(L, limit, cur+L.get(index), used, max, index)){
                    max[0] = Math.max(max[0], cur+L.get(index));
//                      return true;
                }
                used[index] = false;
            }

            return rec2(L, limit, cur, used, max, index+1);
        }
public static int maxSum2(列表L,int limit){
boolean[]used=新的boolean[L.size()];
int[]max={0};
rec2(L,极限,0,已使用,最大值,0);
返回最大值[0];
}
公共静态布尔rec2(列表L、整数限制、整数cur、使用的布尔[]、整数[]最大值、整数索引){
如果(当前>限制){
返回false;
}
如果(索引==L.size()){
返回true;
}
如果(!已使用[索引]){
已用[索引]=真;
if(rec2(L,极限,cur+L.get(索引),已使用,最大,索引)){
max[0]=Math.max(max[0],cur+L.get(index));
//返回true;
}
已用[索引]=假;
}
返回rec2(L、限制、当前、已用、最大值、索引+1);
}

根据@Deximat的建议,我重写了代码以删除for循环,它就可以工作了

        public static int maxSum2(List<Integer> L, int limit){
            boolean[] used = new boolean[L.size()];
            int[] max = {0};
            rec2(L, limit, 0, used, max, 0);
            return max[0];
        }

        public static boolean rec2(List<Integer> L, int limit, int cur, boolean[] used, int[] max, int index){
            if(cur > limit){
                return false;
            }

            if(index == L.size()){
                return true;
            }
            if(!used[index]){
                used[index] = true;
                if(rec2(L, limit, cur+L.get(index), used, max, index)){
                    max[0] = Math.max(max[0], cur+L.get(index));
//                      return true;
                }
                used[index] = false;
            }

            return rec2(L, limit, cur, used, max, index+1);
        }
public static int maxSum2(列表L,int limit){
boolean[]used=新的boolean[L.size()];
int[]max={0};
rec2(L,极限,0,已使用,最大值,0);
返回最大值[0];
}
公共静态布尔rec2(列表L、整数限制、整数cur、使用的布尔[]、整数[]最大值、整数索引){
如果(当前>限制){
返回false;
}
如果(索引==L.size()){
返回true;
}
如果(!已使用[索引]){
已用[索引]=真;
if(rec2(L,极限,cur+L.get(索引),已使用,最大,索引)){
max[0]=Math.max(max[0],cur+L.get(index));
//返回true;
}
已用[索引]=假;
}
返回rec2(L、限制、当前、已用、最大值、索引+1);
}

根据@Deximat的建议,我重写了代码以删除for循环,它就可以工作了

        public static int maxSum2(List<Integer> L, int limit){
            boolean[] used = new boolean[L.size()];
            int[] max = {0};
            rec2(L, limit, 0, used, max, 0);
            return max[0];
        }

        public static boolean rec2(List<Integer> L, int limit, int cur, boolean[] used, int[] max, int index){
            if(cur > limit){
                return false;
            }

            if(index == L.size()){
                return true;
            }
            if(!used[index]){
                used[index] = true;
                if(rec2(L, limit, cur+L.get(index), used, max, index)){
                    max[0] = Math.max(max[0], cur+L.get(index));
//                      return true;
                }
                used[index] = false;
            }

            return rec2(L, limit, cur, used, max, index+1);
        }
public static int maxSum2(列表L,int limit){
boolean[]used=新的boolean[L.size()];
int[]max={0};
rec2(L,极限,0,已使用,最大值,0);
返回最大值[0];
}
公共静态布尔rec2(列表L、整数限制、整数cur、使用的布尔[]、整数[]最大值、整数索引){
如果(当前>限制){
返回false;
}
如果(索引==L.size()){
返回true;
}
如果(!已使用[索引]){
已用[索引]=真;
if(rec2(L,极限,cur+L.get(索引),已使用,最大,索引)){
max[0]=Math.max(max[0],cur+L.get(index));
//返回true;
}
已用[索引]=假;
}
返回rec2(L、限制、当前、已用、最大值、索引+1);
}

根据@Deximat的建议,我重写了代码以删除for循环,它就可以工作了

        public static int maxSum2(List<Integer> L, int limit){
            boolean[] used = new boolean[L.size()];
            int[] max = {0};
            rec2(L, limit, 0, used, max, 0);
            return max[0];
        }

        public static boolean rec2(List<Integer> L, int limit, int cur, boolean[] used, int[] max, int index){
            if(cur > limit){
                return false;
            }

            if(index == L.size()){
                return true;
            }
            if(!used[index]){
                used[index] = true;
                if(rec2(L, limit, cur+L.get(index), used, max, index)){
                    max[0] = Math.max(max[0], cur+L.get(index));
//                      return true;
                }
                used[index] = false;
            }

            return rec2(L, limit, cur, used, max, index+1);
        }
public static int maxSum2(列表L,int limit){
boolean[]used=新的boolean[L.size()];
int[]max={0};
rec2(L,极限,0,已使用,最大值,0);
返回最大值[0];
}
公共静态布尔rec2(列表L、整数限制、整数cur、使用的布尔[]、整数[]最大值、整数索引){
如果(当前>限制){
返回false;
}
如果(索引==L.size()){
返回true;
}
如果(!已使用[索引]){
已用[索引]=真;
if(rec2(L,极限,cur+L.get(索引),已使用,最大,索引)){
max[0]=Math.max(max[0],cur+L.get(index));
//返回true;
}
已用[索引]=假;
}
返回rec2(L、限制、当前、已用、最大值、索引+1);
}

这个问题实际上可以在不使用其他方法的情况下解决。概念如下:

  • 如果列表为空,则返回0
  • 如果列表中有1项且为限制项,则返回0
  • 如果列表有多个项目,且第一个项目为>限制,则返回子列表的最大值
  • 否则,返回子列表的最大值和第一项之间的最大值加上子列表的最大值和限制减去第一项
公共静态整数最大和(列表编号,整数限制){
如果(numbers.size()==0){返回0;}
int