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)

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