LeetCode算法汇总-3

字符串简介

  1. 字符串的基本操作对象通常是字符串整体或者其子串 I LIKE LEETCODE 反向输出后,更希望是LEETCODE LIKE I 这时候操作对象就是这些子串

  2. 字符串操作比其他数据类型更复杂

    1. 比较函数

      Java的字符串比较有三者方法 compareTo:比较的是数据的大小;equals:比较的是内容是否相等;==:比较的是是否来自统一引用

      package 数组和字符串;
      
      /**
       * @author sandu
       * @create 2020-08-11 14:14
       */
      public class 字符串简介 {
      
      	// "static void main" must be defined in a public class.
      		public static void main(String[] args) {
      			// initialize
      			String s1 = "Hello World";
      			System.out.println("s1 is \"" + s1 + "\"");
      			String s2 = s1;
      			System.out.println("s2 is another reference to s1.");
      			String s3 = new String(s1);
      			System.out.println("s3 is a copy of s1.");
      			// compare using '=='
      			System.out.println("Compared by '==':");
      			// true since string is immutable and s1 is binded to "Hello World"
      			System.out.println("s1 and \"Hello World\": " + (s1 == "Hello World"));
      			// true since s1 and s2 is the reference of the same object
      			System.out.println("s1 and s2: " + (s1 == s2));
      			// false since s3 is refered to another new object
      			System.out.println("s1 and s3: " + (s1 == s3));
      			// compare using 'equals'
      			System.out.println("Compared by 'equals':");
      			System.out.println("s1 and \"Hello World\": " + s1.equals("Hello World"));
      			System.out.println("s1 and s2: " + s1.equals(s2));
      			System.out.println("s1 and s3: " + s1.equals(s3));
      			// compare using 'compareTo'
      			System.out.println("Compared by 'compareTo':");
      			System.out.println("s1 and \"Hello World\": " + (s1.compareTo("Hello World") == 0));
      			System.out.println("s1 and s2: " + (s1.compareTo(s2) == 0));
      			System.out.println("s1 and s3: " + (s1.compareTo(s3) == 0));
      
      			System.out.println(s1.hashCode());
      			System.out.println(s2.hashCode());
      			System.out.println(s3.hashCode());
      		}
      }
      
      
    2. 连接操作。在Java中,字符串是不可变的,如果想修改其中的字符,需要创建一个新的字符串。在连接时首先为新字符串分配足够的空间,复制就字符串中的内容并附加到新字符串。因此,总时间复杂度为O(N²)。

    3. 如果你确实希望你的字符串是可变的,则可以使用 toCharArray 将其转换为字符数组。

    4. 如果你经常必须连接字符串,最好使用一些其他的数据结构,如 StringBuilder

最长公共前缀

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

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

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

所有输入只包含小写字母 a-z 。
方法
横向扫描

横向扫描所有的字符串,以第一个为公共前缀,层层对比并且递减,遇到空则直接退出。

递归真香,真好用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vmlg1fxE-1597137556227)(算法.assets/14_fig1-1597130093656.png)]

class Solution14{
	public String longestCommonPrefix(String[] strs){

		if (strs.length == 0 || strs == null){
			return "";
		}

		int strsLength = strs.length;
		String firstStr = strs[0];
		for (int i = 1; i < strsLength; i++) {
			firstStr = longestCommonPrefix(firstStr,strs[i]);
			if (firstStr.equals("")){
				break;
			}
		}
		return firstStr;
	}

	public String longestCommonPrefix(String str1,String str2){
		int minLength = Math.min(str1.length(),str2.length());
		int numberCount = 0;
		while (numberCount < minLength && str1.charAt(numberCount) == str2.charAt(numberCount)){
			numberCount++;
		}
		return str1.substring(0,numberCount);
	}
}

时间复杂度:O(mn)O(mn),其中 mm 是字符串数组中的字符串的平均长度,nn 是字符串的数量。最坏情况下,字符串数组中的每个字符串的每个字符都会被比较一次。

空间复杂度:O(1)O(1)。使用的额外空间复杂度为常数。

纵向扫描

横向扫描是以整个字符串作比较。纵向是将几个字符串纵向排列,从第一列开始比较,如果相同则进行第二列比较,有不同,就取当前位置为最大公共前缀的索引。

class Solution140001{
	public String longestCommonPrefix(String[] strs){
		if (strs.length == 0 || strs == null){
			return "";
		}

		int strsLength = strs.length;
		int firstLength = strs[0].length();

		for (int i = 0; i < firstLength; i++) {
			char firstChar = strs[0].charAt(i);
			for (int j = 1; j < strsLength; j++) {
				if (i == strs[j].length() || firstChar != strs[j].charAt(i)){// 或 前面的判断是当前串比后串数量大的时候,做比较
					return strs[0].substring(0,i);
				}
			}
		}
		return strs[0];
	}
}

时间复杂度:O(mn)O(mn),其中 mm 是字符串数组中的字符串的平均长度,nn 是字符串的数量。最坏情况下,字符串数组中的每个字符串的每个字符都会被比较一次。

空间复杂度:O(1)O(1)。使用的额外空间复杂度为常数。

二分法

首先选择数组里最小的一个,他可能是公共前缀的最大长度。然后以这个数来进行二分法,当公共值等于mid的时候,有可能相等或者大于;当小于的时候,就mid-1继续判断

class Solution140002{
	public String longestCommonPrefix(String[] strs){
		if (strs.length == 0 || strs == null){
			return "";
		}

		int minLength = Integer.MAX_VALUE;
		for (String str : strs) {
			minLength = Math.min(minLength , str.length());
		}

		int low = 0,high = minLength;
		while (low < high){
			int mid = low + (high - low + 1) / 2;// 防溢出
			if (isCommonPrefix(strs,mid)){
				low = mid;//注意是while循环 如果公共值大于mid 则一直判断
			}else {
				low = mid - 1;
			}
		}
		return strs[0].substring(0,low);
	}

	private boolean isCommonPrefix(String[] strs, int length) {
		String str0 = strs[0].substring(0, length);
		int count = strs.length;
		for (int i = 1; i < count; i++) {
			String str = strs[i];
			for (int j = 0; j < length; j++) {
				if (str0.charAt(j) != str.charAt(j)){
					return false;
				}
			}
		}
		return true;
	}
}

时间复杂度:O(mn log m) 其中m是字符串的最小长度,n是字符串的数量。二分查找的迭代次数是O(log m) 每次迭代最多需要比较mn个字符。

空间复杂度: O(1) 使用的额外空间复杂度为常数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值