[leetcode每日一题2021/2/14]765. 情侣牵手

题目来源于leetcode,解法和思路仅代表个人观点。传送门
难度:困难(今天虾仁猪心)
时间:40min

题目

N 对情侣坐在连续排列的 2N 个座位上,想要牵到对方的手。 计算最少交换座位的次数,以便每对情侣可以并肩坐在一起。 一次交换可选择任意两人,让他们站起来交换座位。

人和座位用 0 到 2N-1 的整数表示,情侣们按顺序编号,第一对是 (0, 1),第二对是 (2, 3),以此类推,最后一对是 (2N-2, 2N-1)。

这些情侣的初始座位 row[i] 是由最初始坐在第 i 个座位上的人决定的。

示例 1:

输入: row = [0, 2, 1, 3]
输出: 1
解释: 我们只需要交换row[1]和row[2]的位置即可。

示例 2:

输入: row = [3, 2, 0, 1]
输出: 0
解释: 无需交换座位,所有的情侣都已经可以手牵手了。

说明:

len(row) 是偶数且数值在 [4, 60]范围内。
可以保证row 是序列 0…len(row)-1 的一个全排列。

思路

每个对 的第一个数为num,第二个数为spouse。只需要num和spouse相邻就可以了。而且输入保证是2N个数,那么肯定能凑完N对。

  1. 如果要把所有对 凑完,那么num和spouse肯定在数组的(2i-2,2i-1)的位置上,即num前面有2k个数。
  2. 题目要求最小的交换次数。但是实际上只需要保证交换不多余就行,即每次交换至少有1对凑成

在这里插入图片描述

并查集

(1,3),(3,2),(1,2)凑成一个集合,(4,4)凑成一个集合。只需要计算每个集合中边的数目,即是最小的交换次数。

贪心

使用一个map记录指针到 i i i为止,数字的所在数组的位置。
每次都尝试着去匹配(交换它相邻元素)map中已存在的数字,(如果配对的数字不存在,就不匹配)。


为什么可行?
每次都至少有一对凑成

要保证每次都不为以后的操作产生多余的交换。

  1. 每次交换的时候都至少凑成1对
  2. 每次交换都需要保证 i i i前面有 2 k 2k 2k个数字

代码

贪心

class Solution {
public:
    template <typename T>
    void swap(T &a,T &b){
        T temp = a;
        a = b;
        b = a;
    }
    int minSwapsCouples(vector<int>& row) {
        int ans = 0;
        //哈希表,记录第i的元素为止的位置
        //匹配交换的任务,交给第二个元素
        unordered_map<int,int> map;
        //数组大小
        int n = row.size();
        for(int i=0;i<n;i++){
            //当前位置的元素
            int& num = row[i];
            map[num] = i;
            //当前位置的元素如果为偶数,则为第一个数字,奇数为第二个数字
            //如:(0,1)中0为第一个数字,1为第二个数字
            int spouse = 0;
            if(num%2 == 0){
                //偶数,找后一个数字
                spouse = num + 1;
            }else{
                //奇数,找前一个数字
                spouse = num - 1;
            }
            //如果配偶不存在,则继续往后找
            //如果配偶存在
            if(map.count(spouse)){
                //配偶的位置
                int j = map[spouse];
                //与它旁边的数字交换
                /*
                * 为什么要这样交换?
                * 确保第i对前面有2k个数字【k对】
                */
                if(j%2 == 0){
                    if(num != row[j+1]){
                        swap(num,row[j+1]);
                        ans++;
                    }
                }else{
                    if(num != row[j-1]){
                        swap(num,row[j-1]);
                        ans++;
                    }
                }
                //更新map
                map[row[i]] = i;
            }
        }
        return ans;
    }
};

算法复杂度

时间复杂度: O(n),n为数组长度。进行一次遍历
空间复杂度: O(n),n为数组长度。用于哈希表存储元素的位置。

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值