acwing学习记录

整数二分

 //区间被划分为[l,mid] [mid+1,r]使用
 //可查找target的最左位置
    public int bSearch1(int[] nums, int l, int r) {
        while (l < r) {
            int mid = l + r >> 1;
            if (check(mid)) r = mid;//check()判断mid是否满足
            else l = mid + 1;
        }
        return l;
    }

    //区间被划分为[l,mid-1] [mid,r]使用
    //可查找taget的最右位置
    public int bSearch2(int[] nums, int l, int r) {
        while (l < r) {
            int mid = r + l + 1 >> 1;
            if (check(mid)) l = mid;
            else r = mid - 1;
        }
        return l;
    }

注意第二种情况mid=r+l+1>>1

浮点二分

在这里插入图片描述

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        double d=sc.nextDouble();
        double l=-10000;
        double r=10000;
        while(r-l>Math.pow(10,-8)){
            double mid=(r+l)/2;
            if(mid*mid*mid>=d)r=mid;
            else
                l=mid;
        }
        System.out.println(String.format("%.6f", l));
    }
}

浮点二分:
1.while(r-l>1e-8))答案要求精确6位小数,可设置终止条件为-8次方
2.浮点边界不需要+1.(l=mid,r=mid)
3.输出保留六位小数浮点数的格式

大整数加减乘除

在这里插入图片描述

//将BigInteger的十进制字符串表示形式转换为BigInteger。 
BigInteger num=new BigInteger(String val) 
  

使用

    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        BigInteger a = sc.nextBigInteger();
        BigInteger b = sc.nextBigInteger();
        //减法
        System.out.println(a.subtract(b));
               //加法
        System.out.println(a.add(b));
        //除法
        System.out.println(a.divide(b));
        //乘法
        System.out.println(a.multiply(b));
        //取余
        System.out.println(a.mod(b));
    }

前缀与差分

在这里插入图片描述
在这里插入图片描述

双指针算法

在这里插入图片描述
双指针算法一般能将双循环遍历(O(N*N))优化为O(n)
需要找出双指针i,j的单调性联系,即可使用双指针

数组模拟栈和队列

单指针模拟栈

   private static int p=0;
    private static int[] stack=new int[100010];
    public static void push(int val){
        stack[++p]=val;
    }
    public static void pop(){
        p--;
    }
    public static void empty(){
        if(p==0)
            System.out.println("YES");
        else
            System.out.println("NO");
    }
    public static int query(){
        return stack[p];
    }

双指针模拟队列

 private static int[] queue=new int[100010];
    private static int l=0,r=0;
    public static void push(int val){
        queue[r++]=val;
    }
    public static void pop(){
        l++;
    }
    public static void empty(){
        if(r-l==0)
            System.out.println("YES");
        else
            System.out.println("NO");
    }
    public static void query(){
        System.out.println(queue[l]);
    }

单调栈

在这里插入图片描述
如果求右边第一个(大值/小值)倒序遍历,左边则正序遍历

import java.util.*;
class Solution {
    public int[] dailyTemperatures(int[] T) {
        int len=T.length;
        int[] res=new int[len];
        Stack<Integer> stack=new Stack<>();
        for(int i=len-1;i>=0;i--){
            while(!stack.isEmpty()&&T[stack.peek()]<=T[i]){
                stack.pop();
            }
            res[i]=stack.isEmpty()?0:stack.peek()-i;
            stack.push(i);
        }
        return res;
    }
}

单调队列

滑动窗口
单调队列核心思想:删除冗余数据,保持队列单调性
使用双端队列Dque,可以从尾部删除数据

 Deque<Integer> deque=new LinkedList<>();
        for(int i=0;i<n;i++){
            nums[i]=sc.nextInt();
            //队列头部元素是否超出窗口范围
            if(!deque.isEmpty()&&i-deque.peekFirst()>=k){
                deque.pollFirst();
            }
            //将新元素与队列后端元素比较,大于num[i]的元素poll,保持队列单调性
            while(!deque.isEmpty()&&nums[i]<nums[deque.peekLast()]){
                deque.pollLast();
            }
            //将新元素加入队列
            deque.offerLast(i);
            //输出每个窗口的最小值
            if(i>=k-1){
                System.out.print(nums[deque.peekFirst()]+" ");
            }
        }

合并集合

题目链接

import java.util.*;
public class Main{
    static int n=100010;
    //p[i]表示 i的父节点之一为p[i]
    private static int[] p=new int[n];
    //找到祖宗节点
    //只有祖宗节点才有p[i]=i;
    public static int find(int x){
       while(x!=p[x]){
           p[x]=p[p[x]];
           x=p[x];
       }
        return x;
    }
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int m=sc.nextInt();
        //p[i]初始化,所有的p[i]=i,即初始所有节点的祖宗都是自己
        for(int i=0;i<n;i++){
            p[i]=i;
        }
        String opt;
        int a,b;
        for(int i=0;i<m;i++){
            opt=sc.next();
            a=sc.nextInt();
            b=sc.nextInt();
            if(opt.equals("M")){
                p[find(a)]=find(b);
            }else{
                if(find(a)==find(b))
                    System.out.println("Yes");
                else
                    System.out.println("No");
            }
        }
    }
}

BFS求迷宫最短路径

DFS一般没有固定模板
BFS一般使用此模板
在这里插入图片描述

import java.util.*;

//存储路径
class Pair{
    int x;
    int y;
    public Pair(int x,int y){
        this.x=x;
        this.y=y;
    }
}
public class Main{

    //地图
    static int[][] arr=null;
    //step[i][j]表示走到[i,j]一共走了多少步
    static int[][] step=null;
    //pairs[i][j]表示[i,j]是从pair走过来的
    static Pair[][] pairs=null;
    static int n;
    static int m;
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        n=sc.nextInt();
        m=sc.nextInt();
        arr=new int[n][m];
        step=new int[n][m];
        pairs=new Pair[n][m];
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                arr[i][j]=sc.nextInt();
            }
        }
        System.out.println(bfs());
    }
    public static int bfs(){
        Queue<Pair> queue=new LinkedList<>();

        int[] dy = {0, 1, 0, -1}, dx = {-1, 0, 1, 0};
        //将起始点放入队列
        queue.offer(new Pair(0,0));
        int x,y;
        while(!queue.isEmpty()){
            Pair pair=queue.poll();
            for(int i=0;i<4;i++){
                x=pair.x+dx[i];
                y=pair.y+dy[i];
                if(x>=0&&x<n&&y>=0&&y<m&&arr[x][y]==0&&step[x][y]==0){
                    step[x][y]=step[pair.x][pair.y]+1;
                    queue.offer(new Pair(x,y));
                    pairs[x][y]=pair;
                }
            }
        }
        //倒序打印最短路径
        x=n-1;
        y=m-1;
        while(x!=0||y!=0){
            System.out.println(x+" "+y);
            Pair tmp=pairs[x][y];
            x=tmp.x;
            y=tmp.y;
        }
        return step[n-1][m-1];
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值