双指针TwoPointers

最长无重复子数组

给定一个数组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,...,an,每个数代表坐标中的一个点 (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
输出:
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
  • abc 和 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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值