leecode雙指針部分題目
- 1. 驗證回文串
- 2. 判斷子序列
- 3. 兩數之和 II - 輸入有序數組
- 4. 盛最多水的容器
- 5. 三數之和
1. 驗證回文串
如果在將所有大寫字符轉換為小寫字符、并移除所有非字母數字字符之后,短語正著讀和反著讀都一樣。則可以認為該短語是一個 回文串 。
字母和數字都屬于字母數字字符。
給你一個字符串 s,如果它是 回文串 ,返回 true ;否則,返回 false 。
解題思路: 遍歷字符串,判斷是否為字母或數字,使用Character.isLetterOrDigit(),如果是則放入StringBuilder中。
保存一個原本的字符串和反轉后的字符串,判斷是否相同。
class Solution {public boolean isPalindrome(String s) {StringBuilder re = new StringBuilder();// 過濾字符并標準化為小寫for (char c : s.toCharArray()) {if (Character.isLetterOrDigit(c)) { // 只考慮字母和數字re.append(Character.toLowerCase(c)); // 轉為小寫并添加到 StringBuilder}}// 保存過濾后的字符串String filteredString = re.toString(); // 不翻轉// 生成逆置字符串String rev = re.reverse().toString(); // 反轉System.out.println("Filtered String: " + filteredString);System.out.println("Reversed String: " + rev);// 比較原始過濾的字符串和反轉字符串是否相等return filteredString.equals(rev);
}
}
2. 判斷子序列
給定字符串 s 和 t ,判斷 s 是否為 t 的子序列。
字符串的一個子序列是原始字符串刪除一些(也可以不刪除)字符而不改變剩余字符相對位置形成的新字符串。(例如,"ace"是"abcde"的一個子序列,而"aec"不是)。
解題思路: 同時遍歷這兩個字符串,如果相等則i++,j++,如果不相等則只讓i++,最后返回i是否超過它本身長度,如果超過則true,如果沒有則false。
class Solution {public boolean isSubsequence(String s, String t) {int i = 0;int j = 0;char[] ss = s.toCharArray();char[] ts = t. toCharArray();while(i < ss.length && j < ts.length){if(ss[i] != ts[j]){j++;}else{i++;j++;}}return i == ss.length ;}
}
3. 兩數之和 II - 輸入有序數組
給你一個下標從 1 開始的整數數組 numbers ,該數組已按 非遞減順序排列 ,請你從數組中找出滿足相加之和等于目標數 target 的兩個數。如果設這兩個數分別是 numbers[index1] 和 numbers[index2] ,則 1 <= index1 < index2 <= numbers.length 。
以長度為 2 的整數數組 [index1, index2] 的形式返回這兩個整數的下標 index1 和 index2。
你可以假設每個輸入 只對應唯一的答案 ,而且你 不可以 重復使用相同的元素。
你所設計的解決方案必須只使用常量級的額外空間。
解題思路: 使用和二分查找相似的思路,設置low等于0,high等于len-1,只要low <high,則讓sum = num[low] + num [high],如果sum<target,則說明需要low++,如果大于則說明需要high–,如果相等則返回索引值加一,如果都遍歷完都沒找到結果則直接返回【-1,-1】
class Solution {public int[] twoSum(int[] numbers, int target) {int low = 0, high = numbers.length - 1;while (low < high) {int sum = numbers[low] + numbers[high];if (sum == target) {return new int[]{low + 1, high + 1};} else if (sum < target) {++low;} else {--high;}}return new int[]{-1, -1};}
}
4. 盛最多水的容器
給定一個長度為 n 的整數數組 height 。有 n 條垂線,第 i 條線的兩個端點是 (i, 0) 和 (i, height[i]) 。
找出其中的兩條線,使得它們與 x 軸共同構成的容器可以容納最多的水。
返回容器可以儲存的最大水量。
說明:你不能傾斜容器。
解題思路: 設置l 和 r,一個在最左邊,一個在最右邊,只要l<r,則執行,首先計算面積area = min(l,r) * (r - l), 用 ans = max(ans,area),如果l的高度小于等于r的高度,則l++,如果大于則r–,以此找出最大面積。
public class Solution {public int maxArea(int[] height) {int l = 0, r = height.length - 1;int ans = 0;while (l < r) {int area = Math.min(height[l], height[r]) * (r - l);ans = Math.max(ans, area);if (height[l] <= height[r]) {++l;}else {--r;}}return ans;}
}
5. 三數之和
給你一個整數數組 nums ,判斷是否存在三元組 [nums[i], nums[j], nums[k]] 滿足 i != j、i != k 且 j != k ,同時還滿足 nums[i] + nums[j] + nums[k] == 0 。請你返回所有和為 0 且不重復的三元組。
解題思路: 首先數組排序,用i遍歷數組,L = i+1,R= len - 1,如果num[i]大于0,則說明最小的大于0,直接返回,如果num[i] == num[i+1] 則繼續執行,去重。
再循環內使用雙指針,只要L<R,就執行,讓sum = num[i] + num[L] + num[R],如果等于0,則把這三個數放入列表中存下,給L和R去重,讓L和R取到新值。
如果sum>0,則R–;
如果sum<0,則L++;
如此遍歷得到最終答案。
class Solution {public List<List<Integer>> threeSum(int[] nums) {List<List<Integer>> res = new ArrayList<List<Integer>>();int len = nums.length;if(len < 3 || nums == null) return res;Arrays.sort(nums);for(int i = 0; i < len; i++){int L = i + 1;int R = len - 1;if(nums[i] > 0) break;if(i>0 && nums[i] == nums[i-1]){continue;}while(L < R){int sum = nums[i] + nums[L] + nums[R];if(sum == 0){res.add(Arrays.asList(nums[i],nums[L],nums[R]));while(L<R&&nums[L] == nums[L+1]) L++;while(L<R && nums[R] == nums[R-1]) R--;L++;R--;}else if(sum > 0) R--;else if(sum < 0) L++;} }return res;
}}