每日一刷经验分享:力扣1217简单. 玩筹码

132 阅读4分钟

力扣1217. 玩筹码

题意

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

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

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

因为题意很多人刚看会不太理解:

难点在于理解题目意思。chips = [1, 2, 2, 2, 3, 15, 23] 意味着位置1有1个筹码,位置2有3个筹码,同样位置3、15、23各有1个筹码。把所有筹码移动到一个位置,移动两步代价为0,那其实我就可以把所有“奇数位置”筹码移动到一个点A(奇数位置),且不必花费任何代价;同理,所有“偶数位置”的筹码移动到点B(偶数位置)也不需要任何代价。最终就是看A,B两点谁的筹码数多,把少的筹码移动到多的筹码的位置,每一个筹码的代价都是1。

  • 示例 1:

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

  • 示例 2:

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

  • 示例 3:

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

Note:1 <= chips.length <= 100,1 <= chips[i] <= 10^9

题型:贪心数组数学

提示:

  1. The first move keeps the parity of the element as it is.
  2. The second move changes the parity of the element.
  3. Since the first move is free, if all the numbers have the same parity, the answer would be zero.
  4. Find the minimum cost to make all the numbers have the same parity.

AC代码

👀Java版本: 方法一:Map记录相关信息

class Solution {
    public int minCostToMoveChips(int[] position) {
        Map<Integer,Integer> map = new HashMap<Integer,Integer>();
        for(int i:position){
            map.put(i,map.getOrDefault(i,0)+1);
        }
        int min1 = Integer.MAX_VALUE;
        int sum;
        for(int key:map.keySet()){
            sum=0;
            for(int t:map.keySet()){
                if(Math.abs(t-key)%2==1){
                    sum+=map.get(t);
                }
            }
            min1 = Math.min(min1,sum);
        }
        return min1;
    }
}

方法二:奇偶数位置上的数比较,因为奇数和偶数分别相互之间移动耗费为0

public int minCostToMoveChips(int[] chips) {
    int odd = 0, even = 0;
	for (int i = 0; i < chips.length; i++) {
		if (chips[i] % 2 == 0) {
			even++;
		} else if (chips[i] % 2 != 0) {
			odd++;
		}
	}
	return Math.min(even, odd);   
    }

分析

为什么这么做是因为移动偶数个的位置使用耗费为0,所以任意偶数位置移动到任意奇数位置除了每次移动2个位置的消耗为0,再需要移动一个位置即可到达对应的位置。同理,任意奇数移动到任意偶数位置的耗费要么是0,要么是1.

方法一解法分析

这个方法使用的是map记录每个位置上的数量,然后再分别对每个位置进行作为目标位置,让其他位置上的节点移动到该位置,所以用了两层for循环,也就是这两层for循环,做了和你多不必要的运算,导致时间的小号很大的浪费。

方法二解法分析

因为移动2个位置不需要代价,那么奇数位置移到奇数位置不用代价,偶数位置移到偶数位置不用代价,那就分别统计奇数位置和偶数位置的个数,相当于把所有奇数放一起,所有偶数的放一起,然后比较奇数的少还是偶数的少,将少的个数移到多的个数位置上去就可以了。

题解过程分析

方法一

Map<Integer,Integer> map:代表用于记录存在数的每个位置,和该位置上对应的个数。 两层for循环用于遍历每一个存在节点的位置,内层循环用于对外层循环的每一个位置作为目标节点,然后再遍历一遍for循环记录到目标节点的位置,并在每次进行内层循环之后和min1进行比较最小值,用于记录整个数组中的最小值

方法二

使用old记录偶数位置的个数,使用even记录奇数的个数,然后遍历统计两者的个数即可,遍历完成之后返回old和even中最小的个数,相比于方法一,这个方法只需要一次for循环即可,而且只需要两个变量记录,大大减少了运行的时间和空间占用。

时间复杂度

方法一

  • 时间复杂度:O(n^2),其中 n 为数组 position 的长度,只对数组进行了一次遍历。

  • 空间复杂度:O(2*n),分别记录对应的位置和对应位置上的数量。

方法二

  • 时间复杂度:O(n),其中 n 为数组 position 的长度,只对数组进行了一次遍历。

  • 空间复杂度:O(1),仅使用常数变量。

总结

一般这种常常根据题意去具体分析该使用什么方法,如果思路敏捷的话,能想到方法二,一下子逼格就上来了是吧。

  1. 方法一:使用Map时间复杂度和空间复杂度太高

image.png

  1. 方法二:使用两个变量分别记录奇数位置上和偶数位置上分别总数量,大大降低了时间和空间复杂度

image.png

我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿