其他分享
首页 > 其他分享> > 翻转字符串 & 找到指定的新类型字符

翻转字符串 & 找到指定的新类型字符

作者:互联网

翻转字符串

题目:翻转字符串(1) & 翻转字符串(2)

《程序员代码面试指南》第84题 P267 难度:士★☆☆☆

太菜了,想半天想不出来额外空间复杂度O(1)的方法。

原问题先把chas整体逆序,然后再遍历chas找到每一个单词把每个单词里的字符逆序即可。

public void rotateWord(char[] chas) {
    if (chas == null || chas.length == 0) {
        return;
    }
    reverse(chas, 0, chas.length - 1);
    int l = -1;
    int r = -1;
    for (int i = 0; i < chas.length; i++) {
        if (chas[i] != ' ') {
            l = i == 0 || chas[i - 1] == ' ' ? i : l;
            r = i == chas.length - 1 || chas[i + 1] == ' ' ? i : r;
        }
        if (l != -1 && r != -1) {
            reverse(chas, l, r);
            l = -1;
            r = -1;
        }
    }
}

public void reverse(char[] chas, int start, int end) {
    char tmp = 0;
    while (start < end) {
        tmp = chas[start];
        chas[start] = chas[end];
        chas[end] = tmp;
        start++;
        end--;
    }
}

补充问题方法一先把chas[0..size-1]部分逆序处理再把chas[size..N-1]部分逆序处理最后把chas整体逆序处理即可。

public void rotate1(char[] chas, int size) {
    if (chas == null || size <= 0 || size >= chas.length) {
        return;
    }
    reverse(chas, 0, size - 1);
    reverse(chas, size, chas.length - 1);
    reverse(chas, 0, chas.length - 1);
}

方法二。是我想了一会想出来的方法。核心思想就是对比未交换的左右部分的长度,来进行交换,并且划分下一步要交换的左右部分直到左右部分长度一样交换完即完成全部过程。具体举例见书P269,这里不再赘述。

public void rotate2(char[] chas, int size) {
    if (chas == null || size <= 0 || size >= chas.length) {
        return;
    }
    int start = 0;
    int end = chas.length - 1;
    int lpart = size;
    int rpart = chas.length - size;
    int s = Math.min(lpart, rpart);
    int d = lpart - rpart;
    while (true) {
        exchange(chas, start, end, s);
        if (d == 0) {
            break;
        } else if (d > 0) {
            start += s;
            lpart = d;
        } else {
            end -= s;
            rpart = -d;
        }
        s = Math.min(lpart, rpart);
        d = lpart - rpart;
    }
}

public void exchange(char[] chas, int start, int end, int size) {
    int i = end - size + 1;
    char tmp = 0;
    while (size-- != 0) {
        tmp = chas[start];
        chas[start] = chas[i];
        chas[i] = tmp;
        start++;
        i++;
    }
}

如果每一次左右部分的划分进行M次交换,那么都有M个字符再也不需要移动。而字符数一共为N,所以交换行为最多发生N次。另外,如果某一次划分出的左右部分长度一样,那么交换完成后将不会再有新的划分,因此很多时候交换操作会少于N次。总体上达到了时间复杂度O(N)的要求。

找到指定的新类型字符

题目:找到指定类型的新类型字符

《程序员代码面试指南》第95题 P302 难度:士★☆☆☆

本题比较简单。一个笨方法从str[0]开始从左到右依次划分出新类型字符到k位置就知道指向的新类型字符是什么了。

更快的方法从k-1位置开始向左统计连续出现的大写字母的数量记为uNum遇到小写字母就停止。如果uNum为奇数str[k-1..k]是被指定的新类型字符。如果uNum为偶数str[k]为大写字母时为str[k..k+1]str[k]为小写字母时则就是str[k]

public String pointNewchar(String s, int k) {
    if (s == null || s.equals("") || k < 0 || k >= s.length()) {
        return "";
    }
    char[] chas = s.toCharArray();
    int uNum = 0;
    for (int i = k - 1; i >= 0; i--) {
        if (!isUpper(chas[i])) {
            break;
        }
        uNum++;
    }
    if ((uNum & 1) == 1) {
        return s.substring(k - 1, k + 1);
    }
    if (isUpper(chas[k])) {
        return s.substring(k, k + 2);
    }
    return String.valueOf(chas[k]);
}

public boolean isUpper(char ch) {
    return !(ch < 'A' || ch > 'Z');
}

代码写的太优秀了,这个&1用的很妙,还有isUpper方法,学习学习。

标签:字符,end,start,int,chas,length,字符串,翻转,size
来源: https://www.cnblogs.com/CWZhou/p/16198447.html