天天看點

LeetCode#345 反轉字元串中的元音字母|Java HashSet和HashMap|雙指針|String字元串和字元數組

1. 知識拓展

1.1 HashSet和HashMap

1.1.1 HashSet

HashSet是實作Set< E >接口的一個實體類,資料以哈希表的形式存放,特點是不允許有重複元素且無序存放元素。既然是實作了Set< E >接口,那Set< E >接口的特性是什麼呢?

  • Set接口繼承了Collection接口,故包含Collection接口的所有方法。
  • 無序(存儲和取出順序不一緻,也有可能一緻),但元素唯一,不允許有重複。
  • 實作類有HashSet,底層資料是哈希表;和TreeSet,底層資料是紅黑二叉樹。
    LeetCode#345 反轉字元串中的元音字母|Java HashSet和HashMap|雙指針|String字元串和字元數組
    如何初始化HashSet的值呢?
public static final String[] SET_VALUES = new String[] { "a", "b" };
public static final Set<String> MY_SET = new HashSet<>(Arrays.asList(SET_VALUES));
           
private final static HashSet<Character> vowels = new HashSet<>(
			Arrays.asList('a', 'e', 'o', 'i', 'u', 'A', 'E', 'O', 'I', 'U'));
           
HashSet<String> h = new HashSet<String>() {{
    add("a");
    add("b");
}};
           
HashSet<String> h = new HashSet<String>();
h.add("a");
h.add("b");
           

1.1.2 HashMap

HashMap是實作Map<K,V>接口的一個實體類,它對鍵值做了一對一的映射關系,裡面鍵值不能重複。

HashMap由數組+連結清單組成的,數組是HashMap的主體,連結清單則是主要為了解決哈希沖突而存在的,如果定位到的數組位置不含連結清單(目前entry的next指向null),那麼查找,添加等操作很快,僅需一次尋址即可;如果定位到的數組包含連結清單,對于添加操作,其時間複雜度為O(n),首先周遊連結清單,存在即覆寫,否則新增;對于查找操作來講,仍需周遊連結清單,然後通過key對象的equals方法逐一比對查找。是以,性能考慮,HashMap中的連結清單出現越少,性能才會越好。

LeetCode#345 反轉字元串中的元音字母|Java HashSet和HashMap|雙指針|String字元串和字元數組

HashMap的總體結構

LeetCode#345 反轉字元串中的元音字母|Java HashSet和HashMap|雙指針|String字元串和字元數組

1.1.3 HashSet和HashMap的差別

LeetCode#345 反轉字元串中的元音字母|Java HashSet和HashMap|雙指針|String字元串和字元數組

1.2 String字元串和字元數組

1.2.1 String字元串和字元數組的互相轉換

字元數組轉換為字元串

char[] array = new char[] {'a','b','c','d','e','f','g'};
String str = new String(array);
           
char[] array = new char[] {'a','b','c','d','e','f','g'};
String str2 = String.valueOf(array);
           

字元串轉換為字元數組

使用toCharArray()方法。

String msg = "i am a good boy!";
char[] dest = msg.toCharArray();
           

1.2.2 取String字元串中的某個元素

使用charAt()方法,s是String類型,p,q是int型的。

char s1 = s.charAt(p);
char s2 = s.charAt(q);
           

2.題目描述

編寫一個函數,以字元串作為輸入,反轉該字元串中的元音字母。

示例 1:

輸入: “hello”

輸出: “holle”

示例 2:

輸入: “leetcode”

輸出: “leotcede”

說明:

元音字母不包含字母"y"。

3.分析

使用雙指針,一個指針從前往後周遊,一個指針從後往前周遊,遇到元音字母就交換位置。為快速判斷一個字元是不是元音字元,将全部元音字母(包括大小寫)添加到集合 HashSet 中,進而以 O(1) 的時間複雜度進行該操作。

時間複雜度:周遊所有的元素一次,O(n)

空間複雜度:隻使用兩個指針,O(1)

4.代碼

public class ReverseVowels {

	//把所有的元音字母,包括大小寫存到HashSet中
	private final static HashSet<Character> vowels = new HashSet<>(
			Arrays.asList('a', 'e', 'o', 'i', 'u', 'A', 'E', 'O', 'I', 'U'));
	
	public String reverseVowels(String s) {
		//字元串為空,直接傳回null
		if(s == null)
			return null;
		char[] res = new char[s.length()]; //結果字元數組
 		int p = 0, q = s.length()-1; //雙指針
		while(p <= q) {
			//取出指針對應的字元
			char s1 = s.charAt(p);
			char s2 = s.charAt(q);
			if(!vowels.contains(s1)) { //s1不是元音字母
				res[p++] = s1;
				//p++; 第一次送出後修改
			}
			else if(!vowels.contains(s2)) { //s2不是元音字母
				res[q--] = s2;
				//q--; 第一次送出後修改
			}
			else { //兩指針對應元素至少有一個元音字母
				res[p++] = s2;
				res[q--] = s1;
			}
		}
		return new String(res);
    }
	
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String str = sc.nextLine();
		
		ReverseVowels rv = new ReverseVowels();
		System.out.println(rv.reverseVowels(str));
	}
}
           

5.運作結果

LeetCode#345 反轉字元串中的元音字母|Java HashSet和HashMap|雙指針|String字元串和字元數組

送出修改記錄:

-把兩個語句合成一個之後,運作更快了

res[p] = s1;
p++;
           

改為

參考網址

https://blog.csdn.net/zfliu96/article/details/83476493#21HashSet_111

https://blog.csdn.net/weixin_44551646/article/details/94898951

https://blog.csdn.net/cong____cong/article/details/79727938

https://includestdio.com/1375.html

https://blog.csdn.net/woshimaxiao1/article/details/83661464

https://blog.csdn.net/weixin_42153410/article/details/95494014