算法小笔记
背景(闲话 )
好久没更了,这不到年底了。想想马上2024了,干脆把之前的东西整理整理吧
向上取整技巧 $x \div y$
一般来说,刚开始都会想到两种方法:
1 res = x % y == 0 ? x / y : x / y + 1 ;
或者
实际上,第一种还行,但是稍显啰嗦;第二种容易出bug
,而且调用消耗高。
有更简单 的:
简单证一下:
假设 :
$x \div y = a \cdots b$,
那么:
$x = a \cdot y + b$,
则
$(x + y - 1 ) \div y$
$= (a \cdot y + y + b - 1 ) \div y $
$= a + (y + b - 1) \div y$
如果 $b = 0 $,
那么后半部分就是 $0$ 了;
如果 $b \geq 1 $,
也就是不能整除,$a$ 就会 $+ 1$;
二分板子
nnd, 今天每日一题有思路,知道拿二分,也肯定能过但是居然卡二分实现这儿了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 pubulic int dichotomy (int [] nums , int target) { int n = nums.length; int left = 0 , right = n - 1 ; int resLabel = -1 ; while (left <= right){ int mid = left + (right - left) / 2 ; if (nums[mid] >= target){ resLabel = mid; right = mid - 1 ; } else { left = mid + 1 ; } } return resLabel; }
我之前老想不清的是找到第一个满足条件的数,需要借助前一次查找的标记。但是实际上,在窗口移动的过程中,范围一直在缩小、寻找满足条件且最靠前的数,缩到最小(到达最优解)后下次就会不满足条件直接跳出了。
求解最短路
1. floyd
(弗洛伊德算法)
floyd
算法是把一个图里边的各个点之间的最短路都算出来,适合多源最短路问题
就是每拿到一个点,就借助这个点建立其他点之间的联系,更新其他点之间的最短路
朴素floyd
实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public int [][] floydSimplicity(int n, int [][] edges){ int [][] dis = new int [n][n]; for (int i = 0 ; i < n ; i ++){ Arrays.fill(dis[i], Integer.MAX_VALUE / 2 ); } for (int [] edge : edges){ int from = edge[0 ], to = edge[1 ], len = edge[2 ]; dis[from][to] = len; dis[to][from] = len; } for (int k = 0 ; k < n ; k ++){ dis[k][k] = 0 ; for (int i = 0 ; i < n ; i ++){ for (int j = 0 ; j < n ; j ++){ dis[i][j] = Math.min(dis[i][j], dis[i][k] + dis[k][j]); } } } return dis; }
2. dijkstra
(迪杰斯特拉算法)
dijkstra
算法是从一个点出发,不断更新此点到其他点的最短路,直到所有点都到达或者遍历完。适合单源最短路问题,但同样也可用于多源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 public int [][] dijkstraSimplicity(int n, int [][] edges){ int [][] dis = new int [n][n]; int [][] map = new int [n][n]; boolean [][] vis = new boolean [n][n]; for (int i = 0 ; i < n ; i ++){ Arrays.fill(dis[i], Integer.MAX_VALUE / 2 ); Arrays.fill(map[i], Integer.MAX_VALUE / 2 ); } for (int [] edge : edges){ int from = edge[0 ], to = edge[1 ], len = edge[2 ]; map[from][to] = len; map[from][to] = to; } for (int i = 0 ; i < n ; i ++){ dis[i][i] = 0 ; for (int j = 0 ; j < n ; j ++){ int shortPos = -1 ; for (int k = 0 ; k < n ; k ++){ if ( !vis[i][k] && (shortPos == -1 || dis[i][k] < dis[i][shortPos])){ shortPos = k; } } vis[i][shortPos] = true ; for (int k = 0 ; k < n ; k ++){ dis[i][k] = Math.min(dis[i][k], dis[i][shortPos] + map[shortPos][k]); } } } return dis; }