算法
- 暴力解法
- 优化算法
遍历常见算法思路
遍历常见数据结构
空间和时间交换(哈希表)
预处理信息(排序)
在瓶颈处寻找答案: O(nlogn)+O(n2);O(n3)
- 背包问题
状态转移方程 - State(i-1,j,k) if w[i] > j
State(i,j,k) =
max(State(i-1,j,k), State(i-1,j-w[i],k-1)+V[i]) if w[i]<=j
int n = 130; //总重量
int m = 3; //数量限制
int[] x = {100,20,40,50}; //重量
int[] y = {380,320,360,310}; //value
private static int knap(int[] x, int[] y, int n, int m) {
int[][][]state = new int[x.length+1][n+1][m+1];
for(int k=1;k<m+1;k++){
for(int j=1;j<n+1;j++){
for(int i=1;i<x.length+1;i++){
int w = x[i-1];
int v = y[i-1];
if(w>j){
state[i][j][k] = state[i-1][j][k];
}
else{
state[i][j][k] = Math.max(state[i-1][j][k]
, state[i-1][j-w][k-1]+v);
}
}
}
}
return state[x.length][n][m];
}
2.并查集
private static void union(int a, int b) {
int a = find(a);
int b = find(b);
if(a==b)return;
if(a>b){
arr[a] = b;}
else{arr[b] = a;}
}
private static int find(int i){
while(arr[i]!=i){
i=arr[i];
}
return i;
}
3.回溯法
回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。
典型案例 - 八皇后
public class Queen {
private int[] column; //同栏是否有皇后,1表示有
private int[] rup; //右上至左下是否有皇后
private int[] lup; //左上至右下是否有皇后
private int[] queen; //解答
private int num; //解答编号
public Queen() {
column = new int[8+1];
rup = new int[(2*8)+1];
lup = new int[(2*8)+1];
for (int i = 1; i <= 8; i++)
column[i] = 0;
for (int i = 1; i <= (2*8); i++)
rup[i] = lup[i] = 0; //初始定义全部无皇后
queen = new int[8+1];
}
public void backtrack(int i) {
if (i > 8) {
showAnswer();
} else {
for (int j = 1; j <= 8; j++) {
if ((column[j] == 0) && (rup[i+j] == 0) && (lup[i-j+8] == 0)) {
//若无皇后
queen[i] = j; //设定为占用
column[j] = rup[i+j] = lup[i-j+8] = 1;
backtrack(i+1); //循环调用
column[j] = rup[i+j] = lup[i-j+8] = 0;
}
}
}
}
protected void showAnswer() {
num++;
System.out.println("\n解答" + num);
for (int y = 1; y <= 8; y++) {
for (int x = 1; x <= 8; x++) {
if(queen[y]==x) {
System.out.print("Q");
} else {
System.out.print(".");
}
}
System.out.println();
}
}
public static void main(String[] args) {
Queen queen = new Queen();
queen.backtrack(1);
}
}
4.滑动窗口
其实就是一个队列,比如例题中的 abcabcbb,进入这个队列(窗口)为 abc 满足题目要求,当再进入 a,队列变成了 abca,这时候不满足要求。所以,我们要移动这个队列!
如何移动?
我们只要把队列的左边的元素移出就行了,直到满足题目要求!
一直维持这样的队列,找出队列出现最长的长度时候,求出解!
时间复杂度:O(n)O(n)
class Solution {
public int lengthOfLongestSubstring(String s) {
if (s.length()==0) return 0;
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
int max = 0;
int left = 0;
for(int i = 0; i < s.length(); i ++){
if(map.containsKey(s.charAt(i))){
left = Math.max(left,map.get(s.charAt(i)) + 1);
}
map.put(s.charAt(i),i);
max = Math.max(max,i-left+1);
}
return max;
}
}