LeetCode第154場周賽(Java)

估計要刷好久才能突破三道題了。仍是刷的太少。儘管對了前兩題,可是我以爲寫的不怎麼樣。仍是將全部題目都寫一下吧。html


5189. 「氣球」 的最大數量

題目比較簡單。就是找出一個字符串中,balloon 中每一個字母出現的次數,次數最小的就是結果。注意,lo 要除以 2。java

定義一個數組統計每一個字母的個數。web

int[] count = new int[26];// 統計每一個字母的個數

時間複雜度:只有一個循環,故爲 O ( n ) O(n)
空間複雜度:只有一個一維數組大小恆爲 26,故爲 O ( 1 ) O(1) 數組

代碼以下:
class Solution {
    public int maxNumberOfBalloons(String text) {
        char[] arr = text.toCharArray();
        
        int[] count = new int[26];// 統計每一個字母的個數
        for (char ch : arr) {
            ++count[ch - 'a'];// 字母ch個數加1
        }
        
        int ans = 10001;
        ans = Math.min(ans, count['b' - 'a']);
        ans = Math.min(ans, count['a' - 'a']);
        ans = Math.min(ans, count['l' - 'a'] >> 1);
        ans = Math.min(ans, count['o' - 'a'] >> 1);
        ans = Math.min(ans, count['n' - 'a']);
        return ans;
    }
}
提交結果:

在這裏插入圖片描述


5190. 反轉每對括號間的子串

基本思路:找一對括號,將之間的字符串反轉,再和括號外邊的字符串從新組合成一個字符串賦給 s,若是找不到括號,說明結束,返回 s 便可。上述過程循環。app

方法 int[] find(String s) 查找字符串 s 中的括號,返回左括號和右括號下標,若是未找到,則返回的數組的值爲 -1。svg

找到括號,就將字符串分紅三段,括號左邊,括號之間,括號右邊。將之間的反轉後,重組成字符串賦給 s。直到未找到括號爲止。ui

時間複雜度: Emmm,還不會算這個的時間複雜度。。。
空間複雜度: 與字符串長度無關, O ( 1 ) O(1) spa

代碼以下:
class Solution {
	public String reverseParentheses(String s) {
		int[] index = find(s);// 查找括號
		while (index[0] != -1) {// 如有括號,循環反轉括號內字符串
			// 左括號左邊的內容
			String outLeft = s.substring(0, index[0]);
			// 反轉前括號之間的內容
			String inBefore = s.substring(index[0] + 1, index[1]);
			// 反轉後括號之間的內容
			StringBuilder sb = new StringBuilder(inBefore);
			String inAfter = sb.reverse().toString();
			// 右括號右邊的內容
			String outRight = s.substring(index[1] + 1, s.length());
			// 重組字符串s,由三部分組成
			s = outLeft + inAfter + outRight;
			index = find(s);// 查找括號
		}
		return s;// 返回結果
	}

	// 查找括號
	// 若未找到,數組的值爲-1
	// 若找到,index[0]爲左括號下標,index[1]爲右括號下標
	private int[] find(String s) {
		char[] arr = s.toCharArray();
		int[] index = new int[2];
		index[0] = index[1] = -1;
		for (int i = 0; i < arr.length; ++i) {
			if (arr[i] == '(') {
				index[0] = i;
			} else if (arr[i] == ')') {
				index[1] = i;
				break;// 找到右括號,退出循環
			}
		}
		return index;
	}
}
提交結果:

在這裏插入圖片描述


1191. K 次串聯後最大子數組之和

基本思路:k 次修改其實就是 k 個數組 arr 首尾相連,當 k 小於 2 的時候,咱們只須要找到數組 arr 的最大子序列就行,當 k 大於等於 2 時,咱們將兩端的 arr 連起來,中間的是 k - 2 個數組 arr 的和是固定的爲 (k - 2) × sumArr,其中 sumArr 表示數組 arr 的和。code

所以問題就變成兩組 arr 拼接起來的最大子序列問題。xml

第 1 個循環是計算從第 1 個數到第 i 個數的和。

第 2 個循環是計算從第 1 個數到第 i 個數的和的最大值。

第 3 個循環是計算從最後一個數到從後往前數的第 i 個數的和的最大值。(與第 2 個循環意思同樣,只不過是從後往前而已)

第 4 個循環是計算數組 arr 的子序列的和的最大值。

而後取相應的最大值便可。

時間複雜度: 只有一層循環, O ( n ) O(n)
空間複雜度: 一維數組, O ( n ) O(n)

代碼以下:
class Solution {
	public int kConcatenationMaxSum(int[] arr,
									int k) {
		int n = arr.length;

		int[] sumpi = new int[n + 1];// 前(pre)i個數的和(sum)
		for (int i = 0; i < n; ++i) {
			sumpi[i + 1] = sumpi[i] + arr[i];
		}

		int maxsumpi = 0;// 前i個數的和的最大值,全爲負數則最大值爲0
		for (int i = 1; i <= n; ++i) {
			maxsumpi = Math.max(maxsumpi, sumpi[i]);
		}

		int maxsumri = 0;// 後(n-i)個數的和的最大值,全爲負數則最大值爲0
		for (int i = n; i >= 0; --i) {
			// sumpi[n]表示前n個數的和,即全部數的和
			maxsumri = Math.max(maxsumri, sumpi[n] - sumpi[i]);
		}

		// 後面j個數的最大值和前面i個數的最大值的和
		int maxsumpr = maxsumpi + maxsumri;

		int maxsubsum = 0;// 最大子序列的和
		int minsumpi = 0;// 前i個數的和的最小值
		for (int i = 1; i <= n; ++i) {
			maxsubsum = Math.max(maxsubsum, sumpi[i] - minsumpi);
			minsumpi = Math.min(minsumpi, sumpi[i]);
		}

		// 10^(5+5+4)=10^14,超過int(10^10)範圍,可是未超過long(10^18)範圍
		long maxsum = maxsubsum;
		if (k >= 2) {// 重複
			// 則取子序列最大值和拼接序列的最大值中的較大者
			maxsum = Math.max(maxsum, maxsumpr);
		}
		if (k >= 2) {
			// 取兩組的最大值和所有的最大值中的較大者
			maxsum = Math.max(maxsum, maxsumpr + (long) (k - 2) * sumpi[n]);
		}

		return (int) (maxsum % 1000000007);// 取模
	}
}
提交結果:

在這裏插入圖片描述

相關文章
相關標籤/搜索