基础的几类算法题

一、Arrays & Linked List

二、堆栈 & 队列

image.png
Stack<Integer> stack =new Stack<>();
stack.push(1);
stack.peek();
stack.pop();
stack.isEmpty();
  • java中的队列
Queue<Integer> queue = new Queue<Integer>();
queue.offer(2);
queue.poll();
queue.peek();
queue.isEmpty();

三、优先队列

  • PriorityQueue 优先队列,正常入,按照优先级出(设置属性来规定优先级)
  • 优先队列的实现机制
    方法一:堆(heap)实现,堆也有很多种
    方法二:二叉搜索树
  • 面试题:数据流中的第 K 大元素 https://leetcode-cn.com/problems/kth-largest-element-in-a-stream/
  • 解题方法的核心:使用堆存储前k个大的元素(可能是解决这种第k系列题目的通用想法?)
  • 面试题:滑动窗口的最大值 https://leetcode-cn.com/problems/sliding-window-maximum/
    方法一:使用大顶堆实现
    方法二:使用双端队列维护一个严格递增的单调队列

四、映射(Map)&集合(set)

五、树、二叉树、二叉搜索树

六、递归和分治

七、贪心算法

八、广度有限搜索(bfs)与深度优先搜索(dfs)

  • 感觉二叉树的前序遍历有点像深度有限搜索
  • 广度优先搜索:一层一层地搜,可以使用队列来实现,对于树来说,是没有环存在的,但如果是图上的搜索,需要使用一个数组isVisit来记录当前的点是否已经被访问过
public void bfs(Graph graph, Node start, Node end){
       Queue<Node> queue;
       List visited;
       queue.offer(start);;
       visited.add(start);

       while (!queue.isEmpty()){
           Node node = queue.poll();
           visited.add(node);

           process(node);   //对当前元素进行处理
           nodes=generate_related_nodes(node);//获取node节点的相关后续节点,且他们没有被访问过
           queue.push(nodes);
       }

       //other processing work
   }
  • 深度优先搜索可以使用递归或者栈来实现
#使用递归的方法(常用)
#伪代码
visited = set()
def dfs(node, visited):
  visited.add(node)
  #处理过程
  for next_node in node.children():
    if not next_node in visited:
      dfs(next_node, visited)

#使用迭代(栈)的方法
def dfs(self, tree):
  if tree.root is None:
    return []
  visited, stack = [], [tree.root]
  while stack:
    node  = stack.pop()
    visited.add(node)

    process(node)
    nodes = generate_related_nodes(node) #没有被访问过的子节点
    stack.push(nodes)

九、剪枝

十、二分查找

  • 前提条件:sorted(单调递增或者递减);bounded(存在上下界);accessible by index(能够通过索引访问)
  • x 的平方根 https://leetcode-cn.com/problems/sqrtx/
  • 两种解法:二分;牛顿迭代法
  • 题目中要求输出的结果的整数部分即可,可以尝试将代码写全,输出指定精度的结果
@Test
    public void test5(){
        int num=1;
        while (num!=-1){
            Scanner in = new Scanner(System.in);
            num = in.nextInt();
            System.out.println(mySqrt(num,0.0001));
        }

    }
    public double mySqrt(int num, double accuracy){
        double left = 0;
        double right = num;
        while(right>=left){
            double middle = (left+right)/2;
            if(Math.abs(middle*middle-num)<=accuracy) return middle;
            if(middle*middle>num) right=middle;
            else left=middle;
        }
        return -1;
    }

十一、字典树(Trie)

  • Trie树,即字典树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计
  • 优点:最大限度地减少无谓的字符串比较,查询效率比哈希表高
  • Trie的核心思想是空间换时间,利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的
  • Trie树使用一条边来代表一个字母,单词的长度和寻找该单词找过的路径的长度相同


    字典树的结构
  • 字典树的基本数据结构


    字典树的数据结构
  • 实现 Trie (前缀树) https://leetcode-cn.com/problems/implement-trie-prefix-tree/
public class Trie {
    class TrieNode{
        TrieNode[] next;
        boolean isEnd;

        public TrieNode(){
            isEnd=false;
            next = new TrieNode[26];
        }
    }

    private TrieNode root;
    /** Initialize your data structure here. */
    public Trie() {
        root = new TrieNode();
    }

    /** Inserts a word into the trie. */
    public void insert(String word) {
        TrieNode node = root;
        for(char c : word.toCharArray()){
            if(node.next[c-'a']==null){
                node.next[c-'a']=new TrieNode();
            }
            node = node.next[c-'a'];
        }
        node.isEnd=true;
    }

    /** Returns if the word is in the trie. */
    public boolean search(String word) {
        TrieNode node = root;
        for(char c : word.toCharArray()){
            node = node.next[c-'a'];
            if(node == null) return false;

        }
        return node.isEnd;

    }

    /** Returns if there is any word in the trie that starts with the given prefix. */
    public boolean startsWith(String prefix) {
        TrieNode node = root;
        for(char c : prefix.toCharArray()){
            node = node.next[c-'a'];
            if(node == null) return false;

        }
        return true;
    }
}

十二、位运算

  • 异或的一个重要特征,x^x=0
  • 位运算的常用操作:
    x&1 == 0 x&1==1 用来判断奇偶
    x=x&(x-1) 清零最低位的1
    x&-x 得到最低位的1
  • ✅位运算经常用在数1的个数相关的题目中
  • 位1的个数 https://leetcode-cn.com/problems/number-of-1-bits/
    用上面的式子就可以很好的解决
  • 2的幂 https://leetcode-cn.com/problems/power-of-two/ 做法同上
  • 比特位计数 https://leetcode-cn.com/problems/counting-bits/
    合理利用前面已经算出来的结果(dp+位运算)
  • N皇后 II https://leetcode-cn.com/problems/n-queens-ii/
    之前的方法是使用数组(col[]、pie[]、na[])来记录位置的占用情况,这里借助位运算,使用三个int类型的数值进行记录,col比较好理解占用的位置置1即可,对于int类型的pie和na实际上记录的是当前行的每个位置上的元素是否在之前结果的对角线方向上,转换到新行的时候,pie左移,na右移
public class Queens {
    int res= 0;
    public int totalNQueens(int n) {
        if(n<=0) return 0;
        dfs(n,0,0,0,0);
        return res;
    }
    public void dfs(int n, int row, int col, int pia, int na){
        if(row==n){
            res+=1;
            return;
        }
//计算当前可用的位置,注意使用的是32位的int,要消除n位之前的那些0对bits的影响
        int bits = (~(col|pia|na))&((1<<n)-1);
        while (bits!=0){
//获取当前选定的1的位置
            int pos= bits&(-bits);
            dfs(n,row+1,col|pos,(pia|pos)<<1,(na|pos)>>1);
//去掉最后一个1
            bits=bits&(bits-1);
        }

    }
}
  • 写位运算的公式的时候,一定要使用括号,因为它的运算优先级较低,防止出现错误

十三、动态规划

十四、并查集

之前看过了,也做了笔记 https://www.jianshu.com/p/a380c8ad5b88

十五、LRU Cache

  • LRU(Least Recently used)最近最少使用,一半使用双向链表来实现,O(1)实现查询(第一个)、修改和更新


    image.png
  • LRU 缓存机制 https://leetcode-cn.com/problems/lru-cache/
    需要使用HashMap,然后自己实现一个双向链表。使用虚拟的头尾节点会更容易解决问题

布隆过滤器(Bloom Filter)

  • 一个很长的二进制向量和一个映射函数
  • 布隆过滤器用于检索一个元素是否在集合中,如果判断不在,则该元素一定不在集合中;如果判断在,则该元素有一定的几率不在集合中
    *优点:空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难
    image.png
  • filter的作用与缓存类似,在查询之前加了一步筛选的操作,挡掉一些对不存在的元素的查询。与cache相同,后边都要跟一个真正的存储系统
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,717评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,501评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,311评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,417评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,500评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,538评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,557评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,310评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,759评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,065评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,233评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,909评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,548评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,172评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,420评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,103评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,098评论 2 352

推荐阅读更多精彩内容