算法和数据结构
算法和数据结构
Lzfa
这个作者很懒,什么都没留下…
展开
-
贪心算法.
什么是贪心算法1)最自然智慧的算法2)用一种局部最功利的标准,总是做出在当前看来是最好的选择3)难点在于证明局部最功利的标准可以得到全局最优解4)对于贪心算法的学习主要以增加阅历和经验为主贪心算法求解的标准过程分析业务根据业务逻辑找到不同的贪心策略对于能举出反例的策略直接跳过,不能举出反例的策略要证明有效性这往往是特别困难的,要求数学能力很高且不具有统一的技巧性贪心算法的解题套路实现一个不依靠贪心策略的解法X,可以用最暴力的尝试脑补出贪心策略A、贪心策略B原创 2021-11-27 15:17:57 · 241 阅读 · 0 评论 -
二叉树的递归套路
二叉树的递归套路可以解决面试中绝大多数的二叉树问题尤其是树型dp问题本质是利用递归遍历二叉树的便利性1)假设以X节点为头,假设可以向X左树和X右树要任何信息2)在上一步的假设下,讨论以X为头节点的树,得到答案的可能性(最重要)3)列出所有可能性后,确定到底需要向左树和右树要什么样的信息4)把左树信息和右树信息求全集,就是任何一棵子树都需要返回的信息S5)递归函数都返回S,每一棵子树都这么要求6)写代码,在代码中考虑如何把左树的信息和右树信息整合出整棵树的信息第一题是否平衡二叉树原创 2021-11-12 11:38:42 · 327 阅读 · 0 评论 -
二叉树相关题目
第一题LeetcodeEncode N-ary Tree to Biary Treepackage com.lzf2.class09;import java.util.ArrayList;import java.util.List;//多叉树 转二叉树//力扣 431题 https://leetcode.com/problems/encode-n-ary-tree-to-binary-treepublic class EncodeNaryTreeToBinaryTree {原创 2021-10-30 14:01:40 · 129 阅读 · 0 评论 -
二叉树的基本算法
二叉树结构描述Class Node { V value; Node left; Node right;}先、中、后序遍历先序:任何子树的处理顺序都是,先头节点、再左子树、然后右子树中序:任何子树的处理顺序都是,先左子树、再头节点、然后右子树后序:任何子树的处理顺序都是,先左子树、再右子树、然后头节点递归实现递归序,每个结点都会到达3次,第一次到达一个节点就打印就是先序、第二次打印即中序、第三次即后序。求X祖先结点:先序:[…A…]X[]后续:[]X[…B…]A区间 ∩原创 2021-10-28 09:08:08 · 457 阅读 · 0 评论 -
链表相关面试题
第一题问题描述:快慢指针1)输入链表头节点,奇数长度返回中点,偶数长度返回上中点2)输入链表头节点,奇数长度返回中点,偶数长度返回下中点3)输入链表头节点,奇数长度返回中点前一个,偶数长度返回上中点前一个4)输入链表头节点,奇数长度返回中点前一个,偶数长度返回下中点前一个提示:求上中点,当前结点后有两个结点才继续跳求下中点,当前结点后有一个结点就继续跳/** * 问题描述:快慢指针 * <p> * 1)输入链表头节点,奇数长度返回中点,偶数长度返回上中点 * 2)输入链原创 2021-10-14 18:02:31 · 118 阅读 · 0 评论 -
桶排序 + 排序稳定性及总结
桶排序桶排序思想下的排序:计数排序 & 基数排序1)桶排序思想下的排序都是不基于比较的排序2)时间复杂度为O(N),额外空间负载度O(M)3)应用范围有限,需要样本的数据状况满足桶的划分1)一般来讲,计数排序要求,样本是整数,且范围比较窄(员工年龄)2)一般来讲,基数排序要求,样本是10进制的正整数一旦要求稍有升级,改写代价增加是显而易见的计数排序/** * 计数排序 */public class CountSort { //对员工年龄进行排序 pu原创 2021-10-12 11:24:59 · 1236 阅读 · 0 评论 -
前缀树
前缀树前缀树prefix tree trie1)单个字符串中,字符从前到后的加到一棵多叉树上2)字符放在路上,节点上有专属的数据项(常见的是pass和end值)3)所有样本都这样添加,如果没有路就新建,如有路就复用4)沿途节点的pass值增加1,每个字符串结束时来到的节点end值增加1可以完成前缀相关的查询例子设计一种结构。用户可以:1)void insert(String str) 添加某个字符串,可以重复添加,每次算1个2)int search(String str原创 2021-10-11 15:10:49 · 77 阅读 · 0 评论 -
加强堆+练习题
加强堆系统提供的堆无法做到的事情:1)已经入堆的元素,如果参与排序的指标(数据)方法变化,系统提供的堆无法做到时间复杂度O(logN)调整!都是O(N)的调整!需要先找到该数据对象,然后再对象进行调整。2)系统提供的堆只能弹出堆顶,做不到自由删除任何一个堆中的元素,或者说,无法在时间复杂度O(logN)内完成!一定会高于O(logN)根本原因:无反向索引表1)建立反向索引表2)建立比较器3)核心在于各种结构相互配合,非常容易出错 package com.lzf2.class05;原创 2021-10-11 12:00:18 · 327 阅读 · 0 评论 -
堆、堆排序
一、堆1)堆结构就是用数组实现的完全二叉树结构2)完全二叉树中如果每棵子树的最大值都在顶部就是大根堆3)完全二叉树中如果每棵子树的最小值都在顶部就是小根堆4)左孩子2i + 1 , 右孩子2i + 2 , 父节点 (i - 1)/25)size变量控制大小package com.lzf2.class05;/** * 大根堆 */public class Heap { private int[] heap; private int heapSize; pu原创 2021-09-27 19:36:11 · 254 阅读 · 0 评论 -
随机快速排序
快速排序和随机快排 递归版package com.lzf2.class04;/** * 快速排序、随机快速排序 */public class QuickSort { //1.快随排序 public static void quickSort1(int[] arr){ if (arr == null || arr.length < 2){ return; } process(arr,0,arr.len原创 2021-09-22 22:41:33 · 112 阅读 · 0 评论 -
荷兰国旗问题
将一个数组从L到R分成左边小于等于某个数,右边大于某个数private static void swap(int[] arr, int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp;}//arr[L..R]上,以arr[R]位置的数做划分值// 小于等于 | 大于//返回作为划分值那个数的位置public static int partition(int[] arr, int L, int原创 2021-09-22 21:12:24 · 72 阅读 · 0 评论 -
归并排序+面试题
归并排序1)整体是递归,左边排好序+右边排好序+merge让整体有序2)让其整体有序的过程里用了排外序方法3)利用master公式来求解时间复杂度4)当然可以用非递归实现归并排序复杂度T(N) = 2*T(N/2) + O(N^1)根据master可知时间复杂度为O(N*logN)merge过程需要辅助数组,所以额外空间复杂度为O(N)归并排序的实质是把比较行为变成了有序信息并传递,比O(N^2)的排序快代码实现package com.lzf2.class03;/** *原创 2021-09-21 18:16:19 · 374 阅读 · 0 评论 -
认识递归、哈希表、有序表
递归对于新手来说,把调用的过程画出结构图是必须的,这有利于分析递归递归并不是玄学,递归底层是利用系统栈来实现的任何递归函数都一定可以改成非递归例子:求数组arr[L..R]中的最大值,怎么用递归方法实现。1)将[L..R]范围分成左右两半。左:[L..Mid] 右[Mid+1..R]2)左部分求最大值,右部分求最大值3) [L..R]范围上的最大值,是max{左部分最大值,右部分最大值}注意:2)是个递归过程,当范围上只有一个数,就可以不用再递归了Master公式Master公原创 2021-09-18 15:23:50 · 146 阅读 · 0 评论 -
栈和队列实现+面试题
数组实现栈package com.lzf2.class02;import java.util.Stack;/** * 数组实现栈 */public class ArrayImplStack { private int[] element; private int size; public ArrayImplStack(int capacity) { element = new int[capacity]; size = 0;原创 2021-09-18 14:30:18 · 46 阅读 · 0 评论 -
链表实现+面试题
单向链表public class Node { public int value; public Node next; public Node(int data) { value = data; }}双向链表public class DoubleNode { public int value; public Node next; public Node pre; public Node(int data) {原创 2021-09-18 14:25:33 · 79 阅读 · 0 评论 -
异或运算
无进位相加 00111 01101得 01010性质:0^N = NN^N =0a ^ b ^ c =abc位置可以随意第一题不用额外变量交换 两个数,请保证两个数的内存地址是不一样的public static void swap(int i,int j){ i = i ^ j; j = i ^ j ; i = i ^ j;}第二题一种数出现奇数次,其他都出现偶数次,找出这个数public static int getOneOdd(int[原创 2021-09-16 11:26:47 · 56 阅读 · 0 评论 -
认识二分法
经常见到的类型是在一个有序数组上,开展二分搜索,但有序真的是所有问题求解时使用二分的必要条件吗?不只要能正确构建左右两侧的淘汰逻辑(排它性),你就可以二分。问题一在一个有序数组中,找到某个数是否存在/** * 有序数组中,找某个数是否存在 */public class BSExit { public static boolean isExit(int[] arr,int value){ if(arr == null || arr.length == 0){原创 2021-09-15 16:13:56 · 265 阅读 · 0 评论 -
选择、冒泡、插入排序
一、选择排序过程:arr[0~N-1]范围上,找到最小值所在的位置,然后把最小值交换到0位置。arr[1~N-1]范围上,找到最小值所在的位置,然后把最小值交换到1位置。arr[2~N-1]范围上,找到最小值所在的位置,然后把最小值交换到2位置。…arr[N-1~N-1]范围上,找到最小值位置,然后把最小值交换到N-1位置。估算:很明显,如果arr长度为N,每一步常数操作的数量,如等差数列一般所以,总的常数操作数量 = a*(N^2) + b*N + c (a、b、c都是常数)所以选择排原创 2021-09-14 17:32:40 · 60 阅读 · 0 评论 -
认识对数器
1,你想要测的方法a2,实现复杂度不好但是容易实现的方法b(可以用已有的库函数)3,实现一个随机样本产生器4,把方法a和方法b跑相同的随机样本,看看得到的结果是否一样5,如果有一个随机样本使得比对结果不一致,打印样本进行人工干预,改对方法a和方法b6,当样本数量很多时比对测试依然正确,可以确定方法a已经正确。// for testpublic static void main(String[] args){ int testTime = 500000;//测试次数 int ma原创 2021-09-14 09:48:51 · 64 阅读 · 0 评论