你将收获

1、工作、面试时轻松解决算法相关问题的方法与能力;

2、用图解掌握 30 个数据结构与算法内容+30 个实战项目+30 道 BAT 面试真题;

3.、提升「算法思维」逻辑和「程序设计」能力;

4、系统搭建完整的大厂面试刷题与解题方法,为你的大厂面试助力;

5、购课就可领取 800 元编程大礼包。

适用人群

1、基础能力弱的程序员;2、工作中不能熟练应用数据结构与算法的人; 3、编程能力弱且不会分析源码的程序员; 4、数据结构与算法面试能力弱,且想进入 BAT 等国内一线大厂的人; 5、 准备从事 AI 相关工作的程序员。

课程介绍

限时福利:

1、现在购课,按提示添加助教微信领取 800 元编程大礼包!

2、原价 199 的课程,今日特价仅需 99 元!


课程背景:

如果想要成为一名合格的工程师,前提是一定要有扎实的数据结构与算法基础。作为程序员的核心基础,算法更是在面试中必不可少的一环。


根据市面上的招聘信息显示,超过 90% 的一线公司在招人时都会考察数据结构与算法能力。


所以,我将结合自己多年的数据结构与算法实战经验以及在阿里巴巴担任面试官的经验,从日常应用以及如何解决面试难题的角度,带你从零掌握这项程序员必备的核心技能!


课程详情:

课程内容涵盖了程序员需要掌握的所有常用数据结构与算法知识点!我将分为3大篇章进行讲解。


代码优化篇如何提高代码运行效率,是所有程序员都会面对的难题!在这篇,我将带你掌握应用算法把“烂”代码优化为高效率代码的方法,让你的代码显得不再那么“Low”。


基础+进阶+实战篇:我将为你讲解 30+ 常用数据结构与算法核心知识点,在每个知识点对应的实战部分,还将带你手写代码完成项目,并解读代码逻辑原理。同时每个知识点下还会穿插与之对应的BAT实战项目和常见面试题精讲。让你轻松将所学应用到工作、面试中去。


面试篇:目前几乎所有一线互联网公司面试时都会考察求职者的算法能力。我将结合我在阿里巴巴的工作和面试官经验,为你拆解大厂高频面试题以及答题方法,甚至直接提高你现场手写算法的能力。


通过这三大内容,相信无论你从事哪个技术方向,在面对代码效率优化以及算法相关问题上,都更加游刃有余!


学习时遇到不懂的怎么办?

购课后添加小助手微信,按提示进讲师答疑社群。


购课后如何领取免费赠送的编程大礼包?

购课后,添加助教微信: itxy41,按提示领取编程大礼包。


如何听课?

1、登录CSDN学院 APP 在我的课程中进行学习;

2、登录CSDN学院官网。





本课知识点

数据结构算法编程语言面试教学动画云计算/大数据数据库系统/网络/运维研发管理大学课程

课程目录

学员评价

3.8
  • 25%
  • 25%
  • 50%
  • 0%
  • 0%
  • knight_lixiaohong 2020-07-02 21:54

    [ 学习 24 分时评价 ] 学习资料不全
    3.0分

    请问加助教微信,每次都提示,对方被加好友过于频繁,请稍后再试。

  • JK-万里无云 2020-06-23 20:26

    [ 学习 01 小时 33 分时评价 ] 想学习更多实战案例学习资料不全
    3.0分

    这个更新的太慢了吧

  • Philip Xu 许永勤-湾区 2020-06-23 00:44

    [ 学习 01 小时 04 分时评价 ] 备课很充分经验丰富增加一些练习
    4.0分

    前两章很好,深入浅出, 演示程序作得也好。 问题: 为什么从第三章开始,很多章节的视屏都是空的?是否在更新中?

没有更多了

同学笔记

  • weixin_45328190 2020-07-03 17:28:18

    来源:链表(一):怎样在单链表和双链表中删除倒数第K个节点? 查看详情

    链表(一)&(二)&(三):单链表的概念与结构

     

    链表的概念

    链表是一种物理存储单元上非连续、非顺序的存储结构数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。

     

    链表类型

    单链表  双向链表  循环链表

     

    单链表

    单链表的构造

    【思路】

    一个结点,一块存储数据,并有一个指针引向下一个结点

    /*
    * 如何构造一个单链表?
    * 成员变量:
    * 1.head头结点
    * 2.data数据块
    * 3.next结点指引
    * */
    
    public Class Node{
        private Node head;
        private Object data;
        private Node next;
        
        public Node(Object data){
            this.data = data;
        }
        public Node(){}
        
        public void add(Object data){
            Node node = new Node(data);
            if(head == null){
                head = node;
                return;
            }
            Node temp = head; 
            while(temp.next != null){
                temp = temp.next;
            }
            temp.next = node;
        }
    
        public static void main(String[] args) {
            Node node = new Node();
            node.add(1);
            System.out.println(node.head.data);
            node.add(2);
            System.out.println(node.head.next.data);
            node.add(3);
            System.out.println(node.head.next.next.data);
            node.add(4);
            System.out.println(node.head.next.next.next.data);
            node.add(5);
            System.out.println(node.head.next.next.next.next.data);
        }
    }

    单链表的优劣

    单链表中,每个结点的数据域都是通过一个Object类的对象引用来指引数据元素的,与数组类似,单向链表中的结点也具有一个线性次序,即如果结点a1的next引用指向结点a2,则a1就是a2的直接前驱,a2是a1的直接后续。只能通过前驱节点找到后续节点,而无法从后续节点找到前驱节点。

    顺序存储(比如数组)内存空间固定,根据角标查找就可以直接找到。链式存储,需要一个一个的查询下一节点位置。

  • weixin_45328190 2020-07-03 16:29:15

    来源:栈和队列(七)+大厂面试真题:由两个栈组成的队列 查看详情

    栈和队列(七)&(八)由两个栈组成的队列

     

    题目:编写一个类,用两个栈实现队列,支持队列的基本操作(add、poll、peek)。

     

    【方法思路】

    栈的特点是先进后出,而队列的特点是先进先出。

    我们用两个栈,正好能把顺序反过来,即可实现队列的功能。

    具体实现上是一个栈作为压入栈,在压入数据时只往这个栈中压入,记为stackPush;

    另一个栈只作为弹出栈,在弹出数据时只从这个栈弹出, 记为stackPop.

    因为数据压入栈的时候, 顺序是先进后出的。

    那么只要把stackPush的数据再压入stackPop中, 顺序就变回来了。


    例如, 将1~5依次压入stackPush,那么从stackPush的栈顶到栈底为5~1, 此时依次再将5~1倒入
    stackPop,那么从stackPop的栈顶到栈底就变成了1~5。再从stackPop弹出时, 顺序就像队列一样。
     

     

    【两个栈组成队列常见设计错误】
    支撑理论步骤的两个必要点:
    1.如果stackPush要往stackPop中压入数据, 那么必须一次性把stackPush中的数据全部压入。

    2.如果stackPop不为空, stackPush 绝对不能向stackPop中压入数据。

    违反1的情况举例:  1~5依次压入stackPush, stackPush的栈顶到栈底为5~1,从stackPush压入
    stackPop时, 只将5和4压入了stackPop, stackPush 还剩下1、 2、 3没有压入。 此时如果用户想进
    行弹出操作, 那么4将最先弹出, 与预想的队列顺序就不一致。

    违反2的情况举例:  1~5 依次压入stackPush, stackPush将所有的数据压入了stackPop,此时从
    stackPop的栈项到栈底就变成了1~5。 此时又有6-10依次压入stackPush, stackPop不为空,
    stackPush 不能向其中压入数据。 如果违反2压入了stackPop, 从stackPop的栈顶到栈底就变成了
    6~10、 1~5。 那么此时如果用户想进行弹出操作, 6将最先弹出, 与预想的队列顺序就不一致。


     

    【代码】

    public class TwoStackToQueue {
        private Stack<Integer> stackPush;
        private Stack<Integer> stackPop;
    
        public TwoStackToQueue(Stack<Integer> stackPush, Stack<Integer> stackPop) {
            this.stackPush = stackPush;
            this.stackPop = stackPop;
        }
    
        public TwoStackToQueue() {
            super();
        }
    
        public void add(int pushInt){
            stackPush.push(pushInt);
        }
    
        public int poll(){
            if(stackPop.empty() && stackPush.empty()){
                throw new RuntimeException("队列已空!");
            }else if (stackPop.empty()){
                while (!stackPush.empty()){
                    stackPop.push(stackPush.pop());
                }
            }
            return stackPop.pop();
        }
    
        public int peek(){
            if (stackPop.empty() && stackPush.empty()){
                throw new RuntimeException("队列已空!");
            }else if (stackPop.empty()){
                while (!stackPush.empty()){
                    stackPop.push(stackPush.pop());
                }
            }
            return stackPop.peek();
        }
    
        public static void main(String[] args) {
            TwoStackToQueue twoStackToQueue = new TwoStackToQueue(new Stack<Integer>(),new Stack<Integer>());
            twoStackToQueue.add(1);
            twoStackToQueue.add(2);
            twoStackToQueue.add(3);
            twoStackToQueue.add(4);
            twoStackToQueue.add(5);
            System.out.println(twoStackToQueue.stackPush.toString());
            System.out.println(twoStackToQueue.peek());
            System.out.println(twoStackToQueue.stackPush.toString());
            System.out.println(twoStackToQueue.stackPop.toString());
        }
    }
    

     

  • weixin_45328190 2020-07-03 11:41:43

    来源:栈和队列(五):猫狗问题 查看详情

    栈和队列(五)&(六):猫狗队列

     

    猫狗队列问题

    题目:运用队列的功能,在指定用户的类的基础上,实现以下各种功能

    要求:

    1.用户可以调用add方法将cat类或dog类的实例放入队列中;

    2用户可以调用pollAll方法, 将队列中所有的实例按照进队列的先后顺序依次弹出;

    3.用户可以调用pollDog方法,将队列中dog类的实例按照进队列的先后顺序依次弹出;

    4.用户可以调用pollCat方法, 将队列中cat类的实例按照进队列的先后顺序依次弹出;

    5用户可以调用IsSEmpy方法, 检查队列中是否还有dog或cat的实例:

    6.用户可以调用isDogEmpty方法,检查队列中是否有dog类的实例:

    7.用户可以调用IsCaEmpty方法。检查队列中是否有cart类的实例。

     

     

    猫狗队列问题常见的设计错误

    错误1: cat队列只放cat实例,dog队列只放dog实例,再用一个总队列放所有的实例。

    错误原因:cat、dog以及总队列的更新问题。虽然pollAll可以满足,pollCat的时候,Cat队列可以全部弹出,但是Pet队列如何同步,pollDog也是同样的问题。

    错误2: 用哈希表, key表示一个cat实例或dog实例, value表示这个实例进队列的次序。

    错误原因: 不能支持—个实例多次进队列的功能需求,因为哈希表的key只能对应一个value值

    错误3: 将用户原有的cat或dog类改写,加一个计数项来表示某一个实例进队列的时间。

    错误原因: 不能擅自改变用户的类结构。

     

    【方法思路】

    新定义一个类,将原有的用户的类作为成员变量之一,再添加一个count作为时间戳进行排序,根据时间戳来poll

    每次比较count, 哪边小弹出哪边

    【代码】

    Pet类

    public class Pet {
        private String type;
    
        public Pet(String type) {
            this.type = type;
        }
    
        public Pet() {
            super();
        }
    
        public String getType() {
            return type;
        }
    
    }
    

    Cat类

    public class Cat extends Pet {
    
        public Cat() {
            super("cat");
        }
    }

    Dog类

    public class Dog extends Pet {
    
        public Dog() {
            super("dog");
        }
    }
    

    新定义的PetEnterQueue类,Pet作为属性,并设置时间戳属性

    public class PetEnterQueue {
        private Pet pet;
        private long count; //时间戳
    
        public PetEnterQueue(Pet pet, long count) {
            this.pet = pet;
            this.count = count;
        }
    
        public Pet getPet() {
            return pet;
        }
    
        public long getCount() {
            return count;
        }
    
        public String getPetEnterQueue(){
            return this.getPetEnterQueue();
        }
    }

    CatDogQueue

    import sun.rmi.runtime.NewThreadAction;
    import java.util.Arrays;
    import java.util.LinkedList;
    import java.util.Queue;
    
    /**
     * 代码只是为了实现我们的想法
     * 不是学习算法和数据结构中最重要的东西
     *
     * */
    public class CatDogQueue {
        private Queue<PetEnterQueue> dogQ;
        private Queue<PetEnterQueue> catQ;
        private long count;
    
        public CatDogQueue() {
            this.dogQ = new LinkedList<PetEnterQueue>();
            this.catQ = new LinkedList<PetEnterQueue>();
            this.count = 0;
        }
    
        public void add(Pet pet) {
            if (pet.getType().equals("dog")) {
                this.dogQ.add(new PetEnterQueue(pet, this.count++));
            } else if (pet.getType().equals("cat")) {
                this.catQ.add(new PetEnterQueue(pet, this.count++));
            } else {
                throw new RuntimeException("err, not dog or cat");
            }
        }
    
        public Pet pollAll() {
            if (!this.dogQ.isEmpty() && !this.catQ.isEmpty()) {
                if (this.dogQ.peek().getCount() < this.catQ.peek().getCount()) {
                    return this.dogQ.poll().getPet();
                } else {
                    return this.catQ.poll().getPet();
                }
            } else if (!this.dogQ.isEmpty()) {
                return this.dogQ.poll().getPet();
            } else if (!this.catQ.isEmpty()) {
                return this.catQ.poll().getPet();
            } else {
                throw new RuntimeException("err, queue is empty!");
            }
        }
    
    
        public Pet pollDog() {
            if (!this.isDogQueueEmpty()) {
                return this.dogQ.poll().getPet();
            } else {
                throw new RuntimeException("Dog queue is empty ! ");
            }
        }
    
        public Pet pollCat() {
            if (!this.isCatQueueEmpty()) {
                return  this.catQ.poll().getPet();
            } else {
                throw new RuntimeException("Cat queue is empty!");
            }
        }
    
        public boolean isEmpty() {
            return this.dogQ.isEmpty() && this.catQ.isEmpty();
        }
    
        public boolean isDogQueueEmpty() {
            return this.dogQ.isEmpty();
        }
    
    
        public boolean isCatQueueEmpty() {
            return this.catQ.isEmpty();
        }
    
        public static void main(String[] args) {
            CatDogQueue catDogQueue = new CatDogQueue();
            System.out.println(catDogQueue.count);
            catDogQueue.add(new Pet("cat"));
            catDogQueue.add(new Pet("cat"));
            catDogQueue.add(new Pet("cat"));
            catDogQueue.add(new Pet("dog"));
            catDogQueue.add(new Pet("cat"));
            catDogQueue.add(new Pet("dog"));
            catDogQueue.add(new Pet("cat"));
            catDogQueue.add(new Pet("dog"));
            catDogQueue.add(new Pet("dog"));
            System.out.println(catDogQueue.count);
            System.err.println(catDogQueue.catQ.size());
            for (int i = 0; i< catDogQueue.catQ.size() - 1 ; i++){
                System.out.println(catDogQueue.pollDog().getType());
            }
            for (int i = 0; i< catDogQueue.count ; i++){
                System.out.println(catDogQueue.pollAll().getType());
            }
        }
    }

     

没有更多了