java机试题*:数组分组(按条件分组、动态规划两种思路、条件转化、【完整搜索使用循环可能会漏掉间隔组合的情况,需要使用递归动态规划场景来找出所有组合】)

描述

输入int型数组,询问该数组能否分成两组,使得两组中各元素加起来的和相等,并且,所有5的倍数必须在其中一个组中,所有3的倍数在另一个组中(不包括5的倍数),不是5的倍数也不是3的倍数能放在任意一组,可以将数组分为空数组,能满足以上条件,输出true;不满足时输出false。
 
本题含有多组样例输入。
 
数据范围:每个数组大小满足 1 \le n \le 50 \1n50  ,输入的数据大小满足 |val| \le 500 \val500 

输入描述:

第一行是数据个数,第二行是输入的数据

输出描述:

返回true或者false

复制代码
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

// 思路1:找到将ohter分给这两个组的所有情况,有一组和相等则满足条件,但是找出所有的随机组合不好实现。
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNextInt()) {
            // 分别获取3组,5组,其他组相关信息
            int num = in.nextInt();
            int fiveSum = 0;
            int threeSum = 0;
            int sum = 0;
            List<Integer> other = new ArrayList<Integer>();
            for (int i = 0; i < num; i++) {
                int temp = in.nextInt();
                if(temp % 5 == 0) {
                    fiveSum += temp;
                } else if(temp % 3 == 0) {
                    threeSum += temp;
                } else {
                    other.add(temp);
                }
                sum += temp;
            }

            // 获取是否满足条件
            boolean ret = false;
            // 1.总和不是偶数必定不满足
            if(sum % 2 != 0){
                ret = false;
            // 2.其他组没有数时,3和5组各自和相等即可
            } else if(other.size() == 0) {
                if(fiveSum == threeSum) {
                    ret = true;
                }
            } else {
                //3. 其他组有数时,获取所有分组的和,使得分完组后满足,判断fiveSum == threeSum
                ret = getTarget(0,fiveSum, threeSum,other);
            }
            System.out.println(ret);
        }
    }
    /**
     * 获取所有分组的和,使得分完组后满足,fiveSum == threeSum
     */
    public static boolean getTarget(int index, int fiveSum,int threeSum, List<Integer> other) {
     // 终止条件,分组完成
if(index == other.size()) { return fiveSum == threeSum; } else { // 分两种情况:分给3组,分给5组 return getTarget(index + 1,fiveSum + other.get(index) ,threeSum, other) || getTarget(index + 1,fiveSum, threeSum + other.get(index), other); } } }
复制代码

 

复制代码
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
// 思路2:分完组后,两组和相等,则有:sum / 2 = arr1(分组后)  =  arr2(分组后),则sum必定是偶数
//       则,其他组中需要满足存在sum / 2 - arr1(分组前)的一个和。任意组合,能得到该数即可
//       或存在sum/2 - arr2(分组前),分组前,即,其他组中的数还没有分给3和5组。
// 这里使用思路2
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNextInt()) {
            // 分别获取3组,5组,其他组相关信息
            int num = in.nextInt();
            int fiveSum = 0;
            int threeSum = 0;
            int sum = 0;
            List<Integer> other = new ArrayList<Integer>();
            for (int i = 0; i < num; i++) {
                int temp = in.nextInt();
                if(temp % 5 == 0) {
                    fiveSum += temp;
                } else if(temp % 3 == 0) {
                    threeSum += temp;
                } else {
                    other.add(temp);
                }
                sum += temp;
            }

            // 获取是否满足条件
            boolean ret = false;
            // 1.总和不是偶数必定不满足
            if(sum % 2 != 0){
                ret = false;
            // 2.其他组没有数时,3和5组各自和相等即可
            } else if(other.size() == 0) {
                if(fiveSum == threeSum) {
                    ret = true;
                }
            } else {
                //3. 其他组有数时,用下面的双循环逻辑不完整,会漏掉,间隔相加的和,故这样不能找到所有的和
//                for (int i = 0; i < other.size(); i++) {
//                    int targetNum = 0;
//                    for (int j = i; j < other.size(); j++) {
//                        targetNum += other.get(j);
//                        if(sum / 2 - fiveSum == targetNum) {
//                            ret = true;
//                            break;
//                        } 
//                    }
//                }
                // 其他组有数时,递归遍历出,是否某满足的和存在
                ret = getTarget(0,sum / 2 - fiveSum,other);
                
            }
            System.out.println(ret);
        }
    }
    /**
     * 获取是否有满足条件的数
     */
    public static boolean getTarget(int index, int targetNum, List<Integer> other) {
        // 终止条件,递归完ohther。若,targetNum == 0,则满足条件
        // (因为targetNum在递归中会不断剔除某位置的数,直到剔除到0,说明其他组中存在一个和targetNum = sum / 2 - fiveSum)
        if(index == other.size()) {
            return targetNum == 0;
        } else {
            // 有两种情况:使用index位置的数 + 不使用index位置的数
            return getTarget(index + 1,targetNum - other.get(index),other) || getTarget(index + 1, targetNum,other);
        }
    }

}
复制代码

题目来源:牛客网

posted @   对月当歌  阅读(130)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示
点击右上角即可分享
微信分享提示