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. 找到字符串中所有字母异位词
右指针加,左指针减,每次循环结束后检查答案,因为左右指针可能都会调整后产生答案。

浙公网安备 33010602011771号