n数之和
1.两数之和
java
static public int[] twoSum(int[] numbers, int target) {
int i = 0;
int j = numbers.length - 1;
while (i < j) {
int sum = numbers[i] + numbers[j];
if (sum < target) {
i++;
} else if (sum > target) {
j--;
} else {
break;
}
}
return new int[]{i + 1, j + 1};
}
2.三数/四数之和
java
public List<List<Integer>> threeSum1(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
Arrays.sort(nums);
//定义指针
int l = 0;
int r = nums.length - 1;
dfs(nums, result, new LinkedList<>(), 3, l, r, 0);
return result;
}
public void dfs(int[] nums, List<List<Integer>> result, LinkedList<Integer> stack, int n, int l, int r, int target){
if (n == 2){
twoSum(nums, result, stack, l , r, target);
return;
}
for (int i = l; i < r - (n - 2); i++) {
// 检查重复
if (i > l && nums[i] == nums[i - 1]){
continue;
}
stack.push(nums[i]);
dfs(nums, result, stack, n - 1, i + 1, r, target - nums[i]);
stack.pop();
}
}
public List<List<Integer>> twoSum(int[] nums, List<List<Integer>> result, LinkedList<Integer> stack, int l, int r, int target) {
while(l < r){
int sum = nums[l] + nums[r];
if (sum == target){
List<Integer> list = new ArrayList<>(stack);
list.add(nums[l]);
list.add(nums[r]);
result.add(list);
//去重
while(l < r && nums[l] == nums[l + 1]){
l++;
}
while(l < r && nums[r] == nums[r - 1]){
r--;
}
l++;
r--;
}else if (sum < target){
l++;
}else {
r--;
}
}
return result;
}
盛水最多的容器(双指针)
java
static int maxArea(int[] height) {
int i = 0;
int j = height.length - 1;
int max = 0;
while (i < j) {
if (height[i] < height[j]) {
int area = (j - i) * height[i];
max = Math.max(max, area);
i++;
} else {
int area = (j - i) * height[j];
max = Math.max(max, area);
j--;
}
}
return max;
}
滑动窗口最大值(单调队列)
单调队列:要保证值从大到小排列,如果加入队列时前面的元素比后面的大,就要先把比它大的元素先移出来再入队。
构造一个单调递减的队列出来
滑动窗口最大值
java
static int[] maxSlidingWindow(int[] nums, int k) {
MonotonicQueue queue = new MonotonicQueue();
List<Integer> list = new ArrayList<>();
for (int i = 0; i < nums.length; i++) {
// 检查队列头部元素,超过滑动窗口范围要移除
if (i >= k && queue.peek() == nums[i - k]) {
queue.poll();
}
int num = nums[i];
queue.offer(num);
if (i >= (k - 1)) {
// System.out.println(queue.peek());
list.add(queue.peek());
}
}
return list.stream().mapToInt(Integer::intValue)
.toArray();
}
接雨水(单调栈)
java
static int trap(int[] heights) {
LinkedList<Data> stack = new LinkedList<>();
int sum = 0;
for (int i = 0; i < heights.length; i++) {
Data right = new Data(heights[i], i);
while (!stack.isEmpty()
&& stack.peek().height < right.height) {
Data pop = stack.pop();
Data left = stack.peek();
if (left != null) { // 计算水的容量
int width = right.i - left.i - 1;
int height = Math.min(left.height, right.height) - pop.height;
sum += width * height;
}
}
stack.push(right);
// System.out.println(stack);
}
return sum;
}
字符串匹配
最长公共前缀
java
static String longestCommonPrefix(String[] strings) {
/*
情况1:比较某一列时,遇到不同字符,i 之前的字符就是解
情况2:比较某一列时,遇到字符串长度不够,i 之前的字符就是解
情况3:i 循环自然结束,此时第一个字符串就是解
*/
char[] first = strings[0].toCharArray(); // 第一个字符串
for (int i = 0; i < first.length; i++) {
char ch = first[i];
for (int j = 1; j < strings.length; j++) {
/*if (strings[j].length() == i) { // 情况 2
return new String(first, 0, i);
}
if(ch != strings[j].charAt(i)) { // 情况 1
return new String(first, 0, i);
} */
if (strings[j].length() == i || ch != strings[j].charAt(i)) {
return new String(first, 0, i);
}
}
}
return strings[0];
}
最长回文子串
java
static String longestPalindrome(String s) {
left = 0;
right = 0;
char[] chars = s.toCharArray();
for (int i = 0; i < chars.length - 1; i++) {
extend(chars, i, i); // 一个字符作为中心点
extend(chars, i, i + 1); // 两个字符作为中心点
}
return new String(chars, left, right - left + 1);
}
static int left; // i
static int right; // j
static void extend(char[] chars, int i, int j) {
while (i >= 0 && j < chars.length
&& chars[i] == chars[j]) { // 如果是回文,扩大回文范围
i--; // -1
j++; // 4
}
// 退出循环时,i和j指向的不是回文,需要还原
i++;
j--;
if (j - i > right - left) {
left = i;
right = j;
}
}
最长覆盖子串
java
public class MinWindowLeetcode76_me {
static class Result {
int i;
int j;
public Result(int i, int j) {
this.i = i;
this.j = j;
}
}
static String minWindow(String s, String t) {
//目标t数组
char[] target = t.toCharArray();
//统计目标数组出现次数
int[] targetCount = new int[128];
for (char ch : target) {
targetCount[ch]++;
}
print(targetCount);
//---------------目标数组统计-------------------------
//原数组s
char[] source = s.toCharArray();
//统计原数组出现的次数
int[] sourceCount = new int[128];
//---------------原数组统计-------------------------
int i = 0;
int j = 0;
int passCount = 0;
for (int count : targetCount){
if (count > 0){
passCount++;
}
}
int passed = 0;
Result res = null;
while (j < source.length) {
char right = source[j];
sourceCount[right]++;
if (sourceCount[right] == targetCount[right]) {
passed++;
}
while (passed == passCount && i <= j){
if (res == null) {
res = new Result(i, j);
} else {
if (j - i < res.j - res.i) {
res = new Result(i, j);
}
}
char left = source[i];
sourceCount[left]--;
if (sourceCount[left] < targetCount[left]) {
passed--;
}
i++;
}
j++;
}
// System.out.println(res.i + " " + res.j);
return res == null ? "" : new String(source, res.i, res.j - res.i + 1);
}
static void print(int[] count) {
System.out.println(IntStream.range(0, count.length)
.filter(i -> count[i] != 0)
.boxed()
.collect(toMap(i -> (char) i.intValue(), i -> count[i])));
}
public static void main(String[] args) {
System.out.println(minWindow("ADOBECODEBANC", "ABC")); // BANC
}
}