java 常用数据结构及算法tips

  1. TreeMap可以有序,HashMap无法有序
import java.util.Scanner;
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt(),a,b;
        //TreeMap可以有序,HashMap无法有序,以下代码->TreeMap重写Comparator的compare函数,利用key进行排序
        TreeMap<Integer,Integer> tm = new TreeMap<>(new Comparator<Integer>(){
            public int compare(Integer a, Integer b){
                return a-b;
            }
        });
        while(n-->0){
            a = in.nextInt();
            b = in.nextInt();
            if (tm.containsKey(a)){
                tm.put(a,tm.get(a)+b);
            }else{
                tm.put(a,b);
            }
        }
        //map遍历方式:lambda:推荐
        tm.forEach((key,value)->{
            System.out.println(key+" "+value);
        });
    }
}
  1. 遍历map

1.8以下推荐写法,感觉挺方便

for(Map.Entry<Integer,String> entry:map.entrySet()){
    System.out.println(entry.getKey());
    System.out.println(entry.getValue());
};
Iterator<Map.Entry<String,String>> iterator=map.entrySet().iterator();
while(iterator.hasNext()){
    Map.Entry<String, String> entry=iterator.next();
    if(entry.getKey().equals("2")){
        iterator.remove();
    }
}

lambda表达式,注意{}中不能赋值普通变量,具体原因还未探知

map.forEach((key,value)->{
      System.out.println(key);
      System.out.println(value);
  });
  1. 并查集

常见/(quick)模板

public class Union_find {
    private int[] root = null;

    public Union_find(int row, int col) {
        root = new int[row * col];

        for (int i = 0; i < row * col; i++) {//构建索引对照列表
            root[i] = i;
        }
    }

    //Find the root of x
    public int Find(int x) {//递归寻找最远祖先
        if (x == root[x]) {
            return root[x];
        }
        /*1*/return Find(root[x]);
        
        // /*2*/以下是find quick方法,找到的同时,把自己的祖先值也变了,替换上述的return语句
        //root[x] = Find(root[x]);
        // return roox[x];
    }

    //Union two elements into one root
    public void Union(int x, int y) {
        int rootx = Find(x);
        int rooty = Find(y);
        if (rooty != rootx){//如果x和y不是同一个祖先,就将其中一个element的祖先设为另一个,后面在递归中也能找到
            root[rootx] = rooty;
        }
    }
}

union find 权重rank

public class Union_find_rank {
    private int[] root = null;
    private int[] rank = null;

    public Union_find_rank(int row, int col) {
        root = new int[row * col];
        rank = new int[row * col];
        for (int i = 0; i < row * col; i++) {//构建索引对照列表
            root[i] = i;
            rank[i] = 0;
        }
    }

    //Find the root of x
    public int Find(int x) {//递归寻找最远祖先
        if (x == root[x]) {
            return root[x];
        }
        return Find(root[x]);

        // 以下是find quick方法,找到的同时,把自己的祖先值也变了,替换上述的return语句
        //root[x] = Find(root[x]);
        // return roox[x];
    }

    //Union two elements into one root
    public void Union(int x, int y) {
        int rootx = Find(x);
        int rooty = Find(y);
        if (rooty != rootx){//如果x和y不是同一个祖先,就将其中一个element的祖先设为另一个,后面在递归中也能找到
            if (rank[rootx] > rank[rooty]){//如果x子树比y子树高,就将y放到x下
                root[rooty] = rootx;
            } else if (rank[rootx] < rank[rooty]) {//如果x子树比y子树矮,就将x放到y下
                root[rootx] = rooty;
            }else {//如果两个并查集树高度相等
                root[rooty] = rootx;
                rank[rootx] += 1;
            }
        }
    }
}

  1. kmp,needle是否在haystack中,在则返回第一个下标,否则返回-1
public static int strStr(String haystack, String needle) {
        int[] prefix = new int[needle.length()];//前缀表,最长相等前后缀
        getPrefix(prefix, needle);
        System.out.println(Arrays.toString(prefix));
        int i = 0, j = 0;
        while (i < haystack.length()) {
            if (haystack.charAt(i) == needle.charAt(j)) {
                j++;
                i++;
            } else {
                while (haystack.charAt(i) != needle.charAt(j) && j != 0) {//如果一直不匹配,则j要一直往前
                    j = prefix[j - 1];
                }
                if (haystack.charAt(i) == needle.charAt(j)) {
                    j++;
                }
                i++;

            }
            if (j == needle.length()) {
                return i - needle.length();
            }
        }


        return -1;
    }

    private static void getPrefix(int[] prefix, String needle) {//求前缀表
        Arrays.fill(prefix, 0);
        for (int index = 1; index < needle.length(); index++) {
//            for (int i = 0, j = index; i < index && j > 0; i++, j--) {
//                if (needle.substring(0, i + 1).equals(needle.substring(j, index + 1))) {
//                    prefix[index] = Math.max(prefix[index], i + 1);
//                }
//            }
            for (int i = index, j = 1; i >= 0 && j <= index; i--, j++) {//i是前缀尾,j是后缀头
                if (needle.substring(0, i).equals(needle.substring(j, index + 1))) {
                    prefix[index] = i;
                    break;
                }
            }
        }
    }
  1. 差分数组
    (以leetcode1109,航班预定题目为例)
class Solution {
    public int[] corpFlightBookings(int[][] bookings, int n) {
        int[] seats = new int[n];
        Arrays.fill(seats,0);
        Difference dd = new Difference(seats);
        for (int i=0;i<bookings.length;i++){
            dd.increment(bookings[i][0]-1,bookings[i][1]-1,bookings[i][2]);
        }
        return dd.result();
    }

    class Difference{
        private int[] difference;

        public Difference(int[] nums) {
            difference = new int[nums.length];
            System.arraycopy(nums, 0, this.difference, 0, nums.length);
        }

        public void increment(int i,int j,int val){ //对差分数组的i和j+1位置修改,即可修改原数组i到j之间的所有值
            difference[i] += val;
            if (j+1 < difference.length){
                difference[j+1] -= val;
            }
        }

        public int[] result(){//从差分数组得到原始数组(在更新的原始数组上计算)
            int[] result = new int[difference.length];
            result[0] = difference[0];
            for (int i=1;i<difference.length;i++){
                result[i] = difference[i] + result[i-1];
            }
            return result;
        }

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值