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


题目地址:https://leetcode.com/problems/minimum-swaps-to-make-sequences-increasing/description/

题目描述

We have two integer sequences A and B of the same non-zero length.

We are allowed to swap elements A[i] and B[i]. Note that both elements are in the same index position in their respective sequences.

At the end of some number of swaps, A and B are both strictly increasing. (A sequence is strictly increasing if and only if A[0] < A[1] < A[2] < ... < A[A.length - 1].)

Given A and B, return the minimum number of swaps to make both sequences strictly increasing. It is guaranteed that the given input always makes it possible.

Example:

Input: A = [1,3,5,4], B = [1,2,3,7]
Output: 1
Explanation:
Swap A[3] and B[3]. Then the sequences are:
A = [1, 3, 5, 7] and B = [1, 2, 3, 4]
which are both strictly increasing.

Note:

  • A, B are arrays with the same length, and that length will be in the range [1, 1000].
  • A[i], B[i] are integer values in the range [0, 2000].

题目大意

一个字符串中有0有1,问最少翻转多少个字符能够使得这个字符串编程一个单调递增的字符串。

解题方法

动态规划

这个题和周赛926. Flip String to Monotone Increasing基本一模一样,如果我早点把这个题搞明白的话,周赛的926应该也能做出来了。926题我写的非常的详细,是我写的最认真的一次,强烈建议看下926题的动态规划部分。

我是看了画画酱的讲义的,如下图。这个题也是需要做交换,可以定义两个数组keep和swap,这两个数组的含义是我们交换或者不交换第i个位置使得两个数组都保持严格的单调递增需要进行的交换数量。

那么,当A[i] > A[i - 1] and B[i] > B[i - 1]时,我们可以不交换当前的数字,这个时候前面的数字也不能交换;也可以交换当前的数字,同时需要把前面的数字也进行交换。即,这种情况下,前面的位置和现在的位置做的是同样的交换。

在做了上面的操作之后,我们得到的仍然是有序的部分,但是没有结束,因为我们可能还会出现A[i] > B[i - 1] and B[i] > A[i - 1]这种交叉的情况。这个时候考虑前面的位置和现在的位置做相反的交换。

A[i] > B[i - 1] and B[i] > A[i - 1]时,我们如果不交换当前的数字,同时对前面的位置强制交换,判断交换后的次数是不是比当前的交换次数少;如果我们交换这个位置,同时强制前面的数字不交换,那么当前的交换次数应该是前面不交换的次数+1和当前交换次数的最小值。

上面两种判断并不是if-else的关系,因为,这两种情况同时存在。我们通过这两种情况,考虑了4种情况:当前位置换、不换与前面的位置换、不换的组合。注意第二个判断里面求最小值是相对于自身做比较的,因为我们不一定需要对前面的位置进行操作。

另外,需要注意的是,一般情况的dp初始化都是0或者1,但是这个题需要求最小值,其实已经提醒我们不是0或者1.实际上,需要使用无穷大表示初始情况下,还没有做翻转操作时交换次数应该是无穷多。而不是0表示初始情况下不用交换就能到达有序。

时间复杂度是O(N),空间复杂度是O(N).

class Solution(object):
def minSwap(self, A, B):
"""
:type A: List[int]
:type B: List[int]
:rtype: int
"""
N = len(A)
keep = [float('inf')] * N
swap = [float('inf')] * N
keep[0] = 0
swap[0] = 1
for i in range(1, N):
if A[i] > A[i - 1] and B[i] > B[i - 1]:
keep[i] = keep[i - 1]
swap[i] = swap[i - 1] + 1
if A[i] > B[i - 1] and B[i] > A[i - 1]:
keep[i] = min(keep[i], swap[i - 1])
swap[i] = min(swap[i], keep[i - 1] + 1)
return min(keep[N - 1], swap[N - 1])

这个题如果改成和926题一样的二维数组的dp的话,应该这么写,其实和上面的做法没有任何区别。

class Solution(object):
def minSwap(self, A, B):
"""
:type A: List[int]
:type B: List[int]
:rtype: int
"""
N = len(A)
dp = [[float('inf'), float('inf')] for _ in range(N)]
dp[0][0] = 0
dp[0][1] = 1
for i in range(1, N):
if A[i] > A[i - 1] and B[i] > B[i - 1]:
dp[i][0] = dp[i - 1][0]
dp[i][1] = dp[i - 1][1] + 1
if A[i] > B[i - 1] and B[i] > A[i - 1]:
dp[i][0] = min(dp[i][0], dp[i - 1][1])
dp[i][1] = min(dp[i][1], dp[i - 1][0] + 1)
return min(dp[N - 1][0], dp[N - 1][1])

显然,上面的做法中,每次dp转移操作只和前面的一个状态有关,所以,可以优化空间复杂度到O(1)。对于每次

代码如下:

class Solution(object):
def minSwap(self, A, B):
"""
:type A: List[int]
:type B: List[int]
:rtype: int
"""
N = len(A)
keep, swap = 0, 1
for i in range(1, N):
curswap, curkeep = float('inf'), float('inf')
if A[i] > A[i - 1] and B[i] > B[i - 1]:
curkeep, curswap = keep, swap + 1
if A[i] > B[i - 1] and B[i] > A[i - 1]:
curkeep, curswap = min(curkeep, swap), min(curswap, keep + 1)
keep, swap = curkeep, curswap
return min(keep, swap)

参考资料

https://leetcode.com/problems/flip-string-to-monotone-increasing/discuss/183859/Java-DP-using-O(N)-time-and-O(1)-space

日期

2018 年 10 月 21 日 —— 新的一周又开始了

【LeetCode】801. Minimum Swaps To Make Sequences Increasing 解题报告(Python)的更多相关文章

  1. LeetCode 801. Minimum Swaps To Make Sequences Increasing

    原题链接在这里:https://leetcode.com/problems/minimum-swaps-to-make-sequences-increasing/ 题目: We have two in ...

  2. [LeetCode] 801. Minimum Swaps To Make Sequences Increasing 最少交换使得序列递增

    We have two integer sequences A and B of the same non-zero length. We are allowed to swap elements A ...

  3. 801. Minimum Swaps To Make Sequences Increasing

    We have two integer sequences A and B of the same non-zero length. We are allowed to swap elements A ...

  4. 【leetcode】801. Minimum Swaps To Make Sequences Increasing

    题目如下: We have two integer sequences A and B of the same non-zero length. We are allowed to swap elem ...

  5. 801. Minimum Swaps To Make Sequences Increasing 为使两个数组严格递增,所需要的最小交换次数

    [抄题]: We have two integer sequences A and B of the same non-zero length. We are allowed to swap elem ...

  6. [LeetCode] Minimum Swaps To Make Sequences Increasing 使得序列递增的最小交换

    We have two integer sequences A and B of the same non-zero length. We are allowed to swap elements A ...

  7. [Swift]LeetCode801. 使序列递增的最小交换次数 | Minimum Swaps To Make Sequences Increasing

    We have two integer sequences A and B of the same non-zero length. We are allowed to swap elements A ...

  8. 【LeetCode】926. Flip String to Monotone Increasing 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 Prefix计算 动态规划 参考资料 日期 题目地址 ...

  9. 【LeetCode】26. Remove Duplicates from Sorted Array 解题报告(Python&C++&Java)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 双指针 日期 [LeetCode] https:// ...

随机推荐

  1. 自定义char类型字符,django中事务

    自定义char类型字符 # 自定义char类型,继承Field父类 class MyCharField(Field): def __init__(self, max_length, *args, ** ...

  2. Linux之sed命令常见用法

    1. sed(stream editor),流编辑器 linux中,主要中sed命令实现对文件的增删改替换查 名称 sed - 用于过滤和转换文本的流编辑器 SYNOPSIS sed [选项]... ...

  3. CSS3实现字体描边

    CSS3实现字体描边的两种方法 -webkit-text-stroke: 1px #fff;:不建议,向内描边,字体颜色变细,效果不佳: 用box-shadow模拟描边,向外描边,保留字体粗细,赞! ...

  4. C#序号

    OnRowCreated="gridViewCorrection_RowCreated" <asp:BoundField HeaderText="序号" ...

  5. Java日期格式转换不用发愁

    前言 Java 中日期.时间相关的类相当的多,并且分不同的版本提供了不同的实现,包括 Date . Calendar . LocalDateTime . ZoneDateTime . OffsetDa ...

  6. SpringCloud微服务实战——搭建企业级开发框架(三十二):代码生成器使用配置说明

    一.新建数据源配置 因考虑到多数据源问题,代码生成器作为一个通用的模块,后续可能会为其他工程生成代码,所以,这里不直接读取系统工程配置的数据源,而是让用户自己维护. 参数说明 数据源名称:用于查找区分 ...

  7. JavaScript 链表

    ------------恢复内容开始------------ 背景 数组并不总是组织数据的最佳数据结构,原因如下.在很多编程语言中,数组的长度是固定的,所以当数组已被数据填满时,再要加入新的元素就会非 ...

  8. Android项目的settings.gradle和build.gradle

    gradle构建的项目中的build.gradle和settings.gradle文件 build.gradle 浅析(一) 史上最全的Android build.gradle配置教程 Android ...

  9. spring boot集成mybatis框架

    概述 中文官网:http://www.mybatis.cn 参考教程:https://www.w3cschool.cn/mybatis MyBatis Plus:http://mp.baomidou. ...

  10. When do we use Initializer List in C++?

    Initializer List is used to initialize data members of a class. The list of members to be initialize ...