雜題分享--部分翻轉字符串

 * 描述:
 * 給定一個字符串str和長度leftsize,
 * 請把str左側leftsize的部分和右部分做整體交換。要求額外空間複雜度O(1)。
 * 例如:
 * 輸入: abcde 3
 * 輸出: deabc
 * 輸入: abcdefgh 5
 * 輸出: fghabcde
解法一:(10W人中99000人都會的解法) 
    應用左神一句話,大家都會得東西,你拿出來毫無意義,拿什麼凸顯自己,人家憑啥要你。
分三次翻轉 先翻轉前 leftsize個 在翻轉其它的 最後整體翻轉 
先翻轉 left --> left + leftsize
然後翻轉 left + leftsize + 1 --> right 
最後翻轉 整體

例如: abcde 3  
    首先翻轉 abc -> cba
    然後翻轉 de -> ed 
    此時整個字符串爲 cbaed
    然後翻轉整個字符串結果爲:deabc
複雜度分析:
    空間複雜度:O(1) 只有有限的幾個變量
    時間複雜度:
        假設左半部分是 L 右半部分是 R     
        翻轉左邊 L / 2
        翻轉右邊 R / 2
        整體翻轉 (L + R) / 2
        時間複雜度 大約是 O(2n)
解法一代碼實現:
public class Code1 {
    // 從 left 到 fight 翻轉字符串 
    public static void reserve(char[] chars, int left, int right) {
        while (left < right) {
            char temp = chars[left];
            chars[left++] = chars[right];
            chars[right--] = temp;
        }
    }

    //分三次翻轉 先翻轉前 leftsize個 在翻轉其它的 最後整體翻轉
    //先翻轉 left --> mid 然後翻轉 mid + 1 --> right 最後翻轉 整體
    public static String solution1(char[] chars, int left, int mid, int right) {
        reserve(chars, left, mid);
        reserve(chars, mid + 1, right);
        reserve(chars, left, right);
        return String.valueOf(chars);
    }

    public static String solution1(String str, int leftsize) {
        //判空
        if (leftsize <= 0 || leftsize >= str.length()) {
            return str;
        }
        return solution1(str.toCharArray(),0,leftsize - 1, str.length() - 1);
    }
    public static void main(String[] args){
        System.out.println(solution1("abcde", 3));
    }
}
解法二:
abcdefgh 5
    將上例劃分爲左右兩個部分 左5 右str.length - 5 = 3  abcde(left) fgh(right)
    取左右部分最小的值爲same 作爲交換條件 即爲 same = 3
    首先順序交換 前三個和後三個 abc fgh
    交換完成之後 結果爲 fgh de abc
    由於是交換之前左部分長 所以是左部分開頭same(3)個已經處理完畢 fgh
    新的左部分變爲 5-3 = 2 de 右部分爲 3 abc
    新的same = 左右部分字符個數的最小值 即爲 2
    接下來只需要更改對應指針的值 此問題就遞歸爲 deabc 2(same)
    此時是右邊長 de abc
    還是順序交換最短的部分所包含的字符數次 也就是2次  左2 < 右3
    結果就變爲 bcade
    由於是交換之前右邊長 所以 右側same(2)個處理完畢 de
    新的左部分爲 bc 2 右部分爲 a 1
    此時變爲子問題 bca 1(same)
    繼續交換 結果 acb
    由於是交換之前左部分長 所以a 不動 此時變爲子問題 cb 1(same)
    由於是左邊等於右邊的長度 所以進行最後一次交換
    結果爲bc
總體變化流程爲:||之間的表示已經處理完畢
   abcdefgh -> |fgh| deabc -> |fgh| bca |de| -> |fgha| cb |de| -> fghabcde
   abcdefgh 5   -> deabc 2 -> bca 1 -> cb 1
解法二代碼實現:
public class Code2 {
    //此題的註釋以例二爲例
    public static String solution2(String s, int leftsize) {
        //判空
        if (leftsize <= 0 || leftsize >= s.length()) {
            return s;
        }
        char[] str = s.toCharArray();
        int L = 0;
        int R = str.length - 1;
        int lpart = leftsize; //左半部分 5 左邊未處理的字符數
        int rpart = s.length() - leftsize;//右半部分 3 右邊未處理的字符數
        int same = Math.min(lpart, rpart); //相同個數的部分 same = 3
        exchange(str, L, R, same);
        //在這個exchange 結束之後 整個字符串 變爲fghdeabc
        //此結果意味着前 same個字符已經處理好了 剩下就是遞歸處理後面
        //需要做的僅僅就是玩好 L R same 這三個變量而已
        while (lpart - rpart != 0) { //此條件表示還有未處理的字符
            if (lpart - rpart > 0) { //左邊長  fghdeabc
                L += same; //於是L左移same個,表示前same(3)個已經處理好了 L指向d
                lpart -= same;//也就是意味着 rpart 中已經有same個處理完了
            } else {
                //同理 右邊長 以abcdefgh 3 爲例
                //第一交換之後 結果爲 fghdeabc 右邊長表示 右邊3個已經交換完畢
                //此時只需要遞歸處理 前面 fghde 即可
                R -= same; //修改R的指向
                rpart -= same;//也就是意味着 rpart 中已經有same個處理完了
            }
            same = Math.min(lpart, rpart);
            exchange(str, L, R, same);
        }
        return String.valueOf(str);
    }

    //str 從左出發數 size個 和 從右出發 數size個 交換
    //以例二爲例:abcdefgh 5 -> fghabcde
    //size = 3  第一次交換完成之後結果爲 fghdeabc
    //也就是前三個和後三個順序交換
    public static void exchange(char[] str, int L, int R, int sameSize) {
        int i = R - sameSize + 1;// 7 - 3 + 1 = 5 (d的位置)
        char tmp = 0;
        while (sameSize-- != 0) { //size就是交換的次數
            tmp = str[L];
            str[L++] = str[i];
            str[i++] = tmp;
        }
    }
    public static void main(String[] args){
        //Test
        System.out.println(solution2("abcde", 3));
        System.out.println(solution2("abcdefgh", 5));
        System.out.println(solution2("abcdefgh", 3));
    }
}

 

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