字符串的字典序重构问题

144 阅读2分钟

问题描述

给定字符串和整数 k,通过多次将前 k 个字符中的一个移到末尾的操作,找出字典序最小的字符串。


测试样例

样例1:

输入:s = "def", k = 1
输出:"def"

样例2:

输入:s = "bca", k = 2
输出:"abc"

样例3:

输入:s = "dabc", k = 3
输出:"abcd"

行行检查字字改,反反复复终得道😭😭😭。好像只要k大于1,就可以对整个数组顺序排列。但是当k=1时不行,需要找出最小的那个字符串。

  • 当 k > 1 时,可以直接对字符串进行排序,因为可以移动前 k 个字符中的任意一个,所以可以视为对整个字符串进行排序。

  • 当 k = 1 时,需要找到字典序最小的字符串。具体步骤如下:

    1. 找到字符串中的最小字符。

    2. 计算这个最小字符在字符串中不连续出现的索引对列表。

    3. 如果最小字符只有一个,直接构造字符串并返回。

    4. 如果最小字符有多个,则重复以下步骤直到只剩一个索引对:

      • 找到索引对列表中下一个最小字符。
      • 更新索引对列表,移除已经处理过的字符。
    5. 使用最后一个索引对构造并返回字符串。


import java.util.*;
public class Main {
    public static String solution(String s, int k) {
        String res="";
        int start;
        if(k>1){
            char[] charArray = s.toCharArray();
            Arrays.sort(charArray);
            return  new String(charArray);
        }


        char minChar= QueryMinCharAtString(s);
        List<int[]> indexAndNext=GetIndexAndNext(minChar,s);
        if(indexAndNext.size()==1){
            start=indexAndNext.get(0)[0];
            res=BuildStringAtStart(start,s);
            System.out.println("k=1而且最下字符只有一个,结果是:"+res+"))))))))))))))))))))");
            return res;
        }
        while(true){
            char minC=minCharAtList(indexAndNext,s);
            List<int[]> ints = updataList(indexAndNext, s, minC);
            if(ints.size()==1){
                start= ints.get(0)[0];
                res=BuildStringAtStart(start,s);
                return res;
            }
            indexAndNext=ints;
        }


    }
    //找出字符串里面的最小字符
    static char QueryMinCharAtString(String s){
        char minChar=s.charAt(0);
        int i,len=s.length();
        for(i=0;i<len;i++){
            if(s.charAt(i)<minChar){
                minChar=s.charAt(i);
            }
        }
        return minChar;
    }
    //计算字符串里面某个字符不连续出现的list<第一个的索引,下一个的索引>
    static List<int[]> GetIndexAndNext(char ch,String s){
        int  i,len=s.length();
        List<int[]> indexAndNext=new  ArrayList<>();
        if(s.charAt(0)==ch){
            indexAndNext.add(new int[]{0,1});
        }
        for(i=1;i<len;i++){
            if(s.charAt(i)==s.charAt(i-1)){
                continue;
            }
            if(s.charAt(i)==ch){
                indexAndNext.add(new int[]{i,i+1});
            }
        }
        return indexAndNext;
    }

    //从字符串的第start个字符开始构造字符串
    static String BuildStringAtStart(int start ,String s){
        StringBuilder sb=new StringBuilder();
        sb.append(s.substring(start, s.length()));
        for(int i=0;i<start;i++){
            sb.append(s.charAt(i));
        }
        return sb.toString();
    }

    //找下一个的最小值(char)
    static char minCharAtList(List<int[]> list,String s){
        char min=s.charAt(list.get(0)[1]);
        for(int i=1;i<list.size();i++){
            if(s.charAt(list.get(i)[1])<min){
                min=s.charAt(list.get(i)[1]);
            }
        }
        return min;
    }
    //新建一个list更新list
    static List<int[]> updataList(List<int[]> arr,String s,char minch){
        List<int[]> res=new ArrayList<>();
        for(int i=0;i<arr.size();i++){
            if(s.charAt(arr.get(i)[1])==minch){
                res.add(new int[]{arr.get(i)[0],arr.get(i)[1]+1});
            }
        }
        return res;
    }

    public static void main(String[] args) {
        System.out.println(solution("def", 1) == "def");
        System.out.println(solution("bca", 2) == "abc");
        System.out.println(solution("dabc", 3) == "abcd");
    }
}