LeetCode算法(二)字符串

字符串

目录

字符串反转

请编写一个函数,其功能是将输入的字符串反转过来。
示例

输入:s = “hello”

返回:”olleh”

解决思路:

  1. 逆序遍历字符串

具体思路:创建一个新的空字符串,将s的字符逆序放在空字符串中

问题:超出时间限制

String result = "";
for(int i=s.length()-1;i>=0;i--){
    result += s.charAt(i);
}
System.out.print(result);
return result;
  1. 通过数组来实现

具体思路:通过字符串转换为char数组,通过for循环来给char数组赋值

ps:一次可以给两个元素赋值

if(s==null || s.length()==0) return s;
char[] array = s.toCharArray();
for(int i=0;i<s.length()/2;i++){
    array[i] = s.charAt(s.length()-i-1);
    array[s.length()-i-1] = s.charAt(i);
}
return new String(array);
  1. 使用栈来实现

具体思路:将字符串压栈之后,再弹出来的就是一个逆序的字符串

        if(s==null || s.length()==0) return s;
        Stack<Character> stack = new Stack<>();
        char[] array = s.toCharArray();
        for(Character c : array){
            stack.push(c);
        }
        int length = s.length();
        for(int i=0;i<length;i++){
            array[i] = stack.pop();
        }
        return new String(array);
  1. 使用递归

具体思路:找到递归临界条件,对临界条件不同的值做不同的处理

if(s==null || s.length()==0) return s;
int length = s.length();
if(length==1) {
    return s;
}else{
    return reverseString(s.substring(1)) + s.charAt(0);
}

颠倒整数

给定一个 32 位有符号整数,将整数中的数字进行反转。

示例 1:

输入: 123
输出: 321

示例 2:

输入: -123
输出: -321

示例 3:

输入: 120
输出: 21

注意:

假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−2^31, 2^31 − 1]。根据这个假设,如果反转后的整数溢出,则返回 0。

解决思路

x%10 取出最低位

x/10 去除最低位

public int reverse(int x){
        int int_max= 0x7fffffff;
        int int_min= 0x80000000;
        long  anwser = 0;
        int result = 0;
        while(x!=0){
            anwser = anwser*10+(x%10);
            x/=10;
        }
        if(anwser < int_min || anwser>int_max){
            anwser = 0;
        }else{
            result = (int)anwser;
        }
        return result;
    }

字符串中的第一个唯一字符

给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。

案例:

s = “leetcode”
返回 0.

s = “loveleetcode”,
返回 2.

注意事项:您可以假定该字符串只包含小写字母。

解题思路

通过一个map集合将字符串放在其中,遍历map,每次判断是否存在的时候,将当前元素从map中删除,结束后再将当前元素放入map中.

public int firstUniqChar(String s) {
         Map<Integer,Character> map = new HashMap<Integer,Character>();
        for(int i=0;i<s.length();i++){
            map.put(i,s.charAt(i));
        }
        for(int i=0;i<s.length();i++){
            //只需要将当前key与之后的字符串比较即可
            Character c = map.get(i);
            map.remove(i);
            if(!map.containsValue(c)){
                return i;
            }
            map.put(i,c);
        }
        return -1;
    }

有效的字母异位词

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的一个字母异位词。

示例 1:

输入: s = “anagram”, t = “nagaram”
输出: true

示例 2:

输入: s = “rat”, t = “car”
输出: false

说明:
你可以假设字符串只包含小写字母。

进阶:
如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?

解决思路

大体思路,都是记录字符串中各个字符出现的次数。然后比较两个字符串的内容情况.

  1. 使用hashmap
public boolean isAnagram(String s,String t){
        Map<Character,Integer> map1 = new HashMap<>();
        Map<Character,Integer> map2 = new HashMap<>();
        int sLength = s.length();
        int tLength = t.length();
        if(sLength!=tLength){
            return false;
        }
        for(int i=0;i<sLength;i++){
            Integer sValue = map1.get(s.charAt(i));
            Integer tValue = map2.get(t.charAt(i));
            map1.put(s.charAt(i),(sValue==null ? 0 : sValue)+1);
            map2.put(t.charAt(i),(tValue==null ? 0 : tValue)+1);
        }

        /*
            直接使用==操作符,比较的是两个字符串的引用地址,并不是比较内容
         */
        for(Character c : map1.keySet()){
            if(!map2.containsKey(c) || !map1.get(c).equals(map2.get(c))){
                return false;
            }
        }
        return true;
    }
  1. 使用数组,两个int型数组,sArray和tArray,来储存s和t字符串中的字符情况,a对应数组下标0,b对应数组下标1……
public boolean isAnagram(String s, String t) {  
        if (s.length() != t.length())  
            return false;  

        int[] sArray = new int[26];  
        int[] tArray = new int[26];  

        for (int i = 0; i < s.length(); i++) {  
            sArray[s.charAt(i)-97] ++;  
            tArray[t.charAt(i)-97] ++;  
        }  

        for (int i = 0; i < 26; i++)   
            if (sArray[i]!=tArray[i])  
                return false;  

        return true;  
    }  
  1. 更加简化的版本,使用一个数组,将第一个数组的各个字符出现次数++,在另一个字符中–,最后判断数组中各个字符的个数是否为0,若不为0,则返回false
public boolean isAnagram(String s, String t) {
    int[] alphabet = new int[26];
    for (int i = 0; i < s.length(); i++) alphabet[s.charAt(i) - 'a']++;
    for (int i = 0; i < t.length(); i++) alphabet[t.charAt(i) - 'a']--;
    for (int i : alphabet) if (i != 0) return false;
    return true;
}

判断回文串

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。

说明:本题中,我们将空字符串定义为有效的回文串。

示例 1:

输入: “A man, a plan, a canal: Panama”
输出: true

示例 2:

输入: “race a car”
输出: false

解决思路

我自己想的是,首先将多余字符去掉,然后在这个纯粹的字符串中比较,没想到提交之后时间超时了。这是我自己的代码

public boolean isPalindrome(String s) {
        if(s == null){
            return false;
        }
        if(s.equals("") || s.length()==1){
            return true;
        }
        //首先将字符串变小写
        String LowS = s.toLowerCase();
        String temp = "";
        String reserveTemp = "";
        for(int i=0;i<LowS.length();i++){
            //若不是字母或数字,则跳过这个字符
            while(!isNeed(LowS.charAt(i))){
                if(i==LowS.length()-1){
                    break;
                }
                i++;
            }
            if(i == LowS.length()-1 && !isNeed(LowS.charAt(i))){
                break;
            }

            temp += LowS.charAt(i);
        }
        for(int i=0;i<temp.length()/2;i++){
            //reserveTemp += temp.charAt(temp.length()-i-1);
            if(temp.charAt(i) != temp.charAt(temp.length()-i-1)){
                return false;
            }
        }
        return true;
        if(reserveTemp.equals(temp)){
            return true;
        }else{
            return false;
        }
    }

上网看了别人的解答才知道自己的思路是对的,但做了太多不必要做的工作了。设置两个指针即可完成判断

public boolean isPalindrome(String s) {
        int left =0,right = s.length()-1;
     while(left<right){
         if(!isNeed(s.charAt(left))) left++;
         else if(!isNeed(s.charAt(right))) right--;
         else if((s.charAt(left)+32 - 'a')%32 != (s.charAt(right)+32 - 'a')%32) return false;
         else{
             left++;right--;
         }
     }
     return true;
    }

    public boolean isNeed(Character c){
        if((c >= 'a' && c<= 'z') ||(c>='0' && c<='9')
                || (c>='A' && c<='Z')){
            return true;
        }
        return false;
    }  

s.charAt(left)+32 - ‘a’)%32 != (s.charAt(right)+32 - ‘a’)%32 可忽略字符大小写判断的方法

将字符串转换为整数

题目大意
  实现一个atoi函数,将字符串转成整形
  要点:考虑所有的输入情况。

解题思路

前导字符是+或-或者没有,接下来输入的是数字,数字不能整数能表示的最大或最小数。如果超过就返回对应的最小或者最小的值。

public int myAtoi(String str){
        //判断是否为空格,若是空格指针加1
        int start=0;
        int length = str.length();
        //如果为空或者长度为0
        //设置一个标志位,判断是正负
        boolean positive = true;
        if(str==null||length==0){
            return 0;
        }
        if(str.charAt(start) == ' '){
            while(str.charAt(start)==' '){
                start++;
                if(start>=length){
                    //全部都是空格
                    return 0;
                }
            }
        }


        //判断第一个字符是什么,若是正号
        if(str.charAt(start) == '+'){
            start++;
        }else if(str.charAt(start)=='-'){
            positive = false;
            start++;
        }else if(str.charAt(start) >= '0' && str.charAt(start) <='9'){
            //strToNum字符串转数字
            return strToNum(positive,start,str);
        }else{
            return 0;
        }
        //只有一个正号或负号
        if(start>=length){
            return 0;
        }
        //若后面跟的不是数字
        if(str.charAt(start) < '0'||str.charAt(start) > '9'){
            return 0;
        }else{
            return  strToNum(positive,start,str);
        }
    }

    /**
     * 将已拿到的字符串转为数字 char-'0'就是其数字
     * @param positive
     * @param start
     * @param str
     * @return
     */
    public int strToNum(boolean positive,int start,String str){
        long result = 0;
        while(start<str.length()&&str.charAt(start)>='0'&&str.charAt(start)<='9'){
            result = result*10+(str.charAt(start)-'0');
            if(positive){
                if(result>Integer.MAX_VALUE){
                    return Integer.MAX_VALUE;
                }
            }else{
                if(-result<Integer.MIN_VALUE){
                    return Integer.MIN_VALUE;
                }
            }
            start++;
        }
        if(positive){
            return (int)result;
        }else{
            return -(int)result;
        }
    }

实现strStr()

给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。

解决思路

设计两个指针,遍历haystack中所有和needle相同长度的字符串,进行比较

public int strStr(String haystack,String needle){
        //异常处理:haystack的长度小于needle长度
        if(haystack.length()<needle.length()){
            return -1;
        }
        //判断needle是否为空
        if(needle==null || needle.length()==0){
            return 0;
        }

        //两个字符串长度相等的情况
        if(needle.length() == haystack.length()){
            //直接判断两个字符是否相等
            if(haystack.equals(needle)){
                return 0;
            }else{
                return -1;
            }
        }
        //haystack长度大于needle的长度的时候
        //得到两边的长度
        int hLength = 0;
        int nLength = needle.length();
        String temp = "";
        //遍历haystack,找出所有和needle长度相同的字符串,比较。若相同则返回hLength
        while(hLength<haystack.length()-nLength+1){
            temp = "";
            for(int i=hLength;i<hLength+nLength;i++){
                temp += haystack.charAt(i);
            }
            if(temp.equals(needle)){
                return hLength;
            }
            hLength++;
        }
        return -1;
    }

数数并说

报数序列是指一个整数序列,按照其中的整数的顺序进行报数,得到下一个数。其前五项如下:

  1. 1
  2. 11
  3. 21
  4. 1211
  5. 111221

解决思路

找到前一项中的连续相同的元素个数

public String countAndSay(int n){
        /*
        初步思路:计算其前一项,连续相同的元素个数,将得到的结果放在新的字符串中
         */
        String result = "1";
        if(n<=0){
            return "";
        }
        //遍历n,先自减1
        n = n-1;
        while(n>0){
            String cur = "";
            for(int i=0;i<result.length();i++){
                //计数器,记录出现的次数
                int cflag = 1;
                while(i+1<result.length() && result.charAt(i) == result.charAt(i+1)){
                    cflag++;
                    i++;
                }
                cur += String.valueOf(cflag) + String.valueOf(result.charAt(i));
            }
            result = cur;
            n--;
        }
        return result;
        }

最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串 “”。

public String longestCommonPrefix(String[] strs){
        //若字符串数组为空
        if(strs==null || strs.length==0){
            return "";
        }
        //若只有一个元素
        if(strs.length==1){
            return strs[0];
        }
        //两个以上元素
        int pc = 0;
        String result = "";
        //找出字符串数组中最小的数组长度
        int LowLength = strs[0].length();
        for(int i=1;i<strs.length;i++){
            if(LowLength>strs[i].length()){
                LowLength = strs[i].length();
            }
        }
        if(LowLength==0){
            return "";
        }
        //若字符串数组中的字符串的第一个字符都相同,则将其加入结果字符串
        while(pc<LowLength){
            for (int i=0;i<strs.length-1;i++){
                //得到元素
                if(strs[i].charAt(pc) != strs[i+1].charAt(pc)){
                    return result;
                }
            }
            result += strs[0].charAt(pc);
            pc++;
        }
        return result;
    }

猜你喜欢

转载自blog.csdn.net/qq_34211771/article/details/80556891