八股文—算法框架

排序

快速排序

arr [ n ]
以arr[0]为基准,将小于arr[0]的放在arr[0]的左边,将大于arr[0]的放在arr[0]右边
i 从 1~n-1
j从 n-1~1
while(true){
找到第一个 arr[i]>arr[0]
找到第一个 arr[j]<arr[0]
i<=j 交换 i,j
}

归并排序

二叉树

二叉树的遍历具有框架性
前序、中序、后续遍历等就像深度优先遍历
层次遍历就像广度优先遍历

前序遍历

void traverse(TreeNode root){
	if(root==null){
		return ;
	}
	// do something
	
	traverse(root.left);
	traverse(root.right);
}

中序遍历

void traverse(TreeNode root){
	if(root==null){
		return ;
	}
	traverse(root.left);
	// do something
	
	traverse(root.right);
}

后续遍历

void traverse(TreeNode root){
	if(root==null){
		return ;
	}
	traverse(root.left);
	traverse(root.right);
	// do something
	
}

层次遍历

不区分层数

Queue<TreeNode> queue = new LinkedList<>();
// root入队
queue.offer(root);
while(!queue.isEmpty()){
	// root出队
    TreeNode current = queue.poll();
    // 当前层  do something
    System.out.println(current.val);
    // 加入下一层元素
    queue.offer(current.left);
    queue.offer(current.right);
}

可区分层数

Queue<TreeNode> queue = new LinkedList<>();
queue.offer(pRoot);
while(!queue.isEmpty()){
    // 当前层元素个数
    int size = queue.size();
    while(size>0){
    	// 便利当前层每一个元素
        TreeNode node = queue.poll();
        size --;
		// do something
		
        queue.offer(node.left);
        queue.offer(node.right);
    }
}

动态规划—dp数组

DP三步骤:
1)确定状态转移方程,如:dp[i]与dp[i-1]之间关系
2)确定初始状态,如:dp[0] = 0,dp[1] = 1
3)遍历并且构造出dp数组和对应下标的值
4)根据dp数组得到最终的答案

一维dp

二维dp

0-1背包问题 物品i,价值v[i],重量w[i],能背的重量j
dp[i][j] 前i个物品下,重量j的约束下能达到的最大价值
dp[i][j] = max()

最短路径

Dijkstra算法

掌握一个思路,dp[i] 表示起始节点0到终点i的最短路径
每次找到dp[i]中未访问过的最小值,将之标记为已经访问
与dp[i] 连通的节点 j 算出 dp[j] = Math.min(dp[j], dp[i]+graph[i][j])
直到再也找不到dp[i] 中未访问过的最小值,就全部遍历结束,能够得到点0到1~n-1所有节点的最短路径dp[i]

public int findShortestPath (int n, int m, int[][] graph) {
	int [] visited = new int[n];
    int [][] myGraph = new int[n][n];
    int[] dp = new int[n];

    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            myGraph[i][j] = Integer.MAX_VALUE;
        }
        myGraph[i][i] = 0;
        dp[i] = Integer.MAX_VALUE;
    }

    for(int i=0;i<graph.length;i++){
        myGraph[graph[i][0]-1][graph[i][1]-1] = Math.min(graph[i][2],myGraph[graph[i][0]-1][graph[i][1]-1]);
        myGraph[graph[i][1]-1][graph[i][0]-1] = Math.min(graph[i][2],myGraph[graph[i][1]-1][graph[i][0]-1]);
    }
    
    dp[0] = 0;
    while(true){
        int index = findMinIndex(visited,dp);
        if(index == -1){
            break;
        }
        visited[index] = 1;
        for(int j=0;j<n;j++){
            if( myGraph[index][j] != Integer.MAX_VALUE ){
                dp[j] =  Math.min(dp[index] + myGraph[index][j],dp[j]);
            }
        }
        
    }

    if(dp[n-1]!=Integer.MAX_VALUE){
        return dp[n-1];
    }else{
        return -1;
    }

}

int findMinIndex(int [] visited,int [] dp){
    int len = dp.length;
    int min = Integer.MAX_VALUE;
    int minIndex = -1;
    for(int i=0;i<len;i++){
        if(dp[i] < min && visited[i]==0){
            min = dp[i];
            minIndex = i;
        }
    }
    return minIndex;
}

并查集

树可以看成是一个连通且 无环 的 无向 图。

给定往一棵 n 个节点 (节点值 1~n) 的树中添加一条边后的图。添加的边的两个顶点包含在 1 到 n 中间,且这条附加的边不属于树中已存在的边。图的信息记录于长度为 n 的二维数组 edges ,edges[i] = [ai, bi] 表示图中在 ai 和 bi 之间存在一条边。

请找出一条可以删去的边,删除后可使得剩余部分是一个有着 n 个节点的树。如果有多个答案,则返回数组 edges 中最后出现的那个。

class Solution {
    public int[] findRedundantConnection(int[][] edges) {
        int n = edges.length;
        int[] parent = new int[n + 1];
        // 初始化并查集数组 parent[i] = i
        for (int i = 1; i <= n; i++) {
            parent[i] = i;
        }
        for (int i = 0; i < n; i++) {
            int[] edge = edges[i];
            int node1 = edge[0], node2 = edge[1];
            if (find(parent, node1) != find(parent, node2)) {
                union(parent, node1, node2);
            } else {
            	// 当发现边对应的两个顶点已经在同一个集合了,再次union的话,会形成环,因此去掉这条边
                return edge;
            }
        }
        return new int[0];
    }
	
	// parent[index1的root点] = index2的root点
    public void union(int[] parent, int index1, int index2) {
        parent[find(parent, index1)] = find(parent, index2);
    }
    
	// 查询节点index的root点
    public int find(int[] parent, int index) {
        if (parent[index] != index) {
            parent[index] = find(parent, parent[index]);
        }
        return parent[index];
    }
}
  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值