• [leetcode 周赛 157] 1217 玩筹码


    1217 Play With Chips 玩筹码

    题目描述

    数轴上放置了一些筹码,每个筹码的位置存在数组 chips 当中。

    你可以对 任何筹码 执行下面两种操作之一(不限操作次数,0 次也可以):

    • 将第 i 个筹码向左或者右移动 2 个单位,代价为 0
    • 将第 i 个筹码向左或者右移动 1 个单位,代价为 1

    最开始的时候,同一位置上也可能放着两个或者更多的筹码。

    返回将所有筹码移动到同一位置(任意位置)上所需要的最小代价。

    • 示例 1:

    输入:chips = [1,2,3]
    输出:1
    解释:第二个筹码移动到位置三的代价是 1,第一个筹码移动到位置三的代价是 0,总代价为 1。

    • 示例 2:

    输入:chips = [2,2,2,3,3]
    输出:2
    解释:第四和第五个筹码移动到位置二的代价都是 1,所以最小总代价为 2。

    • 提示:
      • 1 <= chips.length <= 100
      • 1 <= chips[i] <= 10^9

    思路

    • 读题
      移动奇数次位置代价为1, 移动偶数次位置代价为0, 寻找一个位置, 距离其他位置的距离尽量都是偶数

    思路一 遍历所有位置, 选取最小代价

    使用HashMap<Integer, Integer>存储位置该位置上的元素个数
    循环变量, 每个位置与其他位置的距离, 加上其他位置的元素个数, 从而计算出代价
    选出最小代价输出

    • 最坏时间复杂度 O(n^2) n=100 (chips.length <= 100) 位置个数
      思路一

    思路二 取出奇数位置和偶数位置的元素个数最小

    因为不需要将结果位置输出, 并且偶数次移动是没有代价的
    所有同是奇数或同是偶数, 它们之间移动是没有代价的, 而对应的其他奇数或偶数的元素, 就是需要付出的代价
    选出需要付出最小的代价, 即奇或偶数位置上元素个数最小的

    思路三 可以不使用HashMap 直接暴力枚举

    基本思路同思路一, 但不进行记录位置与位置上元素个数, 直接循环暴力枚举(因为数据量不大 chips.length <= 100)

    代码实现

    思路一

    class Solution {
        public int minCostToMoveChips(int[] chips) {
            // maps 存储位置和该位置上元素个数
            Map<Integer, Integer> maps = new HashMap<>(chips.length);
            for (int i : chips) {
                if (!maps.containsKey(i)) {
                    maps.put(i, 0);
                }
                maps.put(i, maps.get(i) + 1);
            }
            //System.out.println("maps:	" + maps);
    
            // keys 存储所有位置信息
            Set<Integer> keys = maps.keySet();
            // cost 所有元素移动到当前位置的代价
            // step 其他位置到当前位置的距离(绝对值)
            // minCost 所有位置中的最小代价
            int cost, step, minCost = Integer.MAX_VALUE;
            for (Integer cur : keys) {
                cost = 0;
                step = 0;
                for (Integer next : keys) {
                    if (!cur.equals(next)) {
                        // 将next位置上的筹码移动到cur位置上
                        step = Math.abs(next - cur);
                        // 距离为偶数 则代价为0 否则代价为1
                        cost += (step % 2 == 1 ? 1 : 0) * maps.get(next);
                        //System.out.println(String.format("%d(%d) --> %d, step:%d, cost:%d",
                        //        next, maps.get(next), cur, step, cost));
                    }
                }
                // 比较当前代价和所存储的最小代价 选出全局最小代价
                minCost = minCost > cost ? cost : minCost;
            }
    
            return minCost;
        }
    }
    

    思路二

    class Solution {
        public int minCostToMoveChips(int[] chips) {
            // cnt 存放奇数和偶数位置上元素个数
            int[] cnt = {0, 0};
            for (int i : chips) {
                // 通过i&1 为0则为偶数 为1则为奇数
                cnt[i&1]++;
            }
            return Math.min(cnt[0], cnt[1]);
        }
    }
    

    思路三

    class Solution {
        public int minCostToMoveChips(int[] chips) {
            int res = Integer.MAX_VALUE;
            int n = chips.length;
            
            for (int i = 0; i < n; i++) {
                int cur = 0;
                for (int j = 0; j < n; j++) {
                    // 距离为奇数则加一
                    cur += Math.abs(chips[j] - chips[i]) % 2;
                }
                res = res > cur ? cur : res;
            }
            
            return res;
        }
    }
    

    参考资源

    第 157 场周赛 全球排名
    【算法实况】体验使用 iPadOS 打算法竞赛 - 力扣周赛 - LeetCode Weekly 157
    力扣周赛录屏-leetcode-weekly-contest-157

  • 相关阅读:
    (C/C++学习笔记) 五. 常变量(只读变量)和宏
    (C/C++学习笔记) 四. 运算符
    (C/C++学习笔记) 三. 作用域和可见性
    (C/C++学习笔记) 一. 基础知识
    计算机科学的基本术语及其英语表达
    模块与包
    Python的递归
    内置函数与匿名函数
    装饰器,迭代器,生成器分析
    命名关键字参数,函数对象,嵌套,名称空间与作用域,闭包
  • 原文地址:https://www.cnblogs.com/slowbirdoflsh/p/11643589.html
Copyright © 2020-2023  润新知