最长无重复子数组
给定一个数组arr,返回arr的最长无重复元素子数组的长度,无重复指的是所有数字都不相同。
子数组是连续的,比如[1,3,5,7,9]的子数组有[1,3],[3,5,7]等等,但是[1,3,7]不是子数组
import java.util.*;
public class Solution {
/**
*
* @param arr int整型一维数组 the array
* @return int整型
*/
public int maxLength (int[] arr) {
// write code here
HashMap<Integer, Integer> map = new HashMap<>();
map.put(arr[0], 0);
int ans = 1;
int pre = 1;
for (int i = 1; i < arr.length; i++) {
pre = Math.min(i - map.getOrDefault(arr[i], -1), pre + 1);
ans = Math.max(pre, ans);
map.put(arr[i], i);
}
return ans;
}
}
接雨水问题
给定一个整形数组arr,已知其中所有的值都是非负的,将这个数组看作一个柱子高度图,计算按此排列的柱子,下雨之后能接多少雨水。(数组以外的区域高度视为0)
public long maxWater (int[] arr) {
int l = 0, r = arr.length-1;
int maxL = 0, maxR = 0;
long res = 0;
while(l < r){
maxL = Math.max(arr[l],maxL);
maxR = Math.max(arr[r],maxR);
if(maxR > maxL){
res += maxL - arr[l++];
}else{
res += maxR - arr[r--];
}
}
return res;
}
滑动窗口的最大值
给定一个长度为 n 的数组 num 和滑动窗口的大小 size ,找出所有滑动窗口里数值的最大值。
例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。
窗口大于数组长度或窗口长度为0的时候,返回空。
要求:空间复杂度 O(n)O(n),时间复杂度 O(n)O(n)
// 双指针
import java.util.*;
public class Solution {
public ArrayList<Integer> maxInWindows(int [] num, int size) {
ArrayList<Integer> res = new ArrayList<>();
if (size > num.length || size == 0) return res;
for (int f=0; f<num.length; f++) {
int limit = f + size;
if (limit > num.length) break;
ArrayList<Integer> list = new ArrayList<>();
for (int s=f; s<limit; s++) {
list.add(num[s]);
list.sort(Comparator.naturalOrder());
}
res.add(list.get(size-1));
}
return res;
}
}
最小覆盖子串
给出两个字符串 s 和 t,要求在 s 中找出最短的包含 t 中所有字符的连续子串。
基本上是某位大佬的代码,添加了有关注释
import java.util.*;
public class Solution {
/**
*
* @param S string字符串
* @param T string字符串
* @return string字符串
*/
public String minWindow (String S, String T) {
// write code here
//存放S串中的字符记录
Map<Character,Integer> source=new HashMap<>();
//存放T串中的字符记录
Map<Character,Integer> target=new HashMap<>();
//初始化Map target,在此后的匹配过程中,T中值作为目标,不变,动态变化的是Map source
for(int i=0;i<T.length();i++){
char c=T.charAt(i);
target.put(c,target.getOrDefault(c,0)+1);
}
//记录滑动窗口的起点
int left=0;
//记录滑动窗口的终点
int right=0;
//记录窗口长度
int min=Integer.MAX_VALUE;
//记录source匹配target中字符种类的个数
//只有source中匹配target中某个字符相同的个数,才算匹配了该字符
int count=0;
//记录最小窗口时的起点,以便定位到最终S中的子串位置(需要起点和长度两个值)
int start=0;
//开始滑动窗口,从右边开始
while(right<S.length()){
char c=S.charAt(right);
right++;
if(target.containsKey(c)){
source.put(c,source.getOrDefault(c,0)+1);
if(source.get(c)==target.get(c)){
count++;
}
}
//缩小窗口,即增大left
while(count==target.size()){
//判断当前窗口长度是否为最小值,如果是则记录
if(right-left<min){
start=left;
min=right-left;
}
c=S.charAt(left);
left++;
//如果之前的left位置的字符c在target中出现
if(target.containsKey(c)){
//之前left的位置正好是S串中 包含 T串中 所有字符c 的左起点,则count-1
if(source.get(c)==target.get(c)){
count--;
}
//当然要在source中将c的统计数减一
source.put(c,source.getOrDefault(c,0)-1);
}
}
}
return min==Integer.MAX_VALUE?"":S.substring(start,start+min);
}
}
数组中相加和为0的三元组
给出一个有n个元素的数组S,S中是否有元素a,b,c满足a+b+c=0?找出数组S中所有满足条件的三元组。
import java.util.*;
public class Solution {
public ArrayList<ArrayList<Integer>> threeSum(int[] num) {
Arrays.sort(num);
ArrayList<ArrayList<Integer>> list = new ArrayList<>();
for(int i = 0; i < num.length; i++){
int l = i+1, r = num.length-1;
if(i > 0 && num[i] == num[i-1]) continue;
while(l < r){
if((l > i+1 && num[l] == num[l-1])){
l++;
continue;
}
if(r < num.length-1 && num[r] == num[r + 1]){
r--;
continue;
}
int sum = num[i] + num[l] + num[r];
if(sum == 0){
ArrayList<Integer> temp = new ArrayList<>();
temp.add(num[i]);
temp.add(num[l]);
temp.add(num[r]);
list.add(temp);
l++;
r--;
}else if(sum > 0){
r--;
}else{
l++;
}
}
}
return list;
}
}
盛最多水的容器
给你 n
个非负整数 a1,a2,...,a
n
,每个数代表坐标中的一个点 (i, ai)
。在坐标内画 n
条垂直线,垂直线 i
的两个端点分别为 (i, ai)
和 (i, 0)
。找出其中的两条线,使得它们与 x
轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器。
public int maxArea(int[] height) {
int left=0,right=height.length-1,max=0;
while(left<right){
max=Math.max(max,Math.min(height[left],height[right])*(right-left));
if(height[left]<height[right]){
int preleft=height[left];
while(height[left]<=preleft && left<right){
left++;
}
}
else{
int preright=height[right];
while(height[right]<=preright && left<right){
right--;
}
}
}
return max;
}
三数之和
给你一个包含 n
个整数的数组 nums
,判断 nums
中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0
且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4] 输出:[[-1,-1,2],[-1,0,1]]
示例 2:
输入:nums = [] 输出:[]
示例 3:
输入:nums = [0] 输出:[]
public List<List<Integer>> threeSum(int[] num) {
Arrays.sort(num);
List<List<Integer>> res = new LinkedList<>();
for (int i = 0; i < num.length-2; i++) {
if (i == 0 || (i > 0 && num[i] != num[i-1])) {
int lo = i+1, hi = num.length-1, sum = 0 - num[i];
while (lo < hi) {
if (num[lo] + num[hi] == sum) {
res.add(Arrays.asList(num[i], num[lo], num[hi]));
while (lo < hi && num[lo] == num[lo+1]) lo++;
while (lo < hi && num[hi] == num[hi-1]) hi--;
lo++; hi--;
} else if (num[lo] + num[hi] < sum) lo++;
else hi--;
}
}
}
return res;
}
最接近的三数之和
给你一个长度为 n
的整数数组 nums
和 一个目标值 target
。请你从 nums
中选出三个整数,使它们的和与 target
最接近。
返回这三个数的和。
假定每组输入只存在恰好一个解。
示例 1:
输入:nums = [-1,2,1,-4], target = 1 输出:2 解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。
示例 2:
输入:nums = [0,0,0], target = 1 输出:0
public class Solution {
public int threeSumClosest(int[] num, int target) {
int result = num[0] + num[1] + num[num.length - 1];
Arrays.sort(num);
for (int i = 0; i < num.length - 2; i++) {
int start = i + 1, end = num.length - 1;
while (start < end) {
int sum = num[i] + num[start] + num[end];
if (sum > target) {
end--;
} else {
start++;
}
if (Math.abs(sum - target) < Math.abs(result - target)) {
result = sum;
}
}
}
return result;
}
}
四数之和
给你一个由 n
个整数组成的数组 nums
,和一个目标值 target
。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]]
(若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < n
a
、b
、c
和d
互不相同nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。
示例 1:
输入:nums = [1,0,-1,0,-2,2], target = 0 输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
示例 2:
输入:nums = [2,2,2,2,2], target = 8 输出:[[2,2,2,2]]
public class Solution {
int len = 0;
public List<List<Integer>> fourSum(int[] nums, int target) {
len = nums.length;
Arrays.sort(nums);
return kSum(nums, target, 4, 0);
}
private ArrayList<List<Integer>> kSum(int[] nums, int target, int k, int index) {
ArrayList<List<Integer>> res = new ArrayList<List<Integer>>();
if(index >= len) {
return res;
}
if(k == 2) {
int i = index, j = len - 1;
while(i < j) {
//find a pair
if(target - nums[i] == nums[j]) {
List<Integer> temp = new ArrayList<>();
temp.add(nums[i]);
temp.add(target-nums[i]);
res.add(temp);
//skip duplication
while(i<j && nums[i]==nums[i+1]) i++;
while(i<j && nums[j-1]==nums[j]) j--;
i++;
j--;
//move left bound
} else if (target - nums[i] > nums[j]) {
i++;
//move right bound
} else {
j--;
}
}
} else{
for (int i = index; i < len - k + 1; i++) {
//use current number to reduce ksum into k-1sum
ArrayList<List<Integer>> temp = kSum(nums, target - nums[i], k-1, i+1);
if(temp != null){
//add previous results
for (List<Integer> t : temp) {
t.add(0, nums[i]);
}
res.addAll(temp);
}
while (i < len-1 && nums[i] == nums[i+1]) {
//skip duplicated numbers
i++;
}
}
}
return res;
}
}
删除链表倒数第n个结点
给你一个链表,删除链表的倒数第 n
个结点,并且返回链表的头结点。
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode start = new ListNode(0);
ListNode slow = start, fast = start;
slow.next = head;
//Move fast in front so that the gap between slow and fast becomes n
for(int i=1; i<=n+1; i++) {
fast = fast.next;
}
//Move fast to the end, maintaining the gap
while(fast != null) {
slow = slow.next;
fast = fast.next;
}
//Skip the desired node
slow.next = slow.next.next;
return start.next;
}