力扣算法:344.反转字符串 541.反转字符串|| 05.替换空格 58.左旋转字符串 151.反转字符串中的单词

学习内容

力扣算法:

344.反转字符串

541.反转字符串||

05.替换空格

58.左旋转字符串

151.反转字符串中的单词

具体内容

344.反转字符串

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

示例 1:

输入:s = [“h”,“e”,“l”,“l”,“o”] 输出:[“o”,“l”,“l”,“e”,“h”]

示例 2:

输入:s = [“H”,“a”,“n”,“n”,“a”,“h”] 输出:[“h”,“a”,“n”,“n”,“a”,“H”]

提示:

1 <= s.length <= 105
s[i] 都是 ASCII 码表中的可打印字符

题目地址

做题思路

类似前面学过的反转链表一样,用双指针

解题

class Solution {
    public void reverseString(char[] s) {
    	int i=0;
    	int j=s.length-1;
    	while(i < j){
    		char temp = s[i];
    		s[i] = s[j];
    		s[j] = temp;
    		i++;
    		j--;
    	}
    }
}

541.反转字符串||

给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。

如果剩余字符少于 k 个,则将剩余字符全部反转。
如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。

示例 1:

输入:s = “abcdefg”, k = 2 输出:“bacdfeg”

示例 2:

输入:s = “abcd”, k = 2 输出:“bacd”

提示:

1 <= s.length <= 104
s 仅由小写英文组成
1 <= k <= 104

题目地址

做题思路

由于要翻转的是每2 * k 区间的起点到k的距离,因此在for循环里面,直接让i移动2*k,再依次遍历,要是剩余的字段小于k,则进行翻转

解题

class Solution {
    public String reverseStr(String s, int k) {
    	char[] a = s.toCharArray();
    	//题目是以 2k 个字符计数,因此i每次相加间隔为2k
    	for(int i = 0;i < a.length-1;i+=2*k){
    		//若是剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符
    		if(i + k <= a.length){
    			reverseString(a,i,i+k-1);
    			//z
    		}else{
    			reverseString(a,i,s.length()-1);
    		}
    	}
    	return new String(a);
    }
    public void reverseString(char[] a,int left,int right){
     	//第一种
    	// while(left < right){
    	// 	char temp = a[left];
    	// 	a[left] = a[right];
    	// 	a[right] = temp;
    	// }
    	//第二种:所用的时间更少
    	for(;left<right;left++,right--){
    		char temp = a[left];
    		a[left] = a[right];
    		a[right] = temp;
    	}
    }
}

解答代码存在的疑问

1、当i + k <= ch.length,为什么翻转是i到i+k-1?
因为k是不断往后移动,且移动的距离是k,减掉1则是我们要反转的位置是前一位数
2、为什么要使用第二种反转?
所用时间更少,效率更好

05.替换空格

请实现一个函数,把字符串 s 中的每个空格替换成"%20"。

示例 1:

输入:s = “We are happy.” 输出:“We%20are%20happy.”

限制:
0 <= s 的长度 <= 10000

题目地址

做题思路

可扩充字符串的长度,将空格填充为所需要的内容。要注意题目是将一个空格变成3个新的字符,也就是每个空格对应扩充2个字符

解题

class Solution {
    public String replaceSpace(String s) {
    	//判断代码是否为空,一定要养成好的习惯
    	if(s == null || s.length() == 0){
    		return s;
    	}
    	//先判断字符串出现空格的地方进行扩充,且必须先创建一个StringBuilder对象进行扩充,不能直接在原字符串进行扩充
    	StringBuilder str = new StringBuilder();
    	for(int i = 0;i < s.length();i++){
    		if(s.charAt(i) == ' '){
    		  //注意是填充2个字符
    			str.append("  ");
    		}
    	}
    	//判断str是否为空 若为空则证明原字符串本身没有空格 直接返回原字符串即可
    	if(str == null || str.length() == 0){
    		return s;
    	}
    	//在原来的字符串用left变量赋值最后一个元素,方便后续使用
    	int left = s.length()-1;
    	//对原字符串进行扩充
    	s += str.toString();
    	//在最新的字符串用right变量赋值最后一个元素,方便后续使用
    	int right = s.length()-1;
    	char[] news = s.toCharArray();
    	//依次赋值
    	while(left <= 0){
    		if(news[left] == ' '){
    			news[right--] = '0';
    			news[right--] = '2';
    			news[right] = '%';
    		}else{
    			news[right] = news[left];
    		}
    		//注意要改变left和right的值
    		left--;
         	right--;
    	}
    	return new String(news);
    }
 }

58.左旋转字符串

字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。

示例 1:

输入: s = “abcdefg”, k = 2 输出: “cdefgab”

示例 2:

输入: s = “lrloseumgh”, k = 6 输出: “umghlrlose”

限制:

1 <= k < s.length <= 10000

题目地址

做题思路

将前n位数的元素进行反转,再反转后n位数,之前再总体反转

解题

class Solution {
    public String reverseLeftWords(String s, int n) {
        char[] k = s.toCharArray();
        reverse(k,0,n-1);
        reverse(k,n,k.length-1);
        reverse(k,0,k.length-1);
        return new String(k);
    }
    public void reverse(char[] a,int left,int right){
        for(;left < right;left++,right--){
            char k = a[left];
            a[left] = a[right];
            a[right] = k;
        }
    }
} 

151.反转字符串中的单词

给你一个字符串 s ,请你反转字符串中 单词 的顺序。

单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。

返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。

注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。

示例 1:

输入:s = “the sky is blue” 输出:“blue is sky the”

示例 2:

输入:s = " hello world " 输出:“world hello” 解释:反转后的字符串中不能存在前导空格和尾随空格

示例 3:

输入:s = “a good example” 输出:“example good a”
解释:如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。

提示:

1 <= s.length <= 104
s 包含英文大小写字母、数字和空格 ' '
s 中 至少存在一个 单词

题目地址

做题思路

先把首尾多余空格去掉,翻转整体,通过判断中间的空格位置再把每个单词一一翻过来,且要注意中间也会有多余的空格

解题

	class Solution {
   /**
     * 不使用Java内置方法实现
     * 

* 1.去除首尾以及中间多余空格 * 2.反转整个字符串 * 3.反转各个单词 */ public String reverseWords(String s) { // System.out.println("ReverseWords.reverseWords2() called with: s = [" + s + "]"); // 1.去除首尾以及中间多余空格 StringBuilder sb = removeSpace(s); // 2.反转整个字符串 reverseString(sb, 0, sb.length() - 1); // 3.反转各个单词 reverseEachWord(sb); return sb.toString(); } private StringBuilder removeSpace(String s) { // System.out.println("ReverseWords.removeSpace() called with: s = [" + s + "]"); int start = 0; int end = s.length() - 1; while (s.charAt(start) == ' ') start++; while (s.charAt(end) == ' ') end--; StringBuilder sb = new StringBuilder(); while (start <= end) { char c = s.charAt(start); if (c != ' ' || sb.charAt(sb.length() - 1) != ' ') { sb.append(c); } start++; } // System.out.println("ReverseWords.removeSpace returned: sb = [" + sb + "]"); return sb; } /** * 反转字符串指定区间[start, end]的字符 */ public void reverseString(StringBuilder sb, int start, int end) { // System.out.println("ReverseWords.reverseString() called with: sb = [" + sb + "], start = [" + start + "], end = [" + end + "]"); while (start < end) { char temp = sb.charAt(start); sb.setCharAt(start, sb.charAt(end)); sb.setCharAt(end, temp); start++; end--; } // System.out.println("ReverseWords.reverseString returned: sb = [" + sb + "]"); } private void reverseEachWord(StringBuilder sb) { int start = 0; int end = 1; int n = sb.length(); while (start < n) { while (end < n && sb.charAt(end) != ' ') { end++; } reverseString(sb, start, end - 1); start = end + 1; end = start + 1; } } }

复习

344.反转字符串

class Solution {
    public void reverseString(char[] s) {
    	int i = 0;
    	int j = s.length - 1;
    	while(i < j){
    		char temp = s[i];
    		s[i] = s[j];
    		s[j] = temp;
    		i++;
    		j--;
    	}
    }
}

541.反转字符串||

第一次写,逻辑有问题

class Solution {
    public String reverseStr(String s, int k) {
        char[] a = s.toCharArray();
        for(int i = 0; i < s.length(); i+=2*k){
            //这里的逻辑有误
            if(i + k <= s.length()){
                reverse(a,i,k+i);
            }else{
                reverse(a,k,s.length()-1);
            }
        }
        return new String(a);
    }
    //写出翻转的函数
    public void reverse(char[] a,int left,int right){
        while(left < right){
            char temp = a[left];
            a[left] = a[right];
            a[right] = temp;
            left++;
            right--;
        }
    } 
}

矫正

class Solution {
    public String reverseStr(String s, int k) {
        char[] ch = s.toCharArray();
        // 1. 每隔 2k 个字符的前 k 个字符进行反转
        for (int i = 0; i< ch.length; i += 2 * k) {
            // 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符
            if (i + k <= ch.length) {
                reverse(ch, i, i + k -1);
                continue;
            }
            // 3. 剩余字符少于 k 个,则将剩余字符全部反转
            reverse(ch, i, ch.length - 1);
        }
        return  new String(ch);

    }
    // 定义翻转函数
    public void reverse(char[] ch, int i, int j) {
    	for (; i < j; i++, j--) {
        	char temp  = ch[i];
        	ch[i] = ch[j];
        	ch[j] = temp;
    	}
    }
}

05.替换空格

中层逻辑不清楚,且没有判空

class Solution {
    public String replaceSpace(String s) {
        //没有空处理!
    	StringBuilder str = new StringBuilder();
        for(int i = 0; i < s.length();i++){
            if(s.charAt(i) == ' '){
                str.append("  ");
            }
        }
        int left = s.length()-1;
        //处理不对
        s.append(str);
        int right = s.length()-1;
        //这里开始混乱
        while(left < right){
            String k = s.charAt(left);
            if(k == ' '){

            }
        }
    }
}

矫正

class Solution {
    public String replaceSpace(String s) {
    	//没有空处理 -------空处理
    	if(s == null || s.length() == 0){
    		return s;
    	}
    	StringBuilder str = new StringBuilder();
    	for(int i = 0;i < s.length();i++){
    		if(s.charAt(i) == ' '){
    		  //注意是填充2个字符
    			str.append("  ");
    		}
    	}
    	//没有空处理 -------空处理
    	if(str == null || str.length() == 0){
    		return s;
    	}
    	int left = s.length()-1;
    	//处理不对s.append(str); ------- 正确处理
    	s += str.toString();
    	int right = s.length()-1;
    	char[] news = s.toCharArray();
    	//依次赋值
    	while(left <= 0){
    		if(news[left] == ' '){
    			news[right--] = '0';
    			news[right--] = '2';
    			news[right] = '%';
    		}else{
    			news[right] = news[left];
    		}
    		//注意要改变left和right的值
    		left--;
         right--;
    	}
    	return new String(news);
    }
 }

58.左旋转字符串

完全没印象

class Solution {
    public String reverseLeftWords(String s, int n) {
        int len=s.length();
        char[] a = s.toCharArray();
        reverseString(a,0,n-1);
        reverseString(a,n,len-1);
         reverseString(a,0,len-1);
        return new String(a);
    }
     public void reverseString(char[] sb, int start, int end) {
        while (start < end) {
            char temp = sb[start];
            sb[start] = sb[end];
            sb[end] = temp;
            start++;
            end--;
            }
        }
}
   

151.反转字符串中的单词

报错,看似正确,但没有移除掉空格,也没有判空

class Solution {
    public String reverseWords(String s) {
        char k[] = s.toCharArray();
        int l = 0;
        int r = k.length - 1;
        while(l < r){
            reverse(k,l,r);
        }
        int i = 0;
        int j = 0;
        while(j <= k.length - 1){
            if(k[j] == ' '){
                reverse(k,i,i+j-1);
                i = j+1;
            }
            j++;
        }
        return new String(k);

    }
    public void reverse(char[] a,int left,int right){
        while(left < right){
            char temp = a[left];
            a[left] = a[right];
            a[right] = temp;
            left++;
            right--;
        }
    }
}

矫正

public String reverseWords(String s) {
        // System.out.println("ReverseWords.reverseWords2() called with: s = [" + s + "]");
        // 1.去除首尾以及中间多余空格
        StringBuilder sb = removeSpace(s);
        // 2.反转整个字符串
        reverseString(sb, 0, sb.length() - 1);
        // 3.反转各个单词
        reverseEachWord(sb);
        return sb.toString();
    }

    private StringBuilder removeSpace(String s) {
        // System.out.println("ReverseWords.removeSpace() called with: s = [" + s + "]");
        int start = 0;
        int end = s.length() - 1;
        //去掉首位空格
        while (s.charAt(start) == ' ') start++;
        while (s.charAt(end) == ' ') end--;
        StringBuilder sb = new StringBuilder();
        while (start <= end) {
            char c = s.charAt(start);
            if (c != ' ' || sb.charAt(sb.length() - 1) != ' ') {
                sb.append(c);
            }
            start++;
        }
        // System.out.println("ReverseWords.removeSpace returned: sb = [" + sb + "]");
        return sb;
    }

    /**
     * 反转字符串指定区间[start, end]的字符
     */
    public void reverseString(StringBuilder sb, int start, int end) {
        // System.out.println("ReverseWords.reverseString() called with: sb = [" + sb + "], start = [" + start + "], end = [" + end + "]");
        while (start < end) {
            char temp = sb.charAt(start);
            sb.setCharAt(start, sb.charAt(end));
            sb.setCharAt(end, temp);
            start++;
            end--;
        }
        // System.out.println("ReverseWords.reverseString returned: sb = [" + sb + "]");
    }

    private void reverseEachWord(StringBuilder sb) {
        int start = 0;
        int end = 1;
        int n = sb.length();
        while (start < n) {
        		//sb.charAt(end) != ' '判断前面是否有空格
            while (end < n && sb.charAt(end) != ' ') {
                end++;
            }
            reverseString(sb, start, end - 1);
            start = end + 1;
            end = start + 1;
        }
    }
}

你可能感兴趣的:(算法,leetcode,java)