面试(四) 数据结构与算法

排序

插入排序:平均on2 最好on(有序)

	//插入 
	public static void insertsort(int[] A){
		for(int i = 1; i<A.length; i++){
			int temp = A[i];
			int j = i-1;
			while(j>=0 && A[j]>temp){
				A[j+1] = A[j];
				j--;
			}
			A[j+1] = temp;
		}
	}

选择排序:on2

	//选择排序,将数组分为两部分,一部分为排序好的,一部分为未排序的,首先把最小的放最前面
	public static void selsort(int[] A){
		for(int i = 0; i < A.length-1; i++){
			int l = i;
			for(int j = i+1; j<A.length; j++){
				if(A[l] > A[j]){
					l = j;
				}
			}
			if(l != i){
				int temp = A[l];
				A[l] = A[i];
				A[i] = temp;
			}
		}
	}

冒泡排序:on2

	//冒泡
	public static void bubsort(int[] A){
		for(int i = 0; i<A.length-1; i++){
			for(int j = 0; j<A.length-1-i; j++){//第一大的挪到最后一位,第二大挪到倒数第二位
				if(A[j]>A[j+1]){
					int temp = A[j];
					A[j] = A[j+1];
					A[j+1] = temp;
				}
			}
		}
	}

堆排序(用的是数组):onlogn)整堆,最大堆,排序三步

	//堆排序
	public static void heapsort(int[] a){
		if(a == null || a.length<=1){
			return;
		}
		buildheap(a);
		for(int i = a.length-1; i>=1; i--){
			int temp = a[0];
			a[0] = a[i];
			a[i] = temp;
			maxheap(a, i, 0);//注意,此处为i,不能把后面最大的再放上去了
		}
	}
	
	//建最大堆
	public static void buildheap(int[] a){
		if(a == null || a.length<=1){
			return;
		}
		int half = a.length/2;
		for(int i = half; i>=0; i--){
			maxheap(a, a.length, i);
		}
	}
	
	//某个index往下落到最小的位置,大的放上来
	public static void maxheap(int[] a, int heapsize, int index){
		int left = index*2+1;
		int right = index*2+2;
		int largest = index;
		if(left<heapsize && a[left]>a[index]){
			largest = left;
		}
		if(right<heapsize && a[right]>a[largest]){
			largest = right;
		}
		if(index != largest){
			int temp = a[largest];
			a[largest] = a[index];
			a[index] = temp;
			maxheap(a, heapsize, largest);
		}
	}

快排:平均onlogn)最差on2)(有序)

	//快排
	public static void quicksort(int[] A, int low, int high){
		if(low < high){
			int mid = partition(A,low,high);
			quicksort(A, low, mid-1);
			quicksort(A, mid+1, high);
		}
	}
	public static int partition(int[] A, int low, int high){
		int x = A[high];
		int i = low-1;
		for(int j = low; j<high; j++){
			if(A[j] <= x){
				int temp = A[j];
				A[i+1] = temp;
				A[j] = A[i+1];
				i++;
			}
		}
		++i;
		int temp = A[i];
		A[i] = x;
		A[high] = temp;
		return i;
	}

归并排序:onlogn)递归+merge  merge是用来合并两个有序数组

	//归并排序
	public static void mergesort(int[] A, int low, int high){
		if(low<high){
			int mid = (low+high) / 2;
			mergesort(A, low, mid);
			mergesort(A, mid+1, high);
			merge(A, low, high, mid);
		}
	}
	public static void merge(int[] A, int low, int high, int mid){
		int[] m = new int[mid-low+1];
		int[] n = new int[high-mid];
		for(int i = 0; i<m.length; i++){
			m[i] = A[i+low];
		}
		for(int j = 0; j<n.length; j++){
			n[j] = A[mid+j+1];
		}
		int i = 0;
		int j = 0;
		int k = low;
		while(i<m.length && j<n.length){
			if(m[i]>n[j]){
				A[k++] = n[j++];
			}else{
				A[k++] = m[i++];
			}
		}
		while(i<m.length){
			A[k++] = m[i++];
		}
		while(j<n.length){
			A[k++] = n[j++];
		}
	}


查找

链表查找on),插入o1);数组查找o1),插入on)。


对于有序的数组(不能是链表,链表需要一个一个的next引用),可以用折半查找onlogn),有递归和非递归两种方式。


查找top10大的数,可以维护一个大小为10的最大堆。


对于数据量多的,可以用哈希,能在o1)情况下查到(其实就是哈希索引),也可以建立索引。


对于查找大小为n-1的数组中(每个值不同,在1~n中,等于漏一个),可以用位图法,等于是new一个bool型的数组,因为bool型只占1个位,而一个int4字节(4*8=32位),大小为1/32,而且在on)解决了问题。思想其实是哈希,以数的值作为bool数组的下表。(好多类似问题)

 

哈希的概念:将一个对象通过一种哈希函数,哈希成一个数值,这个数值是数组的下标,而数组里存放的即为这个对象,这就是建哈希表的过程。如果要查找,其实就是上面过程一样

解决哈希冲突:链地址法,再哈希法,再散列法,公共溢出块等。

 

 

数据结构

数组


链表(双向链表的插入、删除)




树:树的插入,删除,先中后序(递归非递归),查找,各种树的算法,红黑树的一些概念。

层次遍历

之字形层次遍历

层次遍历改编 打印某一层

二叉树的下一结点(有无父亲指针)

是否为bst

二叉树的平衡检查

二叉树和为某一值的路径 如果有返回值 则return 递归

树是否对称

两树是否相同

树的3种遍历的迭代算法

根据前中构建后

根据中后构建前

某数组是不是某bst树的后续遍历

二叉搜索树改双向链表 ······

可以去牛客上多练练

	//先序遍历非递归
	public static void preorder(TreeNode root){
		Stack<TreeNode> stack = new Stack<>();
		TreeNode node = root;
		while(node != null || !stack.isEmpty()){
			//将所有的左孩子进栈
			if(node != null){
				//先访问再进栈
				System.out.println(root.val);
				stack.push(node);
				node = node.left;
			}else{
				//到左下角空了先不急着回去,访问最左下角的右孩子
				node = stack.pop();
				node = node.right;
			}
		}
	}
	
	//中序遍历非递归
	public static void inorder(TreeNode root){
		TreeNode node = root;
		Stack<TreeNode> stack = new Stack<>();
		while(node!=null || !stack.isEmpty()){
			if(node!=null){
				stack.push(node);
				node = node.left;
			}else{
				node = stack.pop();
				System.out.println(node.val);
				node = node.right;
			}
		}
	}
	
	//后续遍历非递归,需要再用一个辅助栈帮助存储后续遍历的结果
	public static void postorder(TreeNode root){
		TreeNode node = root;
		Stack<TreeNode> stack = new Stack<>();
		Stack<TreeNode> result = new Stack<>();
		while(node!=null || !stack.isEmpty()){
			if(node != null){
				result.push(node);
				stack.push(node);
				node = node.right;
			}else{
				node = stack.pop();
				node = node.left;
			}
		}
		while(!result.isEmpty()){
			System.out.println(result.pop().val);
		}
	}

图:最小生成树的primkruscal算法描述(两个思想都是贪心)。dijkstra(贪心在于用一个最小优先队列(即最小堆)维护剩余点,从剩余点选出)描述。哈夫曼描述(贪心)。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值