字典序是指从前到后比较两个字符串大小的方法。首先比较第1个字符,如果不同则第1个字符较小的字符串更小,一直这样子比较下去。

比如:

s1:ABCDEs2:ABCCE 两个字符串,s1的 D 比 s2的 C要更加大一点,所以s1 > s2。


现在有这样一个问题,

给定长度为N的字符串S,要构造一个长度为 N 的字符串 T。起初 ,T 是一个空串,随后反复进行下列任意操作,

  • 从 S 的头部删除一个字符,加到 T 的尾部。
  • 从 S 的尾部删除一个字符,加到 T 的尾部。

目标是构造字典序最小的字符串 T。

这类题型一般利用贪心来做,贪心就是就是遵循某种规则,不断贪心地选取当前的最优策略的算法。

每做出的一步选择都是当前的最优策略,并不需要考虑整体,但难点就在于当前最优策略的选择,拿上面那道题继续分析,

要创建字典序最小的字符串T,我们只需要保证字符串的前面尽量较小,所以每次从字符串 S 的首尾取相对较小的加入到字符串 T 中,这就是策略,但这个策略还可能遇到一个问题,如果当首尾的字符此时相等的话,该如何选择?这时候就要比较下一个了,选择下一个字符里面相对较小的加入到字符串 T 中。这两者结合就是我们的贪心策略。

有点懵?

不急,我们来看看图解。

假定给定的字符串 S = “ACDBCB”,

一开始,两指针指向字符串 S 的首尾,比较两者的大小,将小的一位加入到字符串 T 中,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KPUXSQU8-1587397993732)(https://note.youdao.com/yws/api/personal/file/WEB3456d3793d40c320734e1ed8a5f21870?method=download&shareKey=02b9e33205368bdc04735cace3be3592)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6x9Ulh0e-1587397993735)(https://note.youdao.com/yws/api/personal/file/WEBac8970a5de087e54f280c4a526c55e4b?method=download&shareKey=e83798b44b36054879de800e2e1aebbb)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JFAaqBhe-1587397993738)(https://note.youdao.com/yws/api/personal/file/WEB51ddf14e2f9cc1246a1de464f72cde7b?method=download&shareKey=23bbeaccb17dbf86e0f321cb774de00d)]

此时两指针对应的字符相等,这时候要判断下一位的大小,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4nM19tbw-1587397993743)(https://note.youdao.com/yws/api/personal/file/WEB1dc5c524e818afbf2fb7dee7b3d6144a?method=download&shareKey=9e06ae44b3b788c1d8373bf3868c5159)]

B < D,所以将右侧的先加入,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j20yUjD3-1587397993746)(https://note.youdao.com/yws/api/personal/file/WEB0cb4f8b41d3b817730c5180d659245d0?method=download&shareKey=d7ca2ee4470c4d9cf7a03883be814783)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uQZ2nMCq-1587397993748)(https://note.youdao.com/yws/api/personal/file/WEB679ae8133d4ba32acf96e0686f2979fc?method=download&shareKey=b2bd484581b93e0478165cb2ce3f106e)]

在这里插入图片描述


应该够清晰了吧,那么我们可以写一下伪代码了,伪代码主要是总结以上思路,以便更好的转换成最终代码。

# String S;
# String T;
# left, right
while(left <= right) {
	如果左边较小,将左边加入T;
    如果右变较小,将右边加入T;
    if(相等) {
        i = left + 1;
        j = right - 1;
        while(i <= j) {
            如果左边较小,将左边加入T;
    		如果右变较小,将右边加入T;
            if(相等)
                i++;
                j--;
        }
    }
}

好,以上应该都比较好理解了,那可以直接转成我们的代码了。

class Solution {
    public String bestCowLine(String S) {
        String T = "";
        int left = 0;
        int right = S.length() - 1;
        char[] temp = S.toCharArray();
        //左右两指针,向中间移动
        while(left <= right) {
            //标记左边是否小过右边
            boolean l = false;
            //如果左右两边一致,就跳出循环,不一致就一直寻找
            for(int i = 0; left + i <= right; i++) {
                //如果左边小于右边,标记并跳出
                if(temp[left + i] < temp[right - i]) {
                    l = true;
                    break;
                }
                //如果右边小于左边,标记并跳出
                else if(temp[left + i] > temp[right - i]) {
                    l = false;
                    break;
                }
            }
            //加入到字符串 T 中
            if(left == true)
                T += temp[left++];
            else
                T += tempS[right--];
        }
        return T;
    }
}


整理于 2020.4.19

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐