java字符串算法题

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

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

你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。

输入:["h","e","l","l","o"]
输出:["o","l","l","e","h"]

思路解析:取开始和中间索引一起递增然后交换,另一种是头尾交换向中间靠拢

public void reverseString(char[] s) {
	int len=s.length;
	for(int i=0;i<len/2;i++){
		char temp=s[i];
		s[i]=s[len-1-i];
		s[len-1-i]=temp;
	}
}
//
 public void reverseString(char[] s) {
 	int p1 = -1, p2 = s.length;
 	while(++p1 < --p2){
 		char temp = s[p1];
 		s[p1] = s[p2];
 		s[p2] = temp;
 	}
 }

 

2.给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。

输入: 123
输出: 321

输入: -123
输出: -321

输入: 120
输出: 21

注意:
假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231,  231 − 1]。
请根据这个假设,如果反转后整数溢出那么就返回 0。

答题感受:一道字符串的题目,官解却没用字符串

思路解析:将整数转为字符串在翻转,转为整数时捕获异常,可能捕获异常不是让所有人满意的处理方式。当然还有一种就是每次弹出最后一位放在新数首位重新组合,只要利用最大数除以10判断就不会溢出了

public int reverse(int x) {
	boolean bol=false;
	if(x<0){
		x=-x;
		bol=true;
	}
	String str1=String.valueOf(x);
	String str2="";
	int len=str1.length();
	for(int i=len-1;i>=0;i--){
		str2+=str1.charAt(i);
	}
	try{
		x=Integer.parseInt(str2);
		if(bol){
			return -x;
		}         
	}catch(Exception e){
		return 0;
	}  
	return x;
}
//
public int reverse(int x) {
	int rev = 0;
	while (x != 0) {
		int pop = x % 10;
		x /= 10;
		if (rev > Integer.MAX_VALUE/10 || (rev == Integer.MAX_VALUE / 10 && pop > 7)) return 0;
		if (rev < Integer.MIN_VALUE/10 || (rev == Integer.MIN_VALUE / 10 && pop < -8)) return 0;
		rev = rev * 10 + pop;
	}
	return rev;
}

 

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

s = "leetcode"
返回 0.

s = "loveleetcode",
返回 2.

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

思路解析:构造数组,每个字母转换为整数对应自己的位置并存入+1,第二次遍历查找值为1的索引值。map实现效果相同

 public int firstUniqChar(String s) {
 	int[] times = new int[256];
 	for (char c : s.toCharArray()) {
 		times[c - 'a']++;
 	}
 	for (int i = 0; i < s.length(); i++) {
 		if (times[s.charAt(i) - 'a'] == 1) {
 			return i;
 		}
 	}
 	return -1;
 }

 

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

输入: s = "anagram", t = "nagaram"
输出: true

输入: s = "rat", t = "car"
输出: false

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

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

思路解析:与上题方法相同,进阶暂时没看

public boolean isAnagram(String s, String t) {
	int[] nums1=new int[26];
	int[] nums2=new int[26];
	for(char c:s.toCharArray()){
		nums1[c-'a']++;
	}
	for(char c:t.toCharArray()){
		nums2[c-'a']++;
	} 
	for(int i=0;i<26;i++){
		if(nums2[i]!=nums1[i]){
			return false;
		}
	}     
	return true;   
}   

 

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

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

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

输入: "race a car"
输出: false

思路解析:两种解法道理都一样,但正则好像慢了点

 public boolean isPalindrome(String s) {
 	String str=s.toLowerCase().replaceAll("[^0-9a-z]","");
 	for(int i=0;i<str.length();i++){
 		if(str.charAt(i)!=str.charAt(str.length()-1-i)){
 			return false;
 		}
 	}
 	return true;  
 }
//双指针
public boolean isPalindrome(String s) {
	if (s.length()==0||s.length()==1)return true;
	s = s.toLowerCase();
	int i =0,j=s.length()-1;
	while (i<j){
		while ((s.charAt(i) < '0' || s.charAt(i) > '9') && (s.charAt(i) < 'a' || s.charAt(i) > 'z') && i < j) i++;
		while ((s.charAt(j) < '0' || s.charAt(j) > '9') && (s.charAt(j) < 'a' || s.charAt(j) > 'z') && i < j) j--;
		if (s.charAt(i) != s.charAt(j)) return false;
		i++;j--;
	}
	return true;
}

 

6.请你来实现一个 atoi 函数,使其能将字符串转换成整数。

首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。

当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。

该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。

注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。

在任何情况下,若函数不能进行有效的转换时,请返回 0。

说明:

假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231,  231 − 1]。如果数值超过这个范围,qing返回  INT_MAX (231 − 1) 或 INT_MIN (−231) 

示例 1:

输入: "42"
输出: 42
示例 2:

输入: "   -42"
输出: -42
解释: 第一个非空白字符为 '-', 它是一个负号。
     我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。
示例 3:

输入: "4193 with words"
输出: 4193
解释: 转换截止于数字 '3' ,因为它的下一个字符不为数字。
示例 4:

输入: "words and 987"
输出: 0
解释: 第一个非空字符是 'w', 但它不是数字或正、负号。
     因此无法执行有效的转换。
示例 5:

输入: "-91283472332"
输出: -2147483648
解释: 数字 "-91283472332" 超过 32 位有符号整数范围。 
     因此返回 INT_MIN (−231) 。

思路解析:首先解决空字符,然后是正负号先取下来,接着看字符是否是数字然后拼接数字,不是数字是就退出

public int myAtoi(String str) {
        // ex:"5900万台智能手机发货量"
        String strs = str.trim();
        if(strs == null || "".equals(strs))   return 0;
        char Initials = strs.charAt(0);
        int res = 0;
        boolean isPos = Initials != '-' || Initials == '+' ;
        int i = 0;
        // 若首元素是符号则索引从1开始
        i = (Initials == '+' || Initials == '-') ? 1 : 0;
        // System.out.print(i);
        for (; i < strs.length(); i++)  {
            // 从外面已判断到首元素是否是标记,下面条件作为其后紧接着的元素的是否为数字,
            // 否,则直接跳出循环,直接返回结果0
            if(!Character.isDigit(strs.charAt(i))) break;
            else{
                int right = strs.charAt(i) - '0';
                // System.out.println((Integer.MAX_VALUE - right) / 10);
                if (res > (Integer.MAX_VALUE - right) / 10) { 
                    return isPos ? Integer.MAX_VALUE : Integer.MIN_VALUE;
                }
                res = res * 10 + right;   // 转换的核心思路
            }
        }      
       return isPos ? res : -res;
}

 

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

示例 1:

输入: haystack = "hello", needle = "ll"
输出: 2
示例 2:

输入: haystack = "aaaaa", needle = "bba"
输出: -1
说明:

当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。

对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。

思路解析:最简单的解法

public int strStr(String haystack, String needle) {
        if (needle.equals(""))
            return 0;
        else if (!haystack.contains(needle))
            return -1;
        else {
            return haystack.indexOf(needle);
        }
}

 

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

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

1 被读作  "one 1"  ("一个一") , 即 11。
11 被读作 "two 1s" ("两个一"), 即 21。
21 被读作 "one 2",  "one 1" ("一个二" ,  "一个一") , 即 1211。

给定一个正整数 n(1 ≤ n ≤ 30),输出报数序列的第 n 项。

注意:整数顺序将表示为一个字符串。

示例 1:

输入: 1
输出: "1"
示例 2:

输入: 4
输出: "1211"

思路解析:外层while循环为检索字符串,内层用while循环计数相同数字的个数,拼接的数字为计数的数字加被计数的数字

public String countAndSay(int n) {
        String str="1";
        for(int i=0;i<n-1;i++){
            int j=0;           
            String temp="";
            while(j<str.length()){
                int value=1;
                while(j+1<str.length()&&str.charAt(j)==str.charAt(j+1)){
                    value++;
                    j++;
                }               
                temp=temp+value+str.charAt(j);                    
                j++;
         }     
         str=temp;
    }      
    return str;
}

 

9.编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 ""

示例 1:

输入: ["flower","flow","flight"]
输出: "fl"
示例 2:

输入: ["dog","racecar","car"]
输出: ""
解释: 输入不存在公共前缀。
说明:

所有输入只包含小写字母 a-z 。

思路解析:第一种是从所有字符的后往前找,第二种是从前往后找

public String longestCommonPrefix(String[] strs) {
    if (strs == null || strs.length == 0) return "";
    for (int i = 0; i < strs[0].length() ; i++){
        char c = strs[0].charAt(i);
        for (int j = 1; j < strs.length; j ++) {
            if (i == strs[j].length() || strs[j].charAt(i) != c)
                return strs[0].substring(0, i);             
        }
    }
    return strs[0];
}
//
public String longestCommonPrefix(String[] strs) {
        if (strs == null || strs.length == 0) return "";
        for (int i = 0; i < strs[0].length() ; i++){
            char c = strs[0].charAt(i);
            for (int j = 1; j < strs.length; j ++) {
                if (i == strs[j].length() || strs[j].charAt(i) != c)
                    return strs[0].substring(0, i);             
            }
        }
        return strs[0];
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章