作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/


题目地址: https://leetcode.com/problems/couples-holding-hands/description/

题目描述:

N couples sit in 2N seats arranged in a row and want to hold hands. We want to know the minimum number of swaps so that every couple is sitting side by side. A swap consists of choosing any two people, then they stand up and switch seats.

The people and seats are represented by an integer from 0 to 2N-1, the couples are numbered in order, the first couple being (0, 1), the second couple being (2, 3), and so on with the last couple being (2N-2, 2N-1).

The couples’ initial seating is given by row[i] being the value of the person who is initially sitting in the i-th seat.

Example 1:

Input: row = [0, 2, 1, 3]
Output: 1
Explanation: We only need to swap the second (row[1]) and third (row[2]) person.

Example 2:

Input: row = [3, 2, 0, 1]
Output: 0
Explanation: All couples are already seated side by side.

Note:

  1. len(row) is even and in the range of [4, 60].
  2. row is guaranteed to be a permutation of 0…len(row)-1.

题目大意

有0~N-1这些数字的排列组成的一个数组,0和1,2和3,…,N-2和N-1分别是情侣,现在要让情侣坐在一起,每次能交换两个人的座位,求最少需要换多少次座位。

解题方法

这个题不愧是Hard题,虽然题目简单,但是没有任何思路。

看了Grandyang大神的做法,使用贪心策略。直接找出第偶数个位置是否和他的另一半在一起,是的话不用交换,否则找出另一半在哪里,然后直接把现在和自己坐在一起的人与自己的另一半的位置交换即可。(不会证明)

原文是:

当我们暂时对如何用代码来解决问题没啥头绪的时候,一个很好的办法是,先手动解决问题,意思是,假设这道题不要求你写代码,就让你按照要求排好序怎么做。我们随便举个例子来说吧,比如:

[3 1 4 0 2 5]

我们如何将其重新排序呢?首先明确,我们交换数字位置的动机是要凑对儿,如果我们交换的两个数字无法组成新对儿,那么这个交换就毫无意义。来手动交换吧,我们两个两个的来看数字,前两个数是3和1,我们知道其不成对儿,数字3的老相好是2,不是1,那么怎么办呢?我们就把1和2交换位置呗。好,那么现在3和2牵手成功,度假去了,再来看后面的:

[3 2 4 0 1 5]

我们再取两数字,4和0,互不认识!4跟5有一腿儿,不是0,那么就把0和5,交换一下吧,得到:

[3 2 4 5 1 0]

好了,再取最后两个数字,1和0,两口子,不用动!前面都成对的话,最后两个数字一定成对。而且这种方法所用的交换次数一定是最少的。

使用了一个很高效的求另一半的方式,使用1异或。如果是偶数的话,最后位是0,‘异或’上1等于加了1,变成了可以的成对奇数。如果是奇数的话,最后位是1,‘异或’上1后变为了0,变成了可以的成对偶数。

最坏情况下的时间复杂度是O(N^2),空间复杂度是O(1)。

class Solution(object):
def minSwapsCouples(self, row):
"""
:type row: List[int]
:rtype: int
"""
res = 0
n = len(row)
for i in range(0, n - 1, 2):
if row[i + 1] == (row[i] ^ 1):
continue
for j in range(i + 1, n):
if row[j] == (row[i] ^ 1):
row[j], row[i + 1] = row[i + 1], row[j]
res += 1
return res

另外一个解法,是使用并查集。但是这个解法我没有看懂,所以只贴上代码,不讲解了。

class Solution(object):
def minSwapsCouples(self, row):
"""
:type row: List[int]
:rtype: int
"""
n = len(row)
cnt = n / 2
self.par = range(n)
for i in range(0, n, 2):
x = self.find(row[i] / 2)
y = self.find(row[i + 1] / 2)
if x != y:
self.par[x] = y
cnt -= 1
return n / 2 - cnt def find(self, x):
return x if self.par[x] == x else self.find(self.par[x])

参考资料:

http://www.cnblogs.com/grandyang/p/8716597.html

日期

2018 年 10 月 1 日 —— 欢度国庆!

【LeetCode】765. Couples Holding Hands 解题报告(Python)的更多相关文章

  1. [LeetCode] 765. Couples Holding Hands 情侣牵手

    N couples sit in 2N seats arranged in a row and want to hold hands. We want to know the minimum numb ...

  2. 【LeetCode】62. Unique Paths 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址:https://leetcode.com/problems/unique-pa ...

  3. 【LeetCode】376. Wiggle Subsequence 解题报告(Python)

    [LeetCode]376. Wiggle Subsequence 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.c ...

  4. 【LeetCode】649. Dota2 Senate 解题报告(Python)

    [LeetCode]649. Dota2 Senate 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地 ...

  5. 【LeetCode】911. Online Election 解题报告(Python)

    [LeetCode]911. Online Election 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ ...

  6. 【LeetCode】886. Possible Bipartition 解题报告(Python)

    [LeetCode]886. Possible Bipartition 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu ...

  7. 【LeetCode】36. Valid Sudoku 解题报告(Python)

    [LeetCode]36. Valid Sudoku 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址 ...

  8. 【LeetCode】870. Advantage Shuffle 解题报告(Python)

    [LeetCode]870. Advantage Shuffle 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn ...

  9. 【LeetCode】593. Valid Square 解题报告(Python)

    [LeetCode]593. Valid Square 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地 ...

随机推荐

  1. 【模板】负环(SPFA/Bellman-Ford)/洛谷P3385

    题目链接 https://www.luogu.com.cn/problem/P3385 题目大意 给定一个 \(n\) 个点有向点权图,求是否存在从 \(1\) 点出发能到达的负环. 题目解析 \(S ...

  2. 7个连环问揭开java多线程背后的弯弯绕

    摘要:很多java入门新人一想到java多线程, 就会觉得很晕很绕,什么可见不可见的,也不了解为什么sync怎么就锁住了代码. 本文分享自华为云社区<java多线程背后的弯弯绕绕到底是什么? 7 ...

  3. 报错:Unsupported field: HourOfDay

    报错:Unsupported field: HourOfDay 这个错误就比较搞笑也比较低级了. 代码如下 LocalDate now = LocalDate.now(); String year = ...

  4. 大数据学习day36-----flume02--------1.avro source和kafka source 2. 拦截器(Interceptor) 3. channel详解 4 sink 5 slector(选择器)6 sink processor

    1.avro source和kafka source 1.1 avro source avro source是通过监听一个网络端口来收数据,而且接受的数据必须是使用avro序列化框架序列化后的数据.a ...

  5. 【分布式】Zookeeper的Leader选举-选举过程介绍(经典的Paxos算法解析)

    一.前言 前面学习了Zookeeper服务端的相关细节,其中对于集群启动而言,很重要的一部分就是Leader选举,接着就开始深入学习Leader选举. 二.Leader选举 2.1 Leader选举概 ...

  6. Linux基础命令---elinks文本浏览器

    elinks elinks指令是一个纯文本格式的浏览器,支持颜色.表格.鼠标.菜单操作. 此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.Fedora.   1.语法       ...

  7. Python 基于python实现的http+json协议接口自动化测试框架源码(实用改进版)

    目录 1.      写在前面 2.      开发环境 3.      大致流程 4.      框架简介 5.      运行结果展示 6.      文件与配置 7.      测试接口实例 n ...

  8. hadoop Sort排序

    1 public int getPartition(IntWritable key,IntWritable value,int numPartitions){ 2 int Maxnumber = 12 ...

  9. ActiveRecord教程

    (一.ActiveRecord基础) ActiveRecord是Rails提供的一个对象关系映射(ORM)层,从这篇开始,我们来了解Active Record的一些基础内容,连接数据库,映射表,访问数 ...

  10. Linux上用Jexus部署Asp.Net网站:常规部署与Docker部署

    (一)常规部署 一.把 jexus压缩包下载到linux临时文件夹中. cd /tmp wget linuxdot.net/down/jexus-6.2.x-arm64.tar.gz (不同的操作系统 ...