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)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章