字节跳动2017笔试【Magic】

18 篇文章 0 订阅

【题目描述】 给一个包含 n个整数元素的集合 个整数元素的集合 a,一个包含 m个整数元素的集合 b。
定义 magic操作为,从一个集合中取出元素放到另里且过后每的平均值都大于操作前。
注意以下两点:
①不可以把一个集合的元素取空,这样就没有平均值了
②值为 x的元素从集合 b取出放入集合a,但集合 a中已经有值为 x的元素,则 a的平均值不变(因为集 合元素不会重复), b的平均值可能会改变(因为 x被取出了)
问最多可以进行少次 magic操作
输入:
3 5
1 2 5
2 3 4 5 6
输出:
2

1、深度优先搜索


package ZiJieTiaoDong;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Scanner;


public class MoveMagic {
    static int N = 0;
    static int M = 0;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        N = n;
        M = m;
        HashSet<Integer> setA = new HashSet<>();
        ArrayList<Integer> list = new ArrayList<>();
        double sumA = 0;
        double sumB = 0;
        int a = 0;
        for (int i = 0; i < n; i++) {
            a = sc.nextInt();
            setA.add(a);
            sumA += a;
        }
        for (int i = 0; i < m; i++) {
            a = sc.nextInt();
            list.add(a);
            sumB += a;
        }
        double aveA = sumA / n;
        double aveB = sumB / m;
        dfs(sumA, sumB, aveA, aveB, setA, list);
        System.out.println(count);

    }

    static int count = 0;

    public static void dfs(double sumA, double sumB, double aveA, double aveB, HashSet<Integer> setA,
            ArrayList<Integer> list) {
        if (list.size() == 0) {
            count = list.size() - 1;
            return;
        }
        int n = setA.size();
        int m = list.size();
        for (int i = 0; i < list.size(); i++) {
            int value = list.get(i);
            if ((sumA + value) / (n + 1) > aveA && (sumB - value) / (m - 1) > aveB) {//满足要求
                setA.add(value);
                list.remove(i);
                aveA = (sumA + value) / (n + 1);
                aveB = (sumB - value) / (m - 1);
                dfs(sumA + value, sumB - value, aveA, aveB, setA, list);//操作后,递归
                list.add(i, value);//未操作
                if (setA.size() == n + 1) {
                    setA.remove(value);
                }
                aveA = sumA / n;
                aveB = sumB / m;
            }
        }
        if (M - list.size() > count) {
            count = M - list.size();
        }
    }
}

2、迭代

从平均值大的team_a中取出比team_a平均值小且比team_b大的最小元素放入team_b中

def compete(team_a, team_b):
    def find_min(team_a, ave_a, ave_b):
        # 查找可以动的数值
        if len(team_a) == 1:
            return -1
        for a in sorted(team_a):
            if ave_b < a < ave_a:
                return a
        return -1

    team_a, team_b = set(team_a), set(team_b)  # 转换成集合
    n, m = len(team_a), len(team_b)  # 计算长度
    sum_a, sum_b = sum(team_a), sum(team_b)  # 计算和
    ave_a, ave_b = sum_a / n, sum_b / m  # 计算平均值
    if ave_a < ave_b:  # 交换team_a,和team_b, 保持team_a永远是平均值大的那个
        team_a, team_b = team_b, team_a
        ave_a, ave_b = ave_b, ave_a
        sum_a, sum_b = sum_b, sum_a
        n, m = m, n

    min_val = find_min(team_a, ave_a, ave_b)  # 查找可以动的数值
    res = 0
    while min_val != -1:
        team_a.remove(min_val)  # team_a中取出
        team_b.add(min_val)  # team_b中加入
        # 更新数值
        sum_a -= min_val
        sum_b += min_val
        n -= 1
        m += 1
        ave_a, ave_b = sum_a / n, sum_b / m
        res += 1
        if ave_a < ave_b:  # 保持team_a永远是平均值大的那个
            team_a, team_b = team_b, team_a
            ave_a, ave_b = ave_b, ave_a
            sum_a, sum_b = sum_b, sum_a
            n, m = m, n
        min_val = find_min(team_a, ave_a, ave_b)  # 重新查找可以动的数值
    return res

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值