【C/C++】1217. 玩筹码

261 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第13天,点击查看活动详情


题目链接:1217. 玩筹码

题目描述

有 n 个筹码。第 i 个筹码的位置是 position[i] 。

我们需要把所有筹码移到同一个位置。在一步中,我们可以将第 i 个筹码的位置从 position[i] 改变为:

  • position[i] + 2 或 position[i] - 2 ,此时 cost = 0
  • position[i] + 1 或 position[i] - 1 ,此时 cost = 1 返回将所有筹码移动到同一位置上所需要的 最小代价 。

提示:

  • 1chips.length1001 \leqslant chips.length \leqslant 100
  • 1chips[i]1091 \leqslant chips[i] \leqslant 10^9

示例 1:

chips_e1.jpg

输入:position = [1,2,3]
输出:1
解释:第一步:将位置3的筹码移动到位置1,成本为0。
第二步:将位置2的筹码移动到位置1,成本= 1

示例 2:

chip_e2.jpg

输入: position = [2,2,2,3,3]
输出: 2
解释: 我们可以把位置3的两个筹码移到位置2。每一步的成本为1。总成本= 2

示例 3:

输入: position = [1,1000000000]
输出: 1

整理题意

题目给定长度为 n 的数组 position,表示 n 个筹码的位置,position[i] 表示第 i 个筹码的位置,题目想让所有筹码放在同一个位置上,但是移动筹码是需要花费的:

  • 将某个筹码位置向前或者向后移动两格无需花费;
  • 将某个筹码位置向前或者向后移动一格需要 1 花费; 求将所有筹码放在同一个位置上的最小花费是多少。

需要注意每次只能移动一个筹码,不能将某个位置上的筹码一起移动。

解题思路分析

根据题目给定的移动规则可知,奇数位置上的筹码无论经过多少次 ±2 的移动花费仍然是 0,且位置任然在奇数位置上,偶数位置同理。

那么考虑将所有奇数位置上的筹码移动到偶数位置上所需要花费为奇数位置上筹码个数,再将所有偶数位置上的筹码通过花费为 0±2 操作移动到同一个位置上即可;同理我们也可以将所有偶数位置上的筹码移动到奇数位置上,再将奇数位置上的所有筹码移动到一个位置上。

综上我们可以得知将所有筹码移动到同一位置上的最小花费为:奇数位置上的筹码个数偶数位置上的筹码个数 取最小值即可。

具体实现

  1. 统计数组中奇数位置上筹码的个数。
  2. 统计数组中偶数位置上筹码的个数。
  3. 返回二者中较小的一个即可。

在判断奇偶数时采用位运算 & 操作,判断二进制下最低为是否为 1 即可,因为位运算比模运算快。

复杂度分析

  • 时间复杂度:O(n)O(n),其中 n 为数组 position 的长度,只对数组进行了一次遍历。
  • 空间复杂度:O(1)O(1),仅使用常数变量。

代码实现

class Solution {
public:
    int minCostToMoveChips(vector<int>& position) {
        //even记录偶数位置个数,odd记录奇数位置个数
        int even = 0, odd = 0;
        int n = position.size();
        //统计奇偶位置个数
        for(int i = 0; i < n; i++){
            if(position[i] & 1) odd++;
            else even++;
        }
        //取最小值即可
        return min(odd, even);
    }
};

总结

  • 该题核心思想为 统计数组中奇数和偶数的个数
  • 注意每步只能移动一个筹码,即使所有筹码在同一个位置,也只能一个一个的移动。
  • 解题核心突破口为筹码前后移动两格无需花费,那么就可以把题目化简为奇数位置和偶数位置上的筹码两类。
  • 测试结果:

1217.png

结束语

很多时候,成功的人不是比你更聪明,也不是比你更好运,只是他们在每一件看似微不足道的小事上,都能付出比你更多的认真和努力,也比你更有耐心和责任心。认真做事的人,终会得到生活最好的犒赏。新的一天,加油!