leetcode-双指针与滑动窗口

283. 移动零

思路1:是按照栈来填入 最后补0,因为栈的标记永远比遍历的i要慢,所以可以随便覆盖。其实还是双指针,凭借两个指针无法相遇,所以可以这样使用
思路2:双指针,交换元素,注意指针的次序
输出方法:Arrays.toString(nums)数组不能直接输出
代码:

点击查看代码
import java.util.*

class Solution{
	public void sovle2(int[] nums){
		int n = nums.length,s=0;
		for(int i=0; i<n; i++){
			if(nums[i]!=0){
				nums[s++] = nums[i];
			}
		}
		// 清零剩余位置
    	while (s < n) {
        	nums[s++] = 0;
    	}
		return ;
	}
	public void solve1(int[] nums){
		int n= nums.length,s1=0,s2=0;
		while(s1<n&&s2<n){
			while(s1<n&&nums[s1]!=0) s1++;
			s2 = s1;
			while(s2<n&&nums[s2]==0) s2++;
			if(s1<n&&s2<n){
				nums[s1] = nums[s2];
				nums[s2] = 0;
			}
		}
		return;
	}
	public static void main(String[] args){
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt();
		int[] nums = new int[n];
		for(int i=0; i<n; i++){
			nums[i] = scanner.nextInt();
		}
		
		Solution solution = new Solution();
		solution.solve1(nums);
		solution.solve2(nums);
		
		System.out.println(Arrays.toString(nums));
		scanner.close();
	}
}

11. 盛最多水的容器

思路简单:两个指针往中间移动,核心思想是移动小的一边,贪心。主要是最短的边,不然只会更小,没有变大的可能性。

点击查看代码
import java.util.*;

class Solution{
	public int solve(int[] nums){
		int n = nums.length, ans = 0 ,l = 0,r=n-1;
		while(l<r){
			ans = Math.max(ans, (r-l)*Math.min(nums[l],nums[r]));
			if(nums[l]<nums[r]) l++;
			else r--;
		}
		return ans;
	}
	public static void main(String[] args){
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt();
		int[] nums = new int[n];
		for(int i=0; i<n; i++){
			nums[i] = scanner.nextInt();
		}
		
		Solution solution = new Solution();
		int ans = solution.solve(nums);
		System.out.println(ans);
		scanner.close();
	}
}

15. 三数之和

思路先排序,然后变成两数之和的思想,注意重复的元素考虑!
这个题主要是对重复元素的处理方式
if(k>0 && nums[k] == nums[k-1]) continue;
while(i < j && nums[j] == nums[--j]);

快速建立listArrays.asList(nums[i], nums[l], nums[r])注意是Arrays

点击查看代码
import java.util.*

class Solution{
	public List<List<Integer>> solve(int[] nums){
		Arrays.sort(nums);
		int n = nums.length;
		List<List<Integer>> ans = new ArrayList<>();
		
		for(int i=0; i<n; i++){
			if(i>0&& nums[i]==nums[i-1]) continue;
			int l = i+1, r = n-1;
			while(l<r){
				int sum = nums[i] + nums[l] + nums[r];
				if(sum == 0 ){
					ans.add(new ArrayList<Integer>(Arrays.asList(nums[k], nums[i], nums[j])));
					int t = nums[l];
					while(l<n&&nums[l]==nums[t]) l++;
				}else if(sum<0){
					l++;
				}else{
					r--;
				}
			}
		}
		return ans;
	}
	public static void main(String[] args){
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt();
		int[] nums = new int[n];
		for(int i=0; i<n; i++){
			nums[i] = scanner.nextInt();
		}
		
		Solution solution = new Solution();
		List<List<Integer>> ans = solution.solve(nums);
		
		System.out.println("所有和为 0 的三元组为: ");
        for (List<Integer> triplet : ans) {
            System.out.println(triplet);
        }
		scanner.close();
	}
}

42. 接雨水

两种思路
第一种是,每个位置只受当前左右最大值的影响,所以可以记录每个位置的左右最大值然后计算
第二种是,找宏观递增点和递减点,然后计算每个点之间的凹槽值,重点在于最右边的最高点计算

点击查看代码
import java.util.*;

class Solution{
	public int solve1(int[] nums){
		int n = nums.length, ans = 0, t=0;
		int[] lmax = new int[n];
		int[] rmax = new int[n];
		
		for(int i=0; i<n; i++){
			if(t<nums[i]) t= nums[i];
			lmax[i] = t;
		}
		t=0;
		for(int i=n-1; i>=0; i--){
			if(t<nums[i]) t= nums[i];
			rmax[i] = t;
		}
		for(int i=0; i<n; i++){
			ans+=Math.min(lmax[i],rmax[i]) - nums[i];
		}
		return ans;
	}
	
	public int solve2(int[] nums){
		int n = nums.length,ans=0,maxpos=0;
		for(int i=0; i<n; i++){
			if(nums[maxpos]<=nums[i]) maxpos = i;
		}
		int cur=0,j=0;
		while(cur<maxpos){
			j = cur+1;
			while(j<n&&nums[j]<nums[cur]) j++;
			if(j<n){
				for(int i=cur+1; i<j; i++) ans+=nums[cur] - nums[i];
			}
			cur = j;
		}
		cur = n-1;
		while(cur>maxpos){
			j = cur-1;
			while(j>=0&&nums[j]<nums[cur]) j--;
			if(j>=0){
				for(int i=cur-1; i>j; i--) ans+=nums[cur] - nums[i];
			}
			cur = j;
		}
		return ans;
	}
	
	public static void main(String[] args){
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt();
		int[] nums = new int[n];
		for(int i=0; i<n; i++) nums[i] = scanner.nextInt();
		
		Solution s = new Solution();
		itn ans = s.solve1(nums);
		ans = s.solve2(nums);
		System.out.println(ans);
		scanner.close();
	}
}

3. 无重复字符的最长子串

注意string的一些api用法
先更新右指针,在更新左指针

438. 找到字符串中所有字母异位词

右指针加,左指针减,每次循环结束后检查答案,因为左右指针可能都会调整后产生答案。

posted @ 2025-05-08 22:31  keepsoft123  阅读(12)  评论(0)    收藏  举报