LWC 68: 769. Max Chunks To Make Sorted (ver. 1)

LWC 68: 769. Max Chunks To Make Sorted (ver. 1)

传送门:769. Max Chunks To Make Sorted (ver. 1)

Problem:

Given an array arr that is a permutation of [0, 1, …, arr.length - 1], we split the array into some number of “chunks” (partitions), and individually sort each chunk. After concatenating them, the result equals the sorted array.

What is the most number of chunks we could have made?

Example 1:

Input: arr = [4,3,2,1,0]
Output: 1
Explanation:
Splitting into two or more chunks will not return the required result.
For example, splitting into [4, 3], [2, 1, 0] will result in [3, 4, 0, 1, 2], which isn’t sorted.

Example 2:

Input: arr = [1,0,2,3,4]
Output: 4
Explanation:
We can split into two chunks, such as [1, 0], [2, 3, 4].
However, splitting into [1, 0], 2, [3], [4] is the highest number of chunks possible.

Note:

  • arr will have length in range [1, 10].
  • arr[i] will be a permutation of [0, 1, …, arr.length - 1].

思路:
把数组分成两部分,记作left part 和 right part,求left part 中的最大值,和right part中的最小值,如果最大值比最小值小,说明可以切分。接着递归left part 和 right part。

代码如下:

public int maxChunksToSorted(int[] arr) {
        return dfs(arr, 0, arr.length);
    }

    public int dfs(int[] arr, int s, int e) {
        if (e - s == 1) return 1;
        else {
            for (int i = s + 1; i <= e - 1; ++i) {
                int max = -1;
                int min = 0x3f3f3f3f;
                for (int j = s; j < i; ++j) {
                    max = Math.max(max, arr[j]);
                }
                for (int j = i; j < e; ++j) {
                    min = Math.min(min, arr[j]);
                }
                if (max < min) {
                    return dfs(arr, s, i) + dfs(arr, i, e);
                }
            }
            return 1;
        }
    }

可以改成迭代形式,如下:

    public int maxChunksToSorted(int[] arr) {
        int n = arr.length;
        int ans = 1;
        for (int i = 1; i < n; ++i) {
            int max = -1;
            int min = 0x3f3f3f3f;
            for (int j = 0; j < i; ++j) {
                max = Math.max(max, arr[j]);
            }
            for (int j = i; j < n; ++j) {
                min = Math.min(min, arr[j]);
            }
            if (max <= min) ans ++;
        }
        return ans;
    }

因为切割点满足left part 的 max 一定小于 right part 的min,所以在后续找切割点的时候,left part 的max一定会更新(非递减),于是可以省去一个for循环:

    public int maxChunksToSorted(int[] arr) {
        int n = arr.length;
        int ans = 1;
        int max = -0x3f3f3f3f;
        for (int i = 1; i < n; ++i) {
            int min = 0x3f3f3f3f;
            max = Math.max(max, arr[i - 1]);
            for (int j = i; j < n; ++j) {
                min = Math.min(min, arr[j]);
            }
            if (max <= min) ans ++;
        }
        return ans;
    }

于是min和max的原理一样,可以在O(n)内得到min[i, n],表示arr从i到末尾的最小值。

代码如下:

    public int maxChunksToSorted(int[] arr) {
        int n = arr.length;
        int ans = 1;
        int max = -0x3f3f3f3f;
        int[] min = new int[n];
        min[n - 1] = arr[n - 1];
        for (int i = n - 2; i >= 0; --i) {
            min[i] = Math.min(arr[i], min[i + 1]);
        }
        for (int i = 1; i < n; ++i) {
            max = Math.max(max, arr[i - 1]);
            if (max <= min[i]) ans ++;
        }
        return ans;
    }

Python版本:

class Solution(object):
    def maxChunksToSorted(self, arr):
        """
        :type arr: List[int]
        :rtype: int
        """
        n = len(arr)
        ans = 1
        mins = [float('inf')] * n
        maxs = [-float('inf')] * n
        mins[-1] = arr[-1]
        for i in range(n - 2, -1, -1):
            mins[i] = min(mins[i + 1], arr[i])
        maxs[0] = arr[0]
        for i in range(1, n - 1, 1):
            maxs[i] = max(maxs[i - 1], arr[i])

        for i in range(1, n):
            if (maxs[i - 1] <= mins[i]): ans += 1
        return ans

以上solution也可以解决768. Max Chunks to Make Sorted (ver. 2)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值