算法练习:判断一个字符串中的字符是否唯一(只用基本数据结构)

package codinginterview;

/**
 * 
 * 实现一个算法来判断一个字符串中的字符是否唯一(即没有重复). 
 * 不能使用额外的数据结构。 (即只使用基本的数据结构)
 * @author mingdong.cheng
 * 
 */

public class CheckUniqueChar {

	/**
	 * 对于ASCII字符,我们需要256位
	 * 该算法的时间复杂度为O(n)
	 * @param s
	 * @return
	 */
	public static boolean isUnique(String s) {

		final boolean[] a = new boolean[256];

		int len = s.length();
		for (int i = 0; i < len; i++) {
			int v = (int) s.charAt(i);
			if (a[v])return false;
			a[v] = true;
		}

		return true;

	}

	/**
	 * 通过位运算来减少空间的使用量。 
	 * 用每一位表征相应位置字符的出现。
	 * 对于ASCII字符,我们需要256位,即一个大小为8的int 数组a即可。
	 * 这里的关键是要把字符对应的数字,映射到正确的位上去。
	 * 比如字符'b'对应的 代码是98,那么我们应该将数组中的哪一位置为1呢?
	 * 用98除以32,得到对应数组a的下标:3。
	 * 98对32取模得到相应的位:2。
	 * 该算法的时间复杂度为O(n),需要的内存空间更小
	 * @param s
	 * @return
	 */
	public static boolean isUnique2(String s) {

		final int[] a = new int[8];//位运算时,256个字符需要8个整型数来表征存储位:256/32=8

		int len = s.length();
		for (int i = 0; i < len; i++) {
			int v = (int) s.charAt(i);
			int idx=v/32,shift=v%32;
		    int b=a[idx]&(1 << shift);
			if (b!=0)return false;
			a[idx]|=(1 << shift);
		}
		

		return true;

	}
	
	
	/**
	 * 如果字符集只是a-z(或是A-Z)仅26个字符,那就更好办了,用位运算只需要一个整型数即可。
	 * @param s
	 * @return
	 */
	public static boolean isUnique3(String s) {

		int check=0;//位运算可映射表征32位

		int len = s.length();
		for (int i = 0; i < len; i++) {
			int v = (int) s.charAt(i);
		    int b=check&(1 << v);
			if (b!=0)return false;
			check|=(1 << v);
		}
		

		return true;

	}
	

	public static void main(String[] args) {

		String s1 = "i am daniel cheng.";
		String s2 = "abcdefghijklmnopqrstuvwxyzABCD1234567890";
		String s3 = "abcdefghijklmnopqrstuvwxyz";
		String s4 = "01234567892";
		System.out.println(isUnique(s1));
		System.out.println(isUnique2(s2));
		System.out.println(isUnique3(s3));
		System.out.println(isUnique3(s4));

	}

}

你可能感兴趣的:(算法,字符串,唯一,重复,O(n))