数据结构的整理

一、二叉树

1、二叉树的递归套路:

  1. 假设以X节点为头,假设可以像X左树和X右树要任何信息。
  2. 在上一步的假设下,讨论以X为节点的树,得到答案的可能性。
  3. 列出所有的可能性后,确定到底需要向左树和右树要什么样的信息。
  4. 把左树信息和右树信息求全集,就是任何一颗子树都需要返回的信息S.
  5. 递归函数都返回S,每一颗子树都这么要求
  6. 写代码,在代码中考虑如何把左树的信息和右树的信息整合出整颗树的信息。

2、二叉树按层遍历:

  • 借助队列来实现二叉树按层遍历
//定义一个二叉树
public static class Node{
	public int value;
	public Node left;
	public Node right;
	public Node(int value){
	this.value=value;
}
}
public static void BianLi(Node head){
	if(head==null){
	return}
	Queue<Node> queue=new LinkList<>();
	queue.add(head);
	while(!queue.isEmpty){
	Node cur=queue.poll;
	System.out.println(cur.value);
	if(cur.left != null){
	queue.add(cur.left);
	}
	if(cur.right != null){
	queue.add(cur.right);
	}
}
}

3、二叉树先序遍历

public static class Node{
    public int value;
    public Node left;
    public Node right;
    public Node(int value){
		this.value=value;
}
}
public static void pre(Node head){
	if(head == null){
	return;
	}
	System.out.println(head.value);
	pre(head.left);
	pre(head.right);
}
public static void pre2(head Node){
	if(head==null){
	return;
}
	Stack<Node> stack=new Stack<>();
	stack.add(head)
	while(!stack.isEmpty(){
	Node cur=stack.pop();
	if(cur.right != null){
		stack.push(cur.right);
	}
	if(cur.right != null){
		stack.push(cur.left);
}
}
}

3、二叉树的中序遍历

public static class Node{
	public int value;
	public Node left;
	public Node right;
	public Node(int value){
		this.value=value;
	}
}
public static void in(Node head){
	if(head ==null){
		return;
	}
	in(head.left);
	System.out.println(head.value);
	in(head.right);
}
public static void in2(Node head){
	if(head==null){
		return;
	}
	Stack<Node> stack=new Stack();
	while(head != null || !stack.isEmpty()){
		if(head!= null){
		stack.push(head);
		head=head.left;
	}else{
		stack.pop();
		head=head.right;
	}
	}
	
]

4、二叉树的后序遍历

public static class Node{
	public int value;
	public Node left;
	public Node right;
	public Node(int value){
		this.value=this.value;
	}
	}
public static void pos(Node head){
	if(head==null){
		return;
	}	
	pos(head.left);
	pos(head.right);
	System.out.println(head.value);
	}
public static void pos1(Node head){
		
}

5、递归找到最大的子树是搜索二叉树

完全二叉树出现的情况:
		1、左树是满的,右树是满的,左高==右高
		2、左是完全,右树是满的,左高==右高+1
		3、左树是满的,右树是满的,左高==右高+1
		4、左树是满的,右树是完全,左高==右高
package com.study.code_4;

import java.util.LinkedList;

public class isBST {
//定义一个二叉树节点
    public static class Node{
        private int value;
        private Node left;
        private Node right;

        public Node(int value) {
            this.value = value;
        }
    }
    public static boolean isCBT1(Node head) {
        if (head == null) {
            return true;
        }
        LinkedList<Node> queue = new LinkedList<>();
        // 是否遇到过左右两个孩子不双全的节点
        boolean leaf = false;
        Node l = null;
        Node r = null;
        queue.add(head);
        while (!queue.isEmpty()) {
            head = queue.poll();
            l = head.left;
            r = head.right;
            if (
                // 如果遇到了不双全的节点之后,又发现当前节点不是叶节点
                    (leaf && (l != null || r != null)) || (l == null && r != null)

            ) {
                return false;
            }
            if (l != null) {
                queue.add(l);
            }
            if (r != null) {
                queue.add(r);
            }
            if (l == null || r == null) {
                leaf = true;
            }
        }
        return true;
    }

    public static boolean isCBT2(Node head){
        return process(head).isCST;
    }
    public static class Info{
        private boolean isFull;
        private boolean isCST;
        private int height;

        public Info(boolean isFull, boolean isCST, int height) {
            this.isFull = isFull;
            this.isCST = isCST;
            this.height = height;
        }
    }
    public static Info process(Node head){
        if (head==null){
            return new Info(true,true,0);
        }
        Info leftInfo=process(head.left);
        Info rightInfo=process(head.right);
        int height=Math.max(rightInfo.height,leftInfo.height)+1;
        boolean isfull=leftInfo.isFull && rightInfo.isFull && leftInfo.height==rightInfo.height;
        boolean isCBT=false;
        if (leftInfo.isFull && rightInfo.isFull && leftInfo.height==rightInfo.height){
            isCBT=true;
        }
        if (leftInfo.isCST && rightInfo.isFull && leftInfo.height==rightInfo.height+1){
            isCBT=true;
        }
        if (leftInfo.isFull && rightInfo.isFull && leftInfo.height==rightInfo.height+1){
            isCBT=true;
        }
        if (leftInfo.isFull && rightInfo.isCST && leftInfo.height==rightInfo.height){
            isCBT=true;
        }
        return new Info(isfull,isCBT,height);
    }
    // for test
    public static Node generateRandomBST(int maxLevel, int maxValue) {
        return generate(1, maxLevel, maxValue);
    }

    // for test
    public static Node generate(int level, int maxLevel, int maxValue) {
        if (level > maxLevel || Math.random() < 0.5) {
            return null;
        }
        Node head = new Node((int) (Math.random() * maxValue));
        head.left = generate(level + 1, maxLevel, maxValue);
        head.right = generate(level + 1, maxLevel, maxValue);
        return head;
    }

    public static void main(String[] args) {
        int maxLevel = 5;
        int maxValue = 100;
        int testTimes = 1000000;
        for (int i = 0; i < testTimes; i++) {
            Node head = generateRandomBST(maxLevel, maxValue);
            if (isCBT1(head) != isCBT2(head)) {
                System.out.println("Oops!");
            }
        }
        System.out.println("finish!");
    }

}

6、返回a、b节点最低公共祖先

可能出现的情况:
	与x无关(x 不是最低汇聚点):
			左树有答案
			右树有答案
			a,b不全
	x本身就是a节点,左树和右树发现b
	x本身就是b节点,左树和右树发现了a
package com.study.code_4;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

public class LowestAncestor {
    public static class Node{
        private int value;
        private Node left;
        private Node right;

        public Node(int value) {
            this.value = value;
        }
    }

    public static Node lowestAncestor1(Node head, Node o1, Node o2) {
        if (head == null) {
            return null;
        }
        // key的父节点是value
        HashMap<Node, Node> parentMap = new HashMap<>();
        parentMap.put(head, null);
        fillParentMap(head, parentMap);
        HashSet<Node> o1Set = new HashSet<>();
        Node cur = o1;
        o1Set.add(cur);
        while (parentMap.get(cur) != null) {
            cur = parentMap.get(cur);
            o1Set.add(cur);
        }
        cur = o2;
        while (!o1Set.contains(cur)) {
            cur = parentMap.get(cur);
        }
        return cur;
    }

    public static void fillParentMap(Node head, HashMap<Node, Node> parentMap) {
        if (head.left != null) {
            parentMap.put(head.left, head);
            fillParentMap(head.left, parentMap);
        }
        if (head.right != null) {
            parentMap.put(head.right, head);
            fillParentMap(head.right, parentMap);
        }
    }

    public static Node lowestAncestor2(Node head,Node a ,Node b){
        return process(head, a, b).ans;
    }
    public static class Info{
        private boolean findA;
        private  boolean findB;
        private Node ans;

        public Info(boolean findA, boolean findB, Node ans) {
            this.findA = findA;
            this.findB = findB;
            this.ans = ans;
        }
    }
    public static Info process(Node x,Node a,Node b){
        if (x==null){
            return new Info(false,false,null);
        }
        Info leftInfo=process(x.left,a,b);
        Info rightInfo=process(x.right,a,b);
        boolean findA=(x==a) ||  leftInfo.findA || rightInfo.findA;
        boolean findB=(x==b) || leftInfo.findB || rightInfo.findB;
        Node ans=null;
        if (leftInfo.ans !=null){
            ans=leftInfo.ans;
        }else if (rightInfo.ans != null){
            ans=rightInfo.ans;
        }else{
            if (findA && findB){
                ans =x;
            }
        }
        return new Info(findA,findB,ans);
    }
    // for test
    public static Node generateRandomBST(int maxLevel, int maxValue) {
        return generate(1, maxLevel, maxValue);
    }

    // for test
    public static Node generate(int level, int maxLevel, int maxValue) {
        if (level > maxLevel || Math.random() < 0.5) {
            return null;
        }
        Node head = new Node((int) (Math.random() * maxValue));
        head.left = generate(level + 1, maxLevel, maxValue);
        head.right = generate(level + 1, maxLevel, maxValue);
        return head;
    }

    // for test
    public static Node pickRandomOne(Node head) {
        if (head == null) {
            return null;
        }
        ArrayList<Node> arr = new ArrayList<>();
        fillPrelist(head, arr);
        int randomIndex = (int) (Math.random() * arr.size());
        return arr.get(randomIndex);
    }

    // for test
    public static void fillPrelist(Node head, ArrayList<Node> arr) {
        if (head == null) {
            return;
        }
        arr.add(head);
        fillPrelist(head.left, arr);
        fillPrelist(head.right, arr);
    }

    public static void main(String[] args) {
        int maxLevel = 4;
        int maxValue = 100;
        int testTimes = 1000000;
        for (int i = 0; i < testTimes; i++) {
            Node head = generateRandomBST(maxLevel, maxValue);
            Node o1 = pickRandomOne(head);
            Node o2 = pickRandomOne(head);
            if (lowestAncestor1(head, o1, o2) != lowestAncestor2(head, o1, o2)) {
                System.out.println("Oops!");
            }
        }
        System.out.println("finish!");
    }

}

7、多叉树

   多叉树的原则:
   		1、选节点
   		2、直接上下级不能一起请
   		3、选出最大max值
package com.study.code_4;

import java.util.ArrayList;
import java.util.List;

public class MaxHappy {
    public static class Employee{
        private int happy;
        private List<Employee> nexts;

        public Employee(int happy) {
            this.happy = happy;
            nexts =  new ArrayList<>();
        }
    }
    public static int maxHappy1(Employee boss) {
        if (boss == null) {
            return 0;
        }
        return process1(boss, false);
    }

    // 当前来到的节点叫cur,
    // up表示cur的上级是否来,
    // 该函数含义:
    // 如果up为true,表示在cur上级已经确定来,的情况下,cur整棵树能够提供最大的快乐值是多少?
    // 如果up为false,表示在cur上级已经确定不来,的情况下,cur整棵树能够提供最大的快乐值是多少?
    public static int process1(Employee cur, boolean up) {
        if (up) { // 如果cur的上级来的话,cur没得选,只能不来
            int ans = 0;
            for (Employee next : cur.nexts) {
                ans += process1(next, false);
            }
            return ans;
        } else { // 如果cur的上级不来的话,cur可以选,可以来也可以不来
            int p1 = cur.happy;
            int p2 = 0;
            for (Employee next : cur.nexts) {
                p1 += process1(next, true);
                p2 += process1(next, false);
            }
            return Math.max(p1, p2);
        }
    }

    public static int maxHappy2(Employee x){
        Info result=process(x);
        return Math.max(result.yes,result.no);
    }
    public static class Info{
        private int no;
        private int yes;

        public Info(int no, int yes) {
            this.no = no;
            this.yes = yes;
        }
    }
    public static Info process(Employee x){
        if (x==null){
            return new Info(0,0);
        }
        int no=0;
        int yes=x.happy;
        for (Employee next:x.nexts){
            Info nextInfo=process(next);
            no+=Math.max(nextInfo.yes,nextInfo.no);
            yes+=nextInfo.yes;
        }
        return new Info(yes,no);
    }
}

二、贪心算法

	1、贪心算法是最自然的智慧算法
	2、用一种局部最功利的标准,总是做出在当前看来最好的选择。
	3、难点在于证明局部最功利的标准可以得到全局最优解。
	4、对于贪心算法的学习主要以增加阅历和经验为主。

1、会议室问题

package com.study.code_05;

import java.util.Arrays;
import java.util.Comparator;

public class BestAgree {
    public static class Program{
        private int start;
        private int end;

        public Program(int start, int end) {
            this.start = start;
            this.end = end;
        }
    }
    public static class ProgramComparator implements Comparator<Program>{

        @Override
        public int compare(Program o1, Program o2) {
            return o1.end-o2.end;
        }
    }
    public static int bestArrange2(Program[] programs) {
        Arrays.sort(programs,new ProgramComparator());
        int timeLine=0;
        int result=0;
        for (int i = 0; i <programs.length ; i++) {
            if (timeLine<=programs[i].start){
                result++;
                timeLine=programs[i].end;
            }

        }
        return result;

    }
}

2、用贪心算法解决输入一个数组返回金条分割的最小代价

利用小根堆

package com.study.code_05;

import java.util.PriorityQueue;

public class LessMoneySplitGold {
    public static int lessMoney2(int[] arr){
        PriorityQueue<Integer> pq=new PriorityQueue<>();

        for (int i = 0; i <arr.length ; i++) {
            pq.add(arr[i]);
        }
        int cur=0;
        int sum=0;
        while (pq.size()>1){
            cur=pq.poll()+pq.poll();
            sum+=cur;
            pq.add(cur);
        }
        return sum;
    }
}

3、给定字符串str,返回点亮str中所有点亮的位置至少需要几盏灯。

str中全是x和. 需要把字符串中全部的.给点亮,i位置的.可一照亮i+1,i-1位置的.

public static int light(String str){
	if(str==null){
		return 0;
}
	int light=0;
	int len=stri.length
	int i=0;
	while(i<len){
		if(str[i]=="x"){
			i+=1;
		}else{
			light++;
			if(i+1==len){
				break;
			}
			if(str[i+1]=="x"){
			i+=2;
			}else {
			i+=3;
			}
		}
}
		return light;
}

三、并查集算法

1、并查集code

package com.study.code_05;

import java.util.HashMap;
import java.util.List;
import java.util.Stack;

public class UnitionFind {
    public static class Node<V>{
        private V value;

        public Node(V value) {
            this.value = value;
        }

        }
    public static class UnidFind<V>{
        public HashMap<V,Node<V>> nodes;
        public HashMap<Node<V>,Node<V>> parentMap;
        public HashMap<Node<V>,Integer> sizeMap;

        public UnidFind(List<V> values) {
            nodes = new HashMap<>();
            parentMap =new HashMap<>();
            sizeMap = new HashMap<>();
            for (V cur:values){
                Node<V> node = new Node<>(cur);
                nodes.put(cur,node);
                parentMap.put(node,node);
                sizeMap.put(node,1);
            }
        }
        //给一个节点,返回到最上面的节点然后返回
        public  Node<V> findFather(Node<V> cur){
            Stack<Node<V>> path=new Stack<>();
            while (cur != parentMap.get(cur)){
                path.add(cur);
                cur=parentMap.get(cur);
            }
            while (!path.isEmpty()){
                parentMap.put(path.pop(),cur);
            }
            return cur;
        }
        public boolean isSameSet(V a,V b){
            return findFather(nodes.get(a))==findFather(nodes.get(b));
        }
        public void unition(V a,V b){
            Node<V> pheada=findFather(nodes.get(a));
            Node<V> pheadb=findFather(nodes.get(b));
            if (pheada != pheadb){
                int aSetSize=sizeMap.get(pheada);
                int bSetSize=sizeMap.get(pheadb);
                Node<V> big=aSetSize>bSetSize?pheada:pheadb;
                Node<V> small=big==pheada?pheadb:pheada;
                parentMap.put(small,big);
                sizeMap.put(big,aSetSize+bSetSize);
                sizeMap.remove(small);
            }
        }
        public int sets(){
            return sizeMap.size();
        }
    }
}

2、有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。

省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/number-of-provinces
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

public static class findCircleNum{
		public static int findCircleNum(int[][] M){
			int N=M.length;
			UnitionFind un=new UnitionFind(N);
			for(int i=0;i<N;i++){
				for(int j=i+1;j<N;j++){
					if(M[i][j]==1){
						un.unition(i,j);
					}
				}
			}
			return un.sets();
			
}
		public static class UnitionFind{
			// 辅助结构
			private int[] help;
			// parent[i] = k : i的父亲是k
			private int[] parent;
			// size[i] = k : 如果i是代表节点,size[i]才有意义,否则无意义
		// i所在的集合大小是多少
			private int[] size;
			//一共多少个集合
			private int sets;
			
			public UnitiopnFind(int N){
				help=new int[N];
				parent=new int[N];
				size=new int[N];
				sets=N;
				for(int i ;i <N;i++){
					parent[i]=i;
					size[i]=1;
				}

				public static find(int i){
					int hi=0;
					while(i != parent[i]){
						help[hi++]==i;
						i=parent[i];
						}
					for(hi--;hi>0;hi--){
						parent[help[hi]]=i;
					}
					return i;
				}
				 public static void unition(int i,int j){
						int findi=find(i);
						int findj=find(j);
						while(findi != findj){
							if(size[findj]>size[findi]){
								parent[findi]=findj;
								size[findi] +=size[findj];
							}else{
								parent[findj]=findi;
								size[findj] +=size[findi];
							}
							sets--;
						}
						
				}
				public int sets(){
					return sets;
				}
				

		}
}


}

3、并集查询

题目链接:https://leetcode.com/problems/number-of-islands-ii/
时间复杂度 O(m*n)+O(k)

public satic class NumberOfIslands{

		public static List<Integer> numberofIsLands(int m,int n,int[][] postions){
			UnitionFind un=new UnitionFind(m,n);
			List<Integer> ans=new ArrayList<>();
			for(int[] postion:postions){
				ans.add(un.connect(ponstion[0],ponstion[1]));
			}
			return ans;
			
		}
		public static UnitionFind{
			private int[] parent;
			private int[] help;
			private int[] size;
			private int col;
			private int row;
			private int sets;
			public UnitionFind(int r,int c){
				int col=c;
				int row=r;
				int len=col*row;
				parent=new int[len];
				help=new int[len];
				size=new size[len];
				sets=0;
				
			}
			public int index(int r,int c){
				return r*col+c;
			}
			public int find(int i){
				int hi=0;
				while(i != parent[i]){
					help[hi++]=i;
					i=parent[i];
				}
				for(hi--;hi>0;hi--){
					parent[help[hi]]=i;
				}
				return i;
			}
			public void unition(int r1,int c1,int r2,int c2){
				if(r1<0 || r1==row || c1<0 || c1==col || r2<0 || r2==row || c2<0 || c2==col){
					return;
				}
				int i1=index(r1,c1);
				int i2=index(r2,c2);
				if(size[i1]==0 || size[i2]==0){
					return;
				}
				int find1=find(i1);
				int find2=find(i2);
				if(find1 != find1){
					if(size(find1)>size(find2))){
						parent[find2]=find1;
						size[find1]+=size[find2];
					}else{
						parent[find1]=find2;
						size[find2]+=size[find1];
					}
					sets--;
				}
				
			}
		public int connect(int r,int c){
			int i=index(r,c);
			if(size[i]==0){
			parent[i]=i;
			size[i]=1;
			sets++;
			unition(r-1,c,r,c);
			unition(r,c,r+1,c);
			unition(r,c-1,r,c);
			unition(r,c,r,c+1);
		}
		return sets;
		}
		}
	
}

解2:

// 课上讲的如果m*n比较大,会经历很重的初始化,而k比较小,怎么优化的方法
	public static List<Integer> numIslands22(int m, int n, int[][] positions) {
		UnionFind2 uf = new UnionFind2();
		List<Integer> ans = new ArrayList<>();
		for (int[] position : positions) {
			ans.add(uf.connect(position[0], position[1]));
		}
		return ans;
	}

	public static class UnionFind2 {
		private HashMap<String, String> parent;
		private HashMap<String, Integer> size;
		private ArrayList<String> help;
		private int sets;

		public UnionFind2() {
			parent = new HashMap<>();
			size = new HashMap<>();
			help = new ArrayList<>();
			sets = 0;
		}

		private String find(String cur) {
			while (!cur.equals(parent.get(cur))) {
				help.add(cur);
				cur = parent.get(cur);
			}
			for (String str : help) {
				parent.put(str, cur);
			}
			help.clear();
			return cur;
		}

		private void union(String s1, String s2) {
			if (parent.containsKey(s1) && parent.containsKey(s2)) {
				String f1 = find(s1);
				String f2 = find(s2);
				if (!f1.equals(f2)) {
					int size1 = size.get(f1);
					int size2 = size.get(f2);
					String big = size1 >= size2 ? f1 : f2;
					String small = big == f1 ? f2 : f1;
					parent.put(small, big);
					size.put(big, size1 + size2);
					sets--;
				}
			}
		}

		public int connect(int r, int c) {
			String key = String.valueOf(r) + "_" + String.valueOf(c);
			if (!parent.containsKey(key)) {
				parent.put(key, key);
				size.put(key, 1);
				sets++;
				String up = String.valueOf(r - 1) + "_" + String.valueOf(c);
				String down = String.valueOf(r + 1) + "_" + String.valueOf(c);
				String left = String.valueOf(r) + "_" + String.valueOf(c - 1);
				String right = String.valueOf(r) + "_" + String.valueOf(c + 1);
				union(up, key);
				union(down, key);
				union(left, key);
				union(right, key);
			}
			return sets;
		}

四、图

1、定义点的结构

public class Node{
	private int value;
	private int in;
	private int out;
	private ArrayList<Node> nexts;
	private ArrayList<Edge> edges;
	public Node(int value){
		this.value=value;
		this.in=0;
		this.out=0;
		nexts=new ArrayList<>();
		edges=new ArrayList<>();
	}
}

public class Edge{
	private int weight;
	private Node from;
	private Node to;
	public Edge(int weight,Node from ,Node to){
		this.weight=weight;
		this.from=from;
		this.to=to;
	}
}
public class Graph{
	public HashMap<Integer,Node> nodes;
	public HashSet<Edge> edges;
	public Graph(){
		nodes=new HashMap<>();
		edges=new HashSet<>();
	} 
}
图:
	1、由点的集合和边的集构成。
	2、虽然存在有向图和无向图的概念,但实际上都可以用有向图来表达。
	3、边上可能带权值。

2、从节点出发进行宽度优先遍历

public static void bfs(Node start){
	if(start==null){
		return;
	}
	Queue<Node> queue=new LinkList<>();
	HashSet<Node> set=new HashSet<>();
	queue.add(start);
	set.add(start);
	while(!queue.isEmpty){
		Node curs=queue.poll();
		System.out.println(curs.value);
		for(Node cur:curs.nexts){
			if(!set.container(cur)){
				queue.add(cur);
				set.add(cur);
			}
		}
	}
}

4、深度遍历

public static void dfs(Node start){
        if (start==null){
            return;
        }
        Stack<Node> stack=new Stack<>();
        HashSet<Node> hashSet=new HashSet<>();
        stack.add(start);
        hashSet.add(start);
        System.out.println(start.value);
        while (!stack.isEmpty()){
            Node curs=stack.pop();
            for (Node cur:curs.nexts){
                if (!hashSet.contains(cur)){
                    stack.push(curs);
                    stack.push(cur);
                    hashSet.add(cur);
                    System.out.println(cur.value);
                    break;
                }
            }
        }
    }

5、图的拓扑排序算法

思路:借助队列和hashMap
			1、将所有节点的入度都放到map中,
			2、将所有入度为0的节点都放在队列中
			3、然后从队列中弹出,加入列表里。
public static List<Node> sortGraph(Graph graph){
	HashMap<Node,Integer> hashmap=new HashMap<>();
	Queue<Node> queue=new LinkList<>();
	for(Node node:graph.nodes.values){
		hashmap.put(node,node.in);
		if(node.in==0){
			queue.add(node);
		}
	}
	List<Node> result=new ArrayList<>();
	while(!queue.isEmpty){
		Node cur=queue.poll();
		result.add(cur);
		for(Node next:cur.nexts){
			hashMap.put(next,next.in-1);
			if(hashmap.get(next)==0){
				queue.add(next);
			}
		}
	}
	return result;
}

6、最小生成树算法

1、可以从任意节点出发来寻找最小生成树。
2、某个点被加入到被选取的点中后,解锁这个点出发的所有新的边。
3、在所有解锁的边中选最小的边,然后看看这个边会不会形成环
4、如果会,不要当前边,继续靠察剩下解锁的边中,最小的边。
5、如果不会,要当前边,将该边的指向点加入到被选取的点中。
6、当所有点都被选取,最小生成树就得到了。
public static class MyCompator implements Comparator<Edge>{


        @Override
        public int compare(Edge o1, Edge o2) {
            return o1.weight-o2.weight;
        }
    }
    public static Set<Edge> prim(Graph graph){
        // 解锁的边进入小根堆
        PriorityQueue<Edge> priorityQueue=new PriorityQueue<>(new MyCompator());
        // 解锁的边进入小根堆
        HashSet<Node> hashSet=new HashSet<>();
        Set<Edge> result=new HashSet<>();// 依次挑选的的边在result里

        for (Node node:graph.nodes.values()){
            if (!hashSet.contains(node)){
                hashSet.add(node);
                for(Edge edge:node.edges){
                    priorityQueue.add(edge);
                }
                while (!priorityQueue.isEmpty()){
                    Edge cur=priorityQueue.poll();
                    Node toNode=cur.to;
                   if (!hashSet.contains(toNode)){
                       hashSet.add(toNode);
                       result.add(cur);
                   }
                   for (Edge edge : toNode.edges){
                       priorityQueue.add(edge);
                   }
                }
            }

        }
        return  result;

    }

五、暴力递归

暴力递归是常识
	1、把问题转化为规模缩小了的同类问题的字问题
	2、有明确的不需要进行递归的条件
	3、有当得到了子问题的结果之后的决策过程
	4、不记录每一个子问题的解

1、打印n层汉诺塔从最左边移动到最右边的全部过程

public static class Hanota{
	public static void LeftToRight(int n){
		if(n==1){
			System.out.pringln("Move 1 from left to right");
			return;
		}
		leftToMid(n-1);
		System.out.println("move "+n+" from mid to right");
		midToRight(n-1);
	}
	public static void midToRight(int n){
		if(n==1){
			System.out.println("move 1 from mid to right");
			return;
		}
		midToLeft(n-1);
		System.out.pringln("move "+n+" from mid to right ");
		leftToRight(n-1);
	}
	public static midToLeft(int n){
		if(n==1){
			System.out.println("move 1 from mid to left");
			return;
		}
		midToRight(n-1);
		System.out.println("move "+n+" from mid to left");
		rightToLeft(n-1);
	}
	public static void leftToMid(int n){
		if(n==1){
			System.out.println("Move 1 from left to mid");
			return;
		}
		leftToRight(n-1);
		System.out.println("move "+ n +" from left to mid");
		rightToMid(n-1);
	}
	public static void rightToMid(int n){
		if(n==1){
			System.out.println("move 1 from right to mid");
			return;
		}
		rightToLeft(n-1);
		System.out.println("move "+n+" from right to mid")
		leftToMid(n-1);
	}
	public static void rightToLeft(int n){
		if(n==1){
			System.out.println("move 1 from right to left");
			return;
		}
		rightToMid(n-1);
		System.out.println("move "+n+" from right to left");
		leftToMid(n-1);
	}

}

方法2:

public static hannoi(int n){
	hanioi2(n,"left","right","mid)
}
public static hanio2(int n,String from,String to,String other){
	if(n==1){
		System.out.pringln("move 1 from "+from+"  to "+to);
	}
	hanio2(n-1,from,other,to);
	System.out.println("move"+n+"from "+from+" to "+to);
	hanio2(n-1,other,to,from);
	
}

2、打印一个字符串的全部子序列

// str 固定参数
// 来到了str[index]字符,index是位置
// str[0..index-1]已经走过了!之前的决定,都在path上
// 之前的决定已经不能改变了,就是path
// str[index....]还能决定,之前已经确定,而后面还能自由选择的话,
// 把所有生成的子序列,放入到ans里去
public satic List<String> pringSubqueue(String str){
	char[] s=str.toCharArray();
	List<String> ans=new ArrayList<>();
	String payh="";
	process();		
}
public static void Process(char[] str,int index,List<String> ans,String path){
	if(str.length==index){
		ans.add(path);
		return;
	}
	process(str,index+1,ans,path);
	process(str,index+1,ans,path+String.valueOf(str[index]));
}

3、打印一个字符串的全部子序列,要求不要出现重复字面值的子序列

public static List<String> pringSubQueue(String str){
	char[] s=str.toCharArray();
	String path="";
	Set<String> result=new HashSet<>();
	process(s,0,result,path);
	List<String> ans=new ArrayList<>();
	for(String cur:result){
		ans.add(cur);
	}
	return ans;
}
public static void process(char[] str,int index,Set<String> result,String path){
	if(String.length==index){
		result.add(path);
		return;
	}
	process(str,index+1,result,path);
	process(str,index+1,result,path+String.valueOf(str[index]))
}

4、打印一个字符串的全部排列

public static List<String> printAll(String s){
	List<String> ans=new ArrayList<>();
	if(s==null ||  s.length()==0){
		return ans;
	}
	char[] str=s.toCharArray();
	
}
public static void g(char[] str,int index,ArrayList<String> ans){
	if(str.length==index){
		ans.add(String.valueOf(str));
		return;
	}else{
	for(int i=index,i<str.length,i++){
		swap(str,index,i);
		g2(str,index+1,ans);
		swap(str,index,i);
	}

	}
}
//去重的全排列
public static void g3(char[] str,int index,List<String> ans){
	if(index==str.length){
		ans.add(String.valueOf(str));
		return;
	}else{
		boolean[] isVisit=new boolean[256];
		for(int i=index,i<str.length,i++){
			if(!isVisit(str[i])){
				isVisit(str[i])=true;
				swap(str,index,i);
				g3(str,index+1,ans);
				swap(str,index,i);
			}
		}
	}
}
public static void swap(char[] str,int index1,int index2){
	char temp=str[index1];
	str[index1]=str[index2];
	str[index2]=temp;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值