Leetcode常见算法框架

目录

1. 二分法

2.并查集

3. 线段树

4.单调栈

5.递归

(1)DFS

(2)BFS

6.排序:

7.滑动窗口

8. 动态规划

9.差分

10.前缀和

11.贪心

12.字典树


1. 二分法

private static int dichotomy(List<Integer> list, Integer target) {
    int left = 0, right = list.size() - 1;
    while(left <= right) {
        int middle = (left + right)/2;
        if (list.get(middle).equals(target)) {
            return middle;
        } else if (list.get(middle) > target) {
            right = middle - 1;
        } else {
            left = middle + 1;
        }
    }
    return -1;
}
   public int binarySearch(int[] nums, int target, boolean lower) {
        int left = 0, right = nums.length - 1, ans = nums.length;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (nums[mid] > target || (lower && nums[mid] >= target)) {
                right = mid - 1;
                ans = mid;
            } else {
                left = mid + 1;
            }
        }
        return ans;
    }

2.并查集

private static class UnionFind {

    private int[] parent;
    /**
     * 以 i 为根结点的子树的高度(引入了路径压缩以后该定义并不准确)
     */
    private int[] rank;
    public UnionFind(int n) {
        parent = new int[n];
        rank = new int[n];
        for (int i = 0; i < n; ++i) {
            parent[i] = i;
            rank[i] = 1;
        }
    }
    public int find(int x) {
        return parent[x] != x ? parent[x] = find(parent[x]) : x;
    }
    public void union(int x, int y) {
        int xRoot = find(x);
        int yRoot = find(y);
        if (xRoot == yRoot) {
            return;
        }
        if (rank[xRoot] == rank[yRoot]) {
            parent[xRoot] = yRoot;
            rank[yRoot]++;
        } else if (rank[xRoot] < rank[yRoot]) {
            parent[xRoot] = yRoot;
        } else {
            parent[yRoot] = xRoot;
        }
        //parent[find(x)] = find(y);
    }
}

3. 线段树

(1)建立2N长度的树:tree[i]=tree[2i]+tree[2i+1];

(2)更新:pos更新,循环左找右, 右找左,求pos/2,往前找循环更新;

(3)求和:找到左偶数位,右奇数位除2(否则累加,加减除2)

static class NumArray { //线段树
    int[] tree;
    int n;
    public NumArray(int[] nums) {
        if (nums.length > 0) {
            n = nums.length;
            tree = new int[n * 2];
            buildTree(nums);
        }
    }
    private void buildTree(int[] nums) {
        for (int i = n, j = 0;  i < 2 * n; i++,  j++)
            tree[i] = nums[j];
        for (int i = n - 1; i > 0; --i)
            tree[i] = tree[i * 2] + tree[i * 2 + 1]; //even + odd
    }
    void update(int pos, int val) {
        pos += n;
        tree[pos] = val;
        while (pos > 0) {
            int left = pos;
            int right = pos;
            if (pos % 2 == 0) {
                right = pos + 1;
            } else {
                left = pos - 1;
            }
            // parent is updated after child is updated
            tree[pos / 2] = tree[left] + tree[right];
            pos /= 2;
        }
    }
    public int sumRange(int l, int r) {
        // get leaf with value 'l'
        l += n;
        // get leaf with value 'r'
        r += n;
        int sum = 0;
        while (l <= r) {
            if ((l % 2) == 1) { //left add only is odd number
                sum += tree[l];
                l++;
            }
            if ((r % 2) == 0) { // right add only is even number
                sum += tree[r];
                r--;
            }
            l /= 2;
            r /= 2;
        }
        return sum;
    }
}

4.单调栈

private static int[] dailyTemperaturesDeque(int[] temperatures) {
    Deque<Integer> deque = new LinkedList<>();
    int[] result = new int[temperatures.length];
    deque.add(0);
    for (int i = 1; i < temperatures.length; i++) {
        while (!deque.isEmpty() && 
            temperatures[i] > temperatures[deque.getLast()]){
            int index = deque.pollLast();
            result[index] = i - index;
        }
        deque.add(i);
    }
    return result;
}

5.递归

(1)DFS

    public static void dfs(char[][] grid, int i, int j) {
        //边界,跳出,搜索到的条件
        if (i < 0 || j < 0 || i >= grid.length || j >= grid[0].length || grid[i][j] == '0') {
            return;
        }
        grid[i][j] = '0';
        dfs(grid, i + 1, j);
        dfs(grid, i - 1, j);
        dfs(grid, i, j + 1);
        dfs(grid, i, j - 1);
    }

(2)BFS

    public static int dfs(int n) {///标准bfs
        int result = 0;
        Set<Integer> queue = new HashSet<>();
        queue.add(n); 
        while (queue.size() > 0) {
            result++;
            Set<Integer> next_queue = new HashSet<>();//bfs重在分层
            for (Integer thisLevel : queue) { // 处理这层
                for (int i = 1; i * i <= thisLevel; i++) {
                    if (thisLevel.equals(i*i)) {
                        return result;
                    } else {
                        next_queue.add(thisLevel - i*i); //生成下一层
                    }
                }
            }
            queue = next_queue;
        }
        return -1;
    }

6.排序:

直接上个Comparator,实用。

    static class Room {
        public int roomId = 0;
        public Room(int id) {
            roomId = id;
        }
    }
    public static void main(String[] args) {
        List<Room> list = new ArrayList<>();
        list.add(new Room(1));
        list.add(new Room(2));
        list.add(new Room(3));
        Collections.sort(list, (x1, x2) -> { //1 - 2: 升序
            return x1.roomId - x2.roomId;
        });
        Collections.sort(list, new Comparator<Room>() {
            @Override
            public int compare(Room o1, Room o2) {
                return calculateMethod(o1, o2);
            }
        });
        list.stream().map(x -> x.roomId).forEach(System.out::print);
    }

    private static int calculateMethod(Room r1, Room r2) {
        return r2.roomId - r1.roomId; //逆序
    }

7.滑动窗口

    public int lengthOfLongestSubstring(String s) {
        if(s.length()<2) {
            return s.length();
        }
        int l=0, h=1;//常见滑动起点
        int most =0;
        while (h < s.length()) {
            String gets = s.substring(l, h);

            if(gets.contains(String.valueOf(s.charAt(h)))) {
                most = Math.max(most, gets.length());
                l = l+gets.indexOf(s.charAt(h)) + 1; // 左侧窗口滑动条件
            } else {
                most = Math.max(most, gets.length()+1);
            }
            h++; //滑动窗口常规框架
        }
        return most;
    }

8. 动态规划

    public static int coinChange(int[] coins, int amount) {
        int[] dp = new int[amount + 1];
        Arrays.fill(dp, amount +1);
        dp[0] = 0;
        for (int i = 1; i <= amount; i++) {
            for (int coin : coins) {
                if (coin <= i) {
                    dp[i] = Math.min(dp[i], dp[i-coin] + 1);//转移方程最重要
                }
            }
        }
        return dp[amount] > amount ? -1 : dp[amount];
    }

9.差分

一加,一减,然后求前缀和

        int[] years = new int[101]; //统计1950-2050的人口数量
        final int offset = 1950; //下标模拟年份,偏移值1950
        for (int[] log : logs) { 
            years[log[0] - offset]++; //一加, 一减是关键,减是为了求前缀和是加上
            years[log[1] - offset]--;
        }
        int ans = 0;
        for (int i = 1; i < years.length; i++) { //对差分数组求前缀和
            years[i] += years[i - 1];
            if (years[i] > years[ans]) ans = i;
        }
        return ans + offset;

10.前缀和

前缀和i - 前缀和j = i到j的和;

11.贪心

一般使用排序,或双指针,重思路。

12.字典树

将路径做成树状结构

13.有向无环图

费头发

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值