数据结构与算法之美
王争
前Google工程师
立即订阅
71638 人已学习
课程目录
已完结 75 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 从今天起,跨过“数据结构与算法”这道坎
免费
入门篇 (4讲)
01 | 为什么要学习数据结构和算法?
02 | 如何抓住重点,系统高效地学习数据结构与算法?
03 | 复杂度分析(上):如何分析、统计算法的执行效率和资源消耗?
04 | 复杂度分析(下):浅析最好、最坏、平均、均摊时间复杂度
基础篇 (38讲)
05 | 数组:为什么很多编程语言中数组都从0开始编号?
06 | 链表(上):如何实现LRU缓存淘汰算法?
07 | 链表(下):如何轻松写出正确的链表代码?
08 | 栈:如何实现浏览器的前进和后退功能?
09 | 队列:队列在线程池等有限资源池中的应用
10 | 递归:如何用三行代码找到“最终推荐人”?
11 | 排序(上):为什么插入排序比冒泡排序更受欢迎?
12 | 排序(下):如何用快排思想在O(n)内查找第K大元素?
13 | 线性排序:如何根据年龄给100万用户数据排序?
14 | 排序优化:如何实现一个通用的、高性能的排序函数?
15 | 二分查找(上):如何用最省内存的方式实现快速查找功能?
16 | 二分查找(下):如何快速定位IP对应的省份地址?
17 | 跳表:为什么Redis一定要用跳表来实现有序集合?
18 | 散列表(上):Word文档中的单词拼写检查功能是如何实现的?
19 | 散列表(中):如何打造一个工业级水平的散列表?
20 | 散列表(下):为什么散列表和链表经常会一起使用?
21 | 哈希算法(上):如何防止数据库中的用户信息被脱库?
22 | 哈希算法(下):哈希算法在分布式系统中有哪些应用?
23 | 二叉树基础(上):什么样的二叉树适合用数组来存储?
24 | 二叉树基础(下):有了如此高效的散列表,为什么还需要二叉树?
25 | 红黑树(上):为什么工程中都用红黑树这种二叉树?
26 | 红黑树(下):掌握这些技巧,你也可以实现一个红黑树
27 | 递归树:如何借助树来求解递归算法的时间复杂度?
28 | 堆和堆排序:为什么说堆排序没有快速排序快?
29 | 堆的应用:如何快速获取到Top 10最热门的搜索关键词?
30 | 图的表示:如何存储微博、微信等社交网络中的好友关系?
31 | 深度和广度优先搜索:如何找出社交网络中的三度好友关系?
32 | 字符串匹配基础(上):如何借助哈希算法实现高效字符串匹配?
33 | 字符串匹配基础(中):如何实现文本编辑器中的查找功能?
34 | 字符串匹配基础(下):如何借助BM算法轻松理解KMP算法?
35 | Trie树:如何实现搜索引擎的搜索关键词提示功能?
36 | AC自动机:如何用多模式串匹配实现敏感词过滤功能?
37 | 贪心算法:如何用贪心算法实现Huffman压缩编码?
38 | 分治算法:谈一谈大规模计算框架MapReduce中的分治思想
39 | 回溯算法:从电影《蝴蝶效应》中学习回溯算法的核心思想
40 | 初识动态规划:如何巧妙解决“双十一”购物时的凑单问题?
41 | 动态规划理论:一篇文章带你彻底搞懂最优子结构、无后效性和重复子问题
42 | 动态规划实战:如何实现搜索引擎中的拼写纠错功能?
高级篇 (9讲)
43 | 拓扑排序:如何确定代码源文件的编译依赖关系?
44 | 最短路径:地图软件是如何计算出最优出行路径的?
45 | 位图:如何实现网页爬虫中的URL去重功能?
46 | 概率统计:如何利用朴素贝叶斯算法过滤垃圾短信?
47 | 向量空间:如何实现一个简单的音乐推荐系统?
48 | B+树:MySQL数据库索引是如何实现的?
49 | 搜索:如何用A*搜索算法实现游戏中的寻路功能?
50 | 索引:如何在海量数据中快速查找某个数据?
51 | 并行算法:如何利用并行处理提高算法的执行效率?
实战篇 (5讲)
52 | 算法实战(一):剖析Redis常用数据类型对应的数据结构
53 | 算法实战(二):剖析搜索引擎背后的经典数据结构和算法
54 | 算法实战(三):剖析高性能队列Disruptor背后的数据结构和算法
55 | 算法实战(四):剖析微服务接口鉴权限流背后的数据结构和算法
56 | 算法实战(五):如何用学过的数据结构和算法实现一个短网址系统?
加餐:不定期福利 (6讲)
不定期福利第一期 | 数据结构与算法学习书单
不定期福利第二期 | 王争:羁绊前行的,不是肆虐的狂风,而是内心的迷茫
不定期福利第三期 | 测一测你的算法阶段学习成果
不定期福利第四期 | 刘超:我是怎么学习《数据结构与算法之美》的?
总结课 | 在实际开发中,如何权衡选择使用哪种数据结构和算法?
《数据结构与算法之美》学习指导手册
加餐:春节7天练 (7讲)
春节7天练 | Day 1:数组和链表
春节7天练 | Day 2:栈、队列和递归
春节7天练 | Day 3:排序和二分查找
春节7天练 | Day 4:散列表和字符串
春节7天练 | Day 5:二叉树和堆
春节7天练 | Day 6:图
春节7天练 | Day 7:贪心、分治、回溯和动态规划
加餐:用户学习故事 (2讲)
用户故事 | Jerry银银:这一年我的脑海里只有算法
用户故事 | zixuan:站在思维的高处,才有足够的视野和能力欣赏“美”
结束语 (3讲)
结束语 | 送君千里,终须一别
第2季回归 | 这一次,我们一起拿下设计模式!
打卡召集令 | 60 天攻克数据结构与算法
免费
数据结构与算法之美
登录|注册

春节7天练 | Day 2:栈、队列和递归

王争 2019-02-05
你好,我是王争。初二好!
为了帮你巩固所学,真正掌握数据结构和算法,我整理了数据结构和算法中,必知必会的 30 个代码实现,分 7 天发布出来,供你复习巩固所用。今天是第二篇。
和昨天一样,你可以花一点时间,来完成测验。测验完成后,你可以根据结果,回到相应章节,有针对性地进行复习。

关于栈、队列和递归的几个必知必会的代码实现

用数组实现一个顺序栈
用链表实现一个链式栈
编程模拟实现一个浏览器的前进、后退功能

队列

用数组实现一个顺序队列
用链表实现一个链式队列
实现一个循环队列

递归

编程实现斐波那契数列求值 f(n)=f(n-1)+f(n-2)
编程实现求阶乘 n!
编程实现一组数据集合的全排列

对应的 LeetCode 练习题(@Smallfly 整理)

Valid Parentheses(有效的括号)
Longest Valid Parentheses(最长有效的括号)
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《数据结构与算法之美》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(50)

  • 李皮皮皮皮皮
    基础数据结构和算法是基石,灵活运用是解题的关键。栈,队列这些数据结构说到底就是给顺序表添加约束,更便于解决某一类问题。学习中培养算法的设计思想是非常关键的。而且思想是可以通用的。之前读《暗时间》一书,收获颇深。书中介绍之正推反推我在做程序题时竟出奇的好用。
    2019-02-05
    5
  • abner
    java用数组实现一个顺序栈
    代码如下:
    package stack;

    public class ArrayStack {

        private String[] data;
        private int count;
        private int size;

        public ArrayStack(int n) {
            this.data = new String[n];
            this.count = 0;
            this.size = n;
        }
        
        public boolean push(String value) {
            if (count == size) {
                return false;
            } else {
                data[count] = value;
                count++;
                return true;
            }
        }

        public String pop() {
            if (count == 0) {
                return null;
            } else {
                count--;
                return data[count];
            }
        }
    }
    2019-02-11
    2
  • kai
    1. 编程实现斐波那契数列求值 f(n)=f(n-1)+f(n-2)
    public class Fibonacci {
        public static int fib(int n) {
            if (n <= 0) {
                return 0;
            }
            if (n == 1) {
                return 1;
            }

            return fib(n-1) + fib(n-2);
        }
    }

    2. Climbing Stairs(爬楼梯)
    public class ClimbStairs {
        public int climbFloor(int n) {
            if (n == 1 || n == 2) {
                return n;
            }

            return climbFloor(n - 1) + climbFloor(n - 2);
        }

        public int climbFloorIter(int n) {
            if (n == 1 || n == 2) {
                return n;
            }

            int jump1 = 1;
            int jump2 = 2;
            int jumpN = 0;

            for (int i = 3; i <= n; i++) {
                jumpN = jump1 + jump2;

                jump1 = jump2;
                jump2 = jumpN;
            }

            return jumpN;
        }
    }

    3. Sliding Window Maximum(滑动窗口最大值)
    import java.util.ArrayList;
    import java.util.LinkedList;

    public class MaxNumOfSlidingWindow {
        public ArrayList<Integer> maxInWindows(int [] num, int size)
        {
            ArrayList<Integer> res = new ArrayList<>();

            if (num == null || num.length <= 0 || size <= 0 || size > num.length) {
                return res;
            }

            LinkedList<Integer> qMax = new LinkedList<>(); // 双端队列:左端更新max,右端添加数据

            int left = 0;

            for (int right = 0; right < num.length; right++) {
                // 更新右端数据
                while (!qMax.isEmpty() && num[qMax.peekLast()] <= num[right]) {
                    qMax.pollLast();
                }

                qMax.addLast(right);

                // 更新max:如果max的索引不在窗口内,则更新
                if (qMax.peekFirst() == right - size) {
                    qMax.pollFirst();
                }

                // 待窗口达到size,输出max
                if (right >= size-1) {
                    res.add(num[qMax.peekFirst()]);
                    left++;
                }
            }

            return res;
        }
    }
    2019-02-11
    2
  • abner
    java用链表实现一个链式栈
    代码如下:
    package stack;

    public class LinkedStack {
        
        private Node top = null;
        
        public static class Node {
            
            private String data;
            private Node next;
            
            public Node(String data, Node next) {
                this.data = data;
                this.next = next;
            }
            
            public String getData() {
                return data;
            }
        }
        
        public void push(String item) {
            Node newNode = new Node(item, null);
            if (top == null) {
                top = newNode;
            } else {
                newNode.next = top;
                top = newNode;
            }
        }
        
        public String pop() {
            if (top == null) {
                return null;
            }
            String value = top.data;
            top = top.next;
            return value;
        }
        
        public void printAll() {
            Node pNode = top;
            while (pNode != null) {
                System.out.print(pNode.data + " ");
                pNode = pNode.next;
            }
            System.out.println();
        }
        
        public static void main(String[] args) {
            LinkedStack linkedStack = new LinkedStack();
            linkedStack.push("haha");
            linkedStack.push("nihao");
            linkedStack.printAll();
        }
    }
    2019-02-12
    1
  • abner
    java用递归实现斐波那契数列
    代码如下:
    package recursion;

    public class Fib {

        public long calFib(long n) {
            if (n == 0 || n == 1) {
                return 1;
            } else {
                return calFib(n - 1) + calFib(n - 2);
            }
        }
        
        public static void main(String[] args) {
            Fib fib = new Fib();
            long result = fib.calFib(5);
            System.out.println(result);
        }
    }
    2019-02-11
    1
  • abner
    java用递归实现求解n!
    代码如下:
    package recursion;

    public class Fac {

        public long calFac(long n) {
            if (n == 0) {
                return 1;
            }
            return calFac(n - 1) * n;
        }

        public static void main(String[] args) {
            Fac fac = new Fac();
            long result = fac.calFac(10);
            System.out.println(result);
        }
    }
    2019-02-11
    1
  • abner
    java用数组实现一个顺序队列
    代码如下:
    package queue;

    public class ArrayQueue {
        
        private String[] data;
        private int size;
        private int head;
        private int tail;
        
        public ArrayQueue(int capacity) {
            data = new String[capacity];
            size = capacity;
            head = 0;
            tail = 0;
        }
        
        public boolean enqueue(String value) {
            if (tail == size) {
                return false;
            }
            data[tail] = value;
            tail++;
            return true;
        }

        public String dequeue() {
            if (tail == 0) {
                return null;
            }
            String value = data[head];
            head++;
            return value;
        }
    }
    2019-02-11
    1
  • ALAN
    import java.util.Arrays;

    /**
     *
     *Stack 1 solution
     */
    public class StackArray {

    public Object[] arr = new Object[10];
    public int count;

    public void push(Object ele) {
    if (count == arr.length) { // expand size
    arr = Arrays.copyOf(arr, arr.length * 2);
    }
    arr[count] = ele;
    count++;
    }

    public Object pop() {
    if (count == 0)
    return null;
    if (count < arr.length / 2) {
    arr = Arrays.copyOf(arr, arr.length / 2);
    }
    return arr[--count];

    }
    }

    /**
     *
     *Stack 2 solution
     */
    class StackLinked {
    Node head;
    Node tail;

    public void push(Object ele) {

    if (head == null) {
    head = new Node(ele);
    tail = head;
    } else {
    Node node = new Node(ele);
    tail.next = node;
    node.prev = tail;
    tail = node;
    }
    }

    public Object pop() {
    if (tail == null)
    return null;
    Node node = tail;
    if (tail == head) {
    head = null;
    tail = null;
    } else
    tail = tail.prev;
    return node;

    }
    }
    class Node {
    Node prev;
    Node next;
    Object value;

    public Node(Object ele) {
    value = ele;
    }
    }
    2019-02-08
    1
  • TryTs
    之前有个类似的题,走楼梯,装苹果,就是把苹果装入盘子,可以分为有一个盘子为空(递归),和全部装满没有空的情况,找出状态方程,递归就可以列出来了。我觉得最关键是要列出状态方程,之前老师类似于说的不需要关注特别细节,不要想把每一步都要想明白,快速排序与递归排序之类的算法,之前总是想把很细节的弄懂,却发现理解有困难。
    2019-02-06
    1
  • Hxz
    我用js写的题解都放在了https://github.com/abchexuzheng/algorithm-for-js这里,前端学算法的小伙伴们可以看看一起学习下哈
    2019-10-12
  • Geek_18b741
    再做Climbing Stairs这个题目的时候,提交了两个版本的代码。理论上来说内存应该是有区别的,但是LeetCode给的结果,内存大小却没有什么区别。请帮忙看看。
    /**
         * 动态规划
         * @param n
         * @return
         */
        public int climbStairsV3(int n) {
            if(n==1) return 1;
            int[] dp = new int[n+1];
            dp[1]=1;
            dp[2]=2;
            for(int i=3;i<=n;i++){
                dp[i]=dp[i-1]+dp[i-2];
            }
            return dp[n];
        }

        /**
         * 节省内存的动态规划,但实际LeetCode反馈出来的内存并不少
         * @param n
         * @return
         */
        public int climbStairsV4(int n) {
            if(n==1) return 1;
            int num1 =1;
            int num2 =2;
            int num3=0;
            for(int i=3;i<=n;i++){
                num3=num1+num2;
                num1=num2;
                num2=num3;
            }
            return num2;
        }
    2019-09-11
  • 猫猫
    全排列js
    //9.一组数据集合的全排列 回溯(暴力枚举)
    let count = 1

    function permutation(nums, result = []) {
      if (nums.length == 0) {
        console.log(`${count}:${result}`)
        count++
        return
      }
      for (let i = 0; i < nums.length; i++) {
        permutation(nums.filter((value, index) => index != i), [...result, nums[i]])
      }
    }
    2019-08-26
  • 懒猫
    练完打卡
    2019-05-22
  • Sharry
    有意思, 递归的 LeeCode 题目, 使用简单粗暴的回溯法并没有办法通过, 还是得使用动态规划求解
    2019-02-20
  • hopeful
    #一组数据集合的全排列
    def f(start , b):
        a = list(b)
        if start==len(a):
            print(b)
        else:
            for i in range(start , len(a)):
                a[start] , a[i] = a[i] , a[start]
                c = tuple(a)
                f(start+1 , c)
                a[start] , a[i] = a[i] , a[start]
    2019-02-19
  • hopeful
    #实现快速排序、归并排序
    #---------快排(三数取中)---------
    def QuickSort():
        array = Array(10000)
        qsort(0 , len(array)-1 , array)
        return array
    def qsort(start , end , array):
        if start < end:
            key = partation(array , start , end)
            qsort(start , key-1 , array)
            qsort(key+1 , end , array)
    def swap(array , start , end):
        temp = array[start]
        array[start] = array[end]
        array[end] = temp
    def change(array , start , mid , end):
        if array[start] > array[mid]:
            swap(array , start , mid)
        if array[start]>array[end]:
            swap(array , start , end)
        if array[mid] > array[end]:
            swap(array , mid , end)
        swap(array , mid , start)
    def partation(array , start , end):
        #mid = int((start+end)/2)
        #change(array , start , mid , end)
        temp = array[start]
        while start < end :
            while start<end and array[end]<=temp:
                end-=1
            swap(array , start , end)
            while start<end and array[start]>=temp:
                start+=1
            swap(array , start , end)
        return start
    #---------------归并------------
    def merge(a , b):
        c = []
        i = 0
        j = 0
        while i<len(a) and j<len(b):
            if a[i] > b[j]:
                c.append(a[i])
                i+=1
            else:
                c.append(b[j])
                j+=1
        if i>=len(a):
            for k in range(j , len(b)):
                c.append(b[k])
        if j>=len(b):
            for k in range(i , len(a)):
                c.append(a[k])
        return c
    def devide(array):
        if len(array) == 1:
            return array
        else:
            mid = int((0 + len(array)) / 2)
            leftArray = devide(array[0:mid])
            rightArray = devide(array[mid:len(array)])
            return merge(leftArray , rightArray)
    def mergesort():
        array = Array(100)
        m = devide(array)
        return m
    2019-02-15
  • hopeful
    #冒泡、选择、插入排序
    import random
    import time
    def Array(n):
        a = []
        for i in range(n):
            a.append(random.randint(0 , n))
        return a
    #插入排序
    def insert():
        array = Array(100)
        time_start=time.time()
        for i in range(1 , len(array)):
            for j in range(i , 0 , -1):
                if array[j] > array[j-1]:
                    temp = array[j]
                    array[j] = array[j-1]
                    array[j-1] = temp
                else:
                    break
        time_end=time.time()
        print(array)
        print('totally cost',time_end-time_start)
    def select():
        array = Array(100)
        time_start=time.time()
        for i in range(len(array)):
            for j in range(i+1 , len(array)):
                if array[j] > array[i]:
                    temp = array[j]
                    array[j] = array[i]
                    array[i] = temp
        time_end=time.time()
        print(array)
        print('totally cost',time_end-time_start)
    def bubble():
        array = Array(100)
        time_start=time.time()
        for i in range(len(array)-1 , 0 , -1):
            flag = False
            for j in range(i):
                if array[j] > array[j+1]:
                    temp = array[j]
                    array[j] = array[j+1]
                    array[j+1] = temp
                    flag = True
            if not flag:
                break
        time_end=time.time()
        print(array)
        print('totally cost',time_end-time_start)
    2019-02-15
  • hopeful
    //阶乘n!
    def f(n):
        if(n<=1):
            return 1
        else:
            return f(n-1)*n
    2019-02-15
  • hopeful
    //斐波那契数列
    def f(n):
        if(n<=0):
            return 0
        elif(n==1):
            return 1
        else:
            return f(n-1)+f(n-2)
    2019-02-15
  • hopeful
    //数组实现顺序队列
    public class MyQueue {

    private Object[] object;
    private int count;

    MyQueue(int size){
    this.object = new Object[size];
    count = 0;
    }

    @Override
    public Object pop() {
    // TODO Auto-generated method stub
    if(count==0) {
    return null;
    }else {
    Object temp = object[0];
    count--;
    for (int i = object.length-1; i > 0 ; i--) {
    object[i-1] = object[i];
    }
    return temp;
    }
    }

    @Override
    public void push(Object h) {
    // TODO Auto-generated method stub
    if( (count+1) >= object.length) {
    Object[] ob = new Object[2*object.length];
    System.arraycopy(object, 0, ob, 0, count);
    this.object = ob;
    }
    object[count] = h;
    count++;
    }

    @Override
    public Object getFirst() {
    // TODO Auto-generated method stub
    if(count==0)
    return null;
    else
    return object[0];
    }

    @Override
    public Object getLast() {
    // TODO Auto-generated method stub
    if(count==0)
    return null;
    else
    return object[count-1];
    }

    @Override
    public boolean empty() {
    // TODO Auto-generated method stub
    if(count==0) {
    return true;
    }else
    return false;
    }

    @Override
    public int size() {
    // TODO Auto-generated method stub
    return count;
    }

    }
    2019-02-15
收起评论
50
返回
顶部