Java算法问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java算法问题相关的知识,希望对你有一定的参考价值。

问题陈述::在Java中,给定一个整数数组,是否可以选择一组整数的组,使得该组与给定目标的总和,具有以下附加约束:如果数组中有数字,则相邻且相同的值,它们必须全部被选中,或者都不被选择。例如,对于数组1,2,2,2,5,2,必须选择或不选择中间的所有三个2,所有都作为一个组。 (一个循环可用于查找相同值的范围)。

 groupSumClump(0, 2, 4, 8, 10) → true      
 groupSumClump(0, 1, 2, 4, 8, 1, 14) → true                   
 groupSumClump(0, 2, 4, 4, 8, 14) → false --> Failing Test Case               
 groupSumClump(0, 8, 2, 2, 1, 9) → true   --> Failing Test Case      
 groupSumClump(0, 8, 2, 2, 1, 11) → false --> NegativeArraySizeException 

我做了一些初步分析,部分代码如下。

  public boolean groupSumClump(int start, int[] nums, int target) 
    start = 0;
    boolean flag = false;

    // get the highest int from the list of array we have
    int highestInteger = getTheBiggest(nums);
    if (highestInteger > target) 
        flag = false;
     else 
        int variable = 0;
        for (int i = 0; i < nums.length; i++) 
            variable += nums[i];
        
        if (variable == target) 
            flag = true;
         else 
            if (variable < target) 
                flag = false;
             else 
                // here goes ur grouping logic here
                flag = summate(highestInteger, target, nums);
            
        
    

    return flag;


private  boolean summate(int highestInteger, int target, int[] nums) 
    boolean val = false;
    if (highestInteger == target) 
        val = true;
     else 
        int[] temp = new int[nums.length - 1];
        int var = 0;            

        if ((target - highestInteger) > 0) 
                 for (int j = 0; j < nums.length-1; j++) 
                   if (nums[j] != highestInteger) 
                     temp[var] = nums[j];
                     if (temp[var] == (target - highestInteger)) 
                        val = true;
                        return val;
                     
                     var++;
                   
                 
             val = summate(getTheBiggest(temp), target - highestInteger,
                     temp);  

                                               
           
    return val;


private int getTheBiggest(int[] nums) 
    int biggestInteger = 0;
    for (int i = 0; i < nums.length; i++) 
        if (biggestInteger < nums[i]) 
            biggestInteger = nums[i];
        
    
    return biggestInteger;

请注意:我不知道如何处理下面的问题陈述的逻辑:问题有一个Additional Constraint,如果数组中有相邻的数字和相同的值,它们必须全部被选中,或者没有他们选择了。例如,对于数组1,2,2,2,5,2,必须选择或不选择中间的所有三个2,所有都作为一个组。 (一个循环可用于查找相同值的范围)。

我应该如何在上述问题中处理这部分逻辑。我一直在努力做到这一点,不知道。提供的建议将不胜感激。 Culd你让我知道代码有什么问题/如何处理这个问题中的附加约束, - :((

附加约束表示你选择作为一个组而不选择作为一个组。所以我不知道如何继续。如果你能帮助我。我将不胜感激。

编辑用户 - > MISSINGNO:我已将下面的代码构造添加到上面的主代码中,它打印出错误的值。我错了。

groupSumClump(0,2,4,4,8,14)→false再次失败2 8 4标志是 - > true这是错误的。

      for(int number=0;number<nums.length-1;number++)
      if(nums[number]==nums[number+1])
          nums[number]=nums[number]+nums[number+1];                                
              
    
答案

我会将数组转换为一个更简单的数组,可以使用前面的方法解决,通过聚集相邻的值:

1, 2, 2, 2, 5, 2 --> 1, 6, 5, 2

您可能希望保留一些额外的簿记信息,以便能够从解决方案中找到原始解决方案。

另一答案

此问题类似于查找数组中的整数组,该数组总计给定目标。

这个问题的提示是:

基本情况是start> = nums.length。在这种情况下,如果target == 0则返回true。否则,请考虑nums [start]处的元素。关键的想法是只有两种可能性 - 选择nums [start]或不选择nums [start]。如果选择了nums [start],则进行一次递归调用以查看解决方案是否可行(在该调用中从目标中减去nums [start])。如果未选择nums [start],则进行另一次递归调用以查看是否可以使用解决方案。如果两个递归调用中的任何一个返回true,则返回true。

您可以使用相同的提示,但在其中有一个循环,以查找数组中重复数字的总和。如果选择了总和,则调用以查看是否可以求解,如果未选择求和则进行另一次调用。如果两个递归调用中的任何一个返回true,则返回true。

我认为这会有所帮助。

public boolean groupSumClump(int start, int[] nums, int target)
   
if(start >= nums.length) return target == 0;

int count = 1;
while(start+count < nums.length && nums[start] == nums[start+count])
count++;

if(groupSumClump(start+count, nums, target-count*nums[start])) return true;
if(groupSumClump(start+count, nums, target)) return true;

return false;

另一答案

一旦你完成了missingno的预处理步骤(线性时间),你所拥有的基本上就是subset sum problem。这是一个相当困难的问题,但存在近似算法 - 根据序列的长度,结果可能变得切实可行。

另一答案

问题陈述含糊不清,不清楚:

使用这个附加约束:如果数组中有相邻的数字和相同的值,则必须全部选择它们,或者不选择它们。例如,对于数组1,2,2,2,5,2,必须选择或不选择中间的所有三个2,所有都作为一个组

如果“条纹”没有成功,如何选择单个数字?同样的例子:1,2,2,2,5,2

在一个递归调用中,我们选择2 2 2的条纹(来自上面的答案)* if(groupSumClump(start + count,nums,target-count * nums [start]))返回true *

在下一个rec。为什么我们不能在nums [start]中减去第一个单位数:if(groupSumClump(start + count,nums,target))return true;

我可以这样做:

if(groupSumClump(start + 1,nums,target - nums [start]))返回true;

这意味着我们永远不能选择单一数字?

另一答案

方法groupSumClump的公共方法参数列表不应公开start参数,特别是如果您有一个覆盖它的内部变量。

看看这个实现。 solve方法的时间复杂度是O(2^N),因为在最坏的情况下,你有义务检查所有可能的nums子集。除非有人证明NP = P

我希望它有所帮助。

import java.util.*;

public class SubsetSumSolver 

    public boolean solve(int[] nums, int target) 
        return solve(0, 0, target, mergeSameNumbers(nums));
    

    private boolean solve(int start, int tempSum, int sum, ArrayList<Integer> nums) 
        if (start == nums.size())
            return sum == tempSum;
        return solve(start + 1, tempSum + nums.get(start),sum, nums) || solve(start + 1, tempSum, sum, nums);
    

    private ArrayList<Integer> mergeSameNumbers(int[] nums) 
        if (nums.length == 0)
            return toArrayList(nums);
        LinkedList<Integer> merged = new LinkedList<>();
        int tempSum = nums[0];
        for (int i = 1; i < nums.length; i++) 
            if (nums[i - 1] == nums[i])
                tempSum += nums[i];
            else 
                merged.add(tempSum);
                tempSum = nums[i];
            
        
        merged.add(tempSum);
        return new ArrayList(merged);
    

    private ArrayList<Integer> toArrayList(int[] nums) 
        ArrayList<Integer> result = new ArrayList();
        for (int index = 0; index < nums.length; index++)
            result.add(nums[index]);
        return result;
    


另一答案

我用HashMap的解决方案。

public boolean groupSumClump(int start, int[] nums, int target) 
  Map<Integer, Integer> map = new HashMap<Integer, Integer>();

  Arrays.sort(nums);

  for (int i : nums) 
    if (!map.containsKey(i)) 
      map.put(i, 1);
    

    else 
      map.put(i, map.get(i) + 1);
    
  

  return groupSumClumpHelper(start, nums, target, map);


private boolean groupSumClumpHelper(int start, int[] nums, int target, Map map) 
  if (start >= nums.length) 
    return target == 0;
  

  if (!map.get(nums[start]).equals(1)) 
    return groupSumClumpHelper(start + Integer.parseInt(map.get(nums[start]).toString()), nums, target - Integer.parseInt(map.get(nums[start]).toString()) * nums[start], map) ||
           groupSumClumpHelper(start + Integer.parseInt(map.get(nums[start]).toString()), nums, target, map);
  

  return groupSumClumpHelper(start + 1, nums, target - nums[start], map) || groupSumClumpHelper(start + 1, nums, target, map);

以上是关于Java算法问题的主要内容,如果未能解决你的问题,请参考以下文章

有关java中工作日算法的问题

Java 算法贪心算法

Java简单算法问题

回溯算法解八皇后问题(java版)

95% 的算法都是基于这 6 种算法思想,大厂Java面试必考点

《Java算法》Java动态规划