蓝桥杯java算法学习(一)

注意:以下部分内容摘自Acwing,仅用于个人学习记录,不做任何商业用途。

(1)快速排序

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;


public class Main{
  public static void main(String[] args) throws IOException{
        InputStreamReader in = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(in);

        int num = Integer.parseInt(br.readLine());
        int[] arr = new int[num];

        String[] res = br.readLine().split(" ");
        for (int i = 0; i < num; i++) {
            arr[i] = Integer.parseInt(res[i]);
        }

        quickSort(arr, 0, num - 1);

        for (int i = 0; i < num; i++) {
            System.out.print(arr[i] + " ");
        }
        br.close();

    }
    //快排模板 v.v
    public static void quickSort(int[] q, int l, int r) {
        if (l >= r) return;
        int x = q[l+r>>1];

        //Define positions of two pointers
        int i = l - 1;
        int j = r + 1;

        while (i < j) {
            do i++; while (q[i] < x);
            do j--; while (q[j] > x);
            //do Swap
            if (i < j) {
                int temp = q[i];
                q[i] = q[j];
                q[j] = temp;
            }
        }

        quickSort(q, l, j);
        quickSort(q, j + 1, r);
    }
}

(2)归并排序

public class Main {
    public static void main(String[] args) {
        // 对输入值进行初始化
        Scanner in =  new Scanner(System.in);
        int n = in.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++) {
            arr[i] = in.nextInt();
        }
        // 归并排序
        merge_sort(arr, 0, n - 1);

        // 打印输出
        for (int i = 0; i < n; i++)
            System.out.print(arr[i] + " ");
    }

    // 归并排序
    private static void merge_sort(int[] arr, int l, int r) {
        // 递归结束条件
        if (l >= r) return;

        // 以下都为逻辑部分
        int mid = l + r >> 1;
        merge_sort(arr, l, mid);
        merge_sort(arr, mid + 1, r);

        int[] tmp = new int[r - l + 1]; // 临时数组, 用于临时存储 [l,r]区间内排好序的数据
        int i = l, j = mid + 1, k = 0;  // 两个指针
        // 进行归并
        while (i <= mid && j <= r) {
            if (arr[i] <= arr[j]) 
                tmp[k++] = arr[i++];
            else
                tmp[k++] = arr[j++];
        }

        while (i <= mid) tmp[k++] = arr[i++];
        while (j <= r) tmp[k++] = arr[j++];

        // 进行赋值
        for (i = l, j = 0; i <= r; i++, j++)
            arr[i] = tmp[j];
    }
}

(3)二分

// 区间[l, r]被划分成 [l, mid] 和 [mid+1, r]时使用
int bsearch_1(int l, int r) {
    while (l < r) {
        int mid = l + r >> 1;
        if (check[mid)  // check() 判断 mid是否满足性质
            r = mid; 
        else
            l = mid + 1;
    }
    return l;
}
// 区间[l, r]被划分成 [l, mid-1] 和 [mid, r]时使用
int bsearch_2(int l, int r) {
    while (l < r) {
        int mid = l + r + 1 >> 2;   // 注意
        if (check[mid)  // check() 判断 mid是否满足性质
            l = mid;
        else
            r = mid - 1;

    }
    return l;
}

(4)高精度加减乘除(JAVA)

import java.io.*;
import java.math.BigInteger;
public class Main {
	 public static void main(String[] args) throws IOException{
	        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
	        BigInteger a = new BigInteger(reader.readLine());
	        BigInteger b = new BigInteger(reader.readLine());
	        //add
	        System.out.println(a.add(b));
	        //减法 subtract( )
	        System.out.println(a.subtract(b));
	        //乘法 multiply( )
	        System.out.println(a.multiply(b));
	        
	        //divide 返回值为 a/b
	        BigInteger[] c = a.divideAndRemainder(b); //返回值为数组,分别为a/b和a%b
	        System.out.println(c[0]);
	        System.out.println(c[1]);
	        //取余 mod( )
	        System.out.println(a.mod(b));
	        
	        reader.close();
	    }

}

以下是小数模版

BigDecimal(char[] in) 
一个转换的字符数组表示 BigDecimal成 BigDecimal ,接受字符作为的相同序列 BigDecimal(String)构造。  
BigDecimal(char[] in, int offset, int len) 
一个转换的字符数组表示 BigDecimal成 BigDecimal ,接受字符作为的相同序列 BigDecimal(String)构造,同时允许一个子阵列被指定。    
BigDecimal(double val) 
将 double转换为 BigDecimal ,这是 double的二进制浮点值的精确十进制表示 
BigDecimal(int val)
将 int成 BigDecimal
BigDecimal(long val) 
将 long成 BigDecimal
BigDecimal(String val)  

import java.io.*;
import java.math.BigDecimal;

public class Main {

    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        BigDecimal a = new BigDecimal(reader.readLine());
        BigDecimal b = new BigDecimal(reader.readLine());
        //加法
        System.out.println(a.add(b));
        //其余同上
        reader.close();
    }
}

(5)高精度加减乘除(C++)

(1)加法:

算法思路:

计算 567 + 28

用 a, b 两个字符串存储输入。a = 567, b = 28

为了方便计算,将两个数分别 倒序 存放在 A, B 两个整数数组中。 A = [7, 6, 5], B = [8, 2]

新建整数数组 C 保存结果,整型变量 t 保存进位,初始 t = 0.

将各个位上的数字相加,求出结果对应位上的数字和进位。

例如对个位计算: A[0] + B[0] = 7 + 8 = 15, 结果个位上是 5, 进位是 1. 所以 C[0] = 5, 进位 t = 1

最后把结果数组 C 中就保存了计算倒序结果,倒序输出就是答案

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(new BufferedInputStream(System.in));
        String a = scanner.next();
        String b = scanner.next();
        int aLength = a.length() - 1;
        int bLength = b.length() - 1;

        List<Integer> list = new ArrayList<>((int)(1e6+10));

        int carry = 0;
        int max = Math.max(aLength,bLength) + 1;

        while (max --> 0 ){
            int x = aLength < 0 ? 0 : a.charAt(aLength) - '0';
            int y = bLength < 0 ? 0 : b.charAt(bLength) - '0';

            int sum = x + y + carry;
            list.add(sum % 10);
            carry = sum / 10;

            aLength--;
            bLength--;
        }

        if (carry != 0) list.add(1);

        for (int i = list.size() - 1; i >= 0; i--){
            System.out.print(list.get(i));
        }
    }
}

作者:byteflow666
链接:https://www.acwing.com/solution/content/139804/
来源:AcWing
(2)减法:

算法思路:
(模拟数从后向前减)
初始化借位t = 0
计算加法t = a - b - t 其中a, b范围为(0,9), t为借位0 or 1,同时临时用来存储减法的结果
计算结果值 (t + 10)% 10 如果t为负的,比如-1,向前借一位,(10 - 1) = 9
如果t为正的,比如1,无需向前借一位,(10 + 1) % 10 = 1
计算借位值,用于下次计算 t = 0 or 1 如果t为负的,表示需要向前借一位(正好印证前面借位), t = 1
如果t为正的,无需向前借一位,t = 0 

import java.util.Scanner;

public class Main{
    public static void main(String[] args){
        String a, b;
        Scanner sc = new Scanner(System.in);
        a = sc.next();
        b = sc.next();
        char[] A = new char[a.length()], B = new char[b.length()];
        for(int i = a.length() - 1; i >= 0; i --) A[a.length() - 1 - i] = a.charAt(i);
        for(int i = b.length() - 1; i >= 0; i --) B[b.length() - 1 - i] = b.charAt(i);       
        if(cmp(A, B)){
            String c = sub(A, B);
            System.out.println(c);
        }else{
            String c = sub(B, A);
            System.out.print("-");
            System.out.println(c);
        }
    }
    public static String sub(char[] A, char[] B){
        StringBuffer sb = new StringBuffer();
        int t = 0;
        for(int i = 0; i < A.length; i ++){
            t = A[i] - '0' - t; //注意要减去-'0'
            if(i < B.length) t -= B[i] - '0'; 
            sb.append((t + 10) % 10);
            if(t < 0) t = 1;
            else t = 0;
        }
        String s = sb.reverse().toString();
        int i = 0;
        for(; i < s.length() - 1; i ++)
            if(s.charAt(i) != '0') break;
        return s.substring(i, s.length());
        // char[] C = sb.reverse().toString().toCharArray();
        // //针对77 - 70 = 07 => 7  77 - 77 = 00 => 0
        // //利用截取,来去除开头的0, 当全为0的时候保留1位0
        // int i = 0; //记录开头位置不为0
        // for(; i < C.length - 1; i ++) 
        //     if(C[i] != '0') break; 
        // return new String(C).substring(i, C.length);
    }

    public static boolean cmp(char[] A, char[] B){
        if(A.length != B.length) return A.length > B.length;
        //相等从高位进行比较
        for(int i = A.length - 1; i >= 0; i --){
            if(A[i] != B[i]) return A[i] > B[i];
        }
        return true;

    }
}

作者:派大星的梦想
链接:https://www.acwing.com/solution/content/32440/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
(3)乘法

AcWing 793. 高精度乘法 A x b 和 A x B 的模版(大数相加、大数相乘通用模板) - AcWing 

(4)除法

思路:

数组A[]: 1  2  6
 数b      25
 模拟过程
 初始化余数r = 0
 ((r = 0) * 10 + (A[0] = 1)) / 25 = 0 ... r = 1
 ((r = 1) * 10 + (A[1] = 2)) / 25 = 0 ... r = 12
 ((r = 12) * 10 + (A[2] = 2)) / 25 = 5 ... r = 1
 A遍历完,得到商和余数

 初始化余数r = 0
 计算乘法r = r * 10 + A[i]    其中A[i]为数组中的第i个数, b为数, r用来存储当前的结果
 计算结果值               r / 10 
 计算余数,用于下次计算   r = r / 10

import java.util.Scanner;
public class Main{
    static int r;
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String a = sc.next();
        int b = sc.nextInt();
        char[] A = new char[a.length()];
        for(int i = a.length() - 1; i >= 0; i --) A[a.length() - 1 - i] = a.charAt(i);
        String res = div(A, b);
        System.out.println(res);
        System.out.println(r);
    }

    public static String div(char[] A, int b){
        StringBuffer sb = new StringBuffer();
        r = 0;
        for(int i = A.length - 1; i >= 0; i --){
            r = r * 10 + A[i] - '0';
            sb.append(r / b);
            r %= b;
        }
        String s = sb.toString();
        int i = 0;
        for(; i < s.length()- 1; i++){
            if(s.charAt(i) != '0') break;
        } 
        return s.substring(i, s.length());
    }
}

作者:派大星的梦想
链接:https://www.acwing.com/solution/content/32448/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

(6)前缀和

import java.io.IOException;
import java.util.*;
public class Main {
	 public static void main(String[] args) throws IOException{
	        Scanner in=new Scanner(System.in);
	        int n=in.nextInt();
	        int m=in.nextInt();
	        int q=in.nextInt();
	        int [][] arr=new int [n+1][m+1];
	        //输入
	        for(int i=1;i<=n;i++)
	        	for(int j=1;j<=m;j++)
	        		arr[i][j]=in.nextInt();
	        
	        //前缀和s数组
	        int [][] s=new int [n+1][m+1];
	        for(int i=1;i<=n;i++)
	        	for(int j=1;j<=m;j++)
	        		s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+arr[i][j];
	        //输出
	        while (q-- > 0) {
	            // 定位获取区间大小
	            int x1 = in.nextInt();
	            int y1 = in.nextInt();
	            int x2 = in.nextInt();
	            int y2 = in.nextInt();

	            // 计算, 结合图来理解
	            int res = s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1];
	            System.out.println(res);

	    }
	 }
}

图解如下:

(7)差分

 package 差分;

import java.io.*;

public class Main {
static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
static BufferedWriter log = new BufferedWriter(new OutputStreamWriter(System.out));
static int N = 100010;
static int[] b = new int[N];
static int[] arr = new int[N];

public static void main(String[] args) throws IOException {
    String[] s = reader.readLine().split(" ");
    int n = Integer.parseInt(s[0]);
    int m = Integer.parseInt(s[1]);

    String[] sArr = reader.readLine().split(" ");
    for (int i = 1; i <= n; i++) {
        arr[i] = Integer.parseInt(sArr[ i - 1 ]);
        b[i] = arr[i] - arr[i - 1];
    }
    while(m -- > 0){
        String[] in = reader.readLine().split(" ");
        int l = Integer.parseInt(in[0]), r = Integer.parseInt(in[1]), val = Integer.parseInt(in[2]);
        b[l] += val;
        b[r + 1] -= val;
    }

    for (int i = 1; i <= n; i++) {
        arr[i] = arr[i - 1] + b[i];
        log.write(arr[i] + " ");
    }

    reader.close();
    log.flush();
    log.close();
}
}

(8)双指针

最长不重复子序列

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {
   public static void main(String[] args) throws IOException {
	   BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	   int n=Integer.parseInt(br.readLine());
	   String[] s=br.readLine().split(" ");
	   int[] arr=new int[n];
	   for(int i=0;i<n;i++)
		   arr[i]=Integer.parseInt(s[i]);
	   int[] a=new int[100010];
	   int res=0;
	   int left=0;//左端点
	   for(int i=0;i<n;i++) {
		   a[arr[i]]++;
		   while(left<i&&a[arr[i]]>1) {
			   a[arr[left]]--;
			   left++;
		   }
		   if(res<i-left+1)res=i-left+1;
	   }
	   System.out.print(res);
   }
}

(9)二进制中1的个数

import java.util.Scanner;

public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        while(n -- != 0){
            int x = sc.nextInt();
            int res = 0;
            while(x != 0){
                x -= lowbit(x);
                res ++;
            }
            System.out.print(res + " ");
        }
    }

    public static int lowbit(int x){
        return x & -x;
    }
}

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值