注:代码基于力扣上的题目,但不一定是题目的最优解,如有出错可随时联系
二分查找(升序查找)
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。(力扣题号704)
左闭右开区间
class Solution {
public int search(int[] nums, int target) {
int l = 0, r = nums.length;
while (l < r) {
int mid = l + ((r - l) / 2);// 防止溢出,等同于(l+r)/2
if (nums[mid] == target)
return mid;
else if (nums[mid] < target)
l = mid + 1;
else if (nums[mid] > target)
r = mid;
}
return -1;
}
}
哈希(数组、Set、Map)
优先使用顺序:数组 > Set > Map
判断是否为有效字母异位词(力扣题号242)
利用ASCII码和哈希数组对字符串的判断
class Solution {
public boolean isAnagram(String s, String t) {
int n = s.length();
int m = t.length();
if(n != m) return false;
int[] hash = new int[26];
for(int i = 0; i < n; i++){
hash[s.charAt(i) - 'a'] ++;//ASCII码转换到数组进行加减
}
for(int i = 0; i < m; i++){
hash[t.charAt(i) - 'a'] --;
}
for(int i = 0; i < 26; i++){
if(hash[i] != 0) return false;
}
return true;
}
}
返回同一异位词的数组列表 (力扣题号49)
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
// 创建一个 HashMap,用于存储分组后的字母异位词,键为排序后的字符串,值为字符串列表
Map<String, List<String>> map = new HashMap<String, List<String>>();
// 遍历给定的字符串数组
for (String str : strs) {
char[] array = str.toCharArray(); // 将当前字符串转换为字符数组
Arrays.sort(array); // 对字符数组进行排序,实现字母异位词的统一表示
String key = new String(array); // 将排序后的字符数组转换为字符串作为 key
// 获取 key 对应的值列表,如果不存在则创建一个新的列表
List<String> list = map.getOrDefault(key, new ArrayList<String>());
list.add(str); // 将当前字符串添加到值列表中
map.put(key, list); // 更新哈希表中 key 对应的值列表
}
// 返回哈希表中的值列表,即为分组后的字母异位词列表
return new ArrayList<List<String>>(map.values());
}
}
最长连续序列(可用双指针,力扣题号128)
给出一个乱序数组,要求找出 最长连续序列(即找出前一个比后一个大1的最长序列)
class Solution {
public int longestConsecutive(int[] nums) {
if (nums.length == 0) return 0;
Set<Integer> set = new HashSet<>();
for (int num : nums) {
set.add(num);
}
int max = 0;
for (int num : set) {
// 跳过所有可能的起始数字
if (set.contains(num - 1)) continue;
int count = 1;
while (set.contains(num + 1)) {
num += 1;
count += 1;
}
max = Math.max(max, count);
}
return max;
}
}
双指针
利用 l 、r(或 i 、j ) 两个指针对字符串、数组等元素操作问题进行解题
最长连续序列(可用哈希,力扣题号128)
给出一个乱序数组,要求找出 最长连续序列(即找出前一个比后一个大1的最长序列)
class Solution {
public int longestConsecutive(int[] nums) {
if(nums.length == 0) return 0;
// 对数组排序
Arrays.sort(nums);
int max = 1;
int count = 1;
int i = 0;
// 双指针去重
for (int j = 1; j < nums.length; ++j) {
// 如果重复,跳过
if (nums[i] == nums[j]) {
continue;
} else if (nums[i] + 1 == nums[j]) {
count++;
max = Math.max(max, count);
} else {
count = 1;
}
// 更新慢指针
i = j;
}
return max;
}
}
移动零(力扣题号283)
将数组中的零移到末尾,其他顺序不变
class Solution {
public void moveZeroes(int[] nums) {
//l是慢指针
int l = 0;
//r是快指针
for (int r = 0; r < nums.length; r++) {
if (nums[r] != 0) {
//先进行复制再l+1
nums[l++] = nums[r];
}
}
//补零
while(l < nums.length){
nums[l++] = 0;
}
}
}
盛水最多的容器(经典,力扣题号11)
面积 = 短边 * 两边距离之差
class Solution {
public int maxArea(int[] height) {
int l = 0;
int r = height.length - 1;
int x = 0;
while(l < r){
int t = (r - l) * Math.min(height[l], height[r]);
x = Math.max(x, t);
if(height[l] < height[r]){
l++;
}else{
r--;
}
}
return x;
}
}
三数之和(力扣题号15)
双指针 l,r ,在遍历过程中双指针不断变化来查找合适数组,难点在于去重
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
Arrays.sort(nums);
for (int i = 0; i < nums.length - 2; i++) {
// 跳过重复的元素
if (i > 0 && nums[i] == nums[i - 1]) continue;
int l = i + 1, r = nums.length - 1;
while (l < r) {
int sum = nums[i] + nums[l] + nums[r];
// 如果当前和等于0,则添加当前三元组到结果列表中
if (sum == 0) {
list.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--;
}
// 如果当前和小于0,则移动左指针
else if (sum < 0) l++;
// 如果当前和大于0,则移动右指针
else r--;
}
}
return list;
}
}