最多的划分来使数组有序 Max Chunks To Make Sorted

2018-12-01 11:05:46

一、Max Chunks To Make Sorted

问题描述:

问题求解:

由于没有重复,所以直观的来看对于每个遇到数,其能够被划分出来的前提是其前面已经有相应的数字,具体可以看下面的图片。

    public int maxChunksToSorted(int[] arr) {
        if (arr == null || arr.length == 0) return 0;
        int res = 0;
        int curMax = arr[0];
        for (int i = 0; i < arr.length; i++) {
            curMax = Math.max(curMax, arr[i]);
            if (curMax == i) res++;
        }
        return res;
    }

 

二、Max Chunks To Make Sorted II

问题描述:

问题求解:

本题是上一题的扩展,可以说是普通化的上一题,由于数字范围以及重复性,难度有了较大的提升,显然是不能直接使用上述的解法了,如果进行离散化,那么至少是O(nlogn)的时间复杂度,有没有O(n)的解法呢?

答案是有的,但是看问题的角度要变化一下,我们可以这么来看这个问题,从左向右遍历整个数组,如果说当前的数字的左边的最大值小于其右边的最小值,那么将这个数和左边进行排序是没有风险的,重复进行这样的操作就可以得到最终的结果。

可以使用两个数组来对左侧最大值和右侧最小值进行保存,整个时间复杂度显然是O(n)。

    public int maxChunksToSorted(int[] arr) {
        if (arr == null || arr.length == 0) return 0;
        int[] maxofleft = new int[arr.length];
        int[] minofright = new int[arr.length];
        maxofleft[0] = arr[0];
        for (int i = 0; i < arr.length; i++) {
            maxofleft[i] = Math.max(maxofleft[i - 1], arr[i]);
        }
        minofright[arr.length - 1] = arr[arr.length - 1];
        for (int i = arr.length - 2; i >= 0; i--) {
            minofright[i] = Math.min(minofright[i + 1], arr[i]);
        }
        int res = 0;
        for (int i = 0; i < arr.length - 1; i++) {
            if (maxofleft[i] <= minofright[i + 1]) res++;
        }
        return res + 1;
    }

 

三、Partition Labels

问题描述:

问题求解:

本题的要求是将一个字符串划分成尽量多的子串,并且保证同一个字符只出现在其中一个子串中。

从直观上来看,我们可以暴力的进行求解,也就是对第一字符进行判断,将其最后出现的位置做标定,如果当前的idx和最后出现位置相同,那么就找到了一个划分,否则对第二个字符进行判断,寻找其最后一个字符出现的位置,并更新最后的位置,重复当前操作即可。

如果暴力检索,那么时间复杂度显然是O(n^2),如果进行预处理,将一个字符的最后出现位置保存下来,那么时间复杂度就可以将到O(n)。

    public List<Integer> partitionLabels(String S) {
        List<Integer> res = new ArrayList<>();
        int[] map = new int[128];
        for (int i = 0; i < S.length(); i++) {
            map[S.charAt(i)] = i;
        }
        int begin = 0;
        int end = 0;
        for (int i = 0; i < S.length(); i++) {
            end = Math.max(end, map[S.charAt(i)]);
            if (end == i) {
                res.add(end - begin + 1);
                begin = end + 1;
            }
        }
        return res;
    }

 

posted @ 2018-12-01 18:57  hyserendipity  阅读(301)  评论(0编辑  收藏  举报