数据结构与算法学习(第一天)

之前数据结构其实学得不错,A+,但是已经快忘光了,所以重修一下(记录起来就不怕忘得快了,嘿嘿)

算法是用于解决特定问题的一系列的执行步骤

斐波那契数列

斐波那契数列(0,1,1,2,3,5,8,…),从第三项开始,每项等于前两项之和

求第n个斐波那契数的代码
方法一:

public static int fib1(int n){
    if(n<=1)
        return n;
    return fib1(n-1) + fib1(n-2);
}

方法二:

public static int fib2(int n){
    if(n<=1)
        return n;
    
    int first = 0;
    int second = 1;
    for(int i=1; i<n-1; i++){           //n从1开始
        int sum = first + second;
        first = second;
        second = sum;
    }
    return second;
}

忽略常数项后,方法一的时间复杂度为O(2^n),方法二的时间复杂度为O(n)
当n变大时,方法一显然比方法二时间复杂度大得多,递归这种方法能不用最好就不用。
斐波那契数列这个例子就可以证明算法的重要性

数据结构

数据结构与算法学习(第一天)_第1张图片

线性表

数据结构与算法学习(第一天)_第2张图片

数组

数据结构与算法学习(第一天)_第3张图片

局部变量在栈中,new出来的在堆中,java有垃圾回收机制,不用像c++一样需要delete防止内存泄漏

动态数组

假如不用java官方的动态数组,自己设计的话,接口怎么设计?
设计如下:
数据结构与算法学习(第一天)_第4张图片

自己写动态数组,肯定要先处理打印的问题
java中打印其实就是调用toString方法

数据结构与算法学习(第一天)_第5张图片

泛型肯定也是要用的技术

数据结构与算法学习(第一天)_第6张图片

还有一个问题是动态扩容,怎么处理?
处理起来其实很简单,申请新的足够大的堆空间,将原本的元素赋值过去即可。
其他的接口的实现,如add()、remove()等,相信都不是问题。自己写过动态数组类以后,使用java官方的ArrayList就更加随心所欲了。

链表(Linked List)

动态数组有个明显的缺点,可能会造成内存空间的大量浪费,链表则可以做到用到多少申请多少。
数据结构与算法学习(第一天)_第7张图片

链表使用虚拟头结点可以使代码逻辑统一

数据结构与算法学习(第一天)_第8张图片

简单刷几道leetcode链表题目
这几道题都没有虚拟头结点

数据结构与算法学习(第一天)_第9张图片

提交的答案

class Solution {
    public ListNode deleteNode(ListNode head, int val) {
            if(head.val == val)
                return head.next;

            if(head.next == null)
                return head;

            ListNode pre = head;
            ListNode cur = head.next;
            while(cur.val != val && cur.next != null){
                pre = cur;
                cur = cur.next;
            }

            if(cur.val == val)
                pre.next = cur.next;
            
            return head;
    }
}

删除链表结点需要记录删除结点的前一个结点,或者将删除结点的val改为下一个结点val,并修改next的结点对象

数据结构与算法学习(第一天)_第10张图片

反转链表需要一个newhead,并使用头插法实现反转
提交的答案

class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode newhead = null;
        ListNode tmp;
        while(head!=null){
            tmp = head.next;
            head.next = newhead;
            newhead = head;
            head = tmp;
        }
        return newhead;
    }
}

数据结构与算法学习(第一天)_第11张图片

提交的答案

public class Solution {
    public boolean hasCycle(ListNode head) {
        Set<ListNode> set = new HashSet<ListNode>();
        while(head!=null){
            if(!set.add(head)){
                return true;
            }
            head = head.next;
        }
        return false;
    }
}

ArrayList和LinkedList的时间复杂度分析

数据结构与算法学习(第一天)_第12张图片

双向链表

数据结构与算法学习(第一天)_第13张图片

java官方的LinkedList是双向链表,从JDK1.7开始,LinkedList 由双向循环链表改为双向链表

ArrayList和LinkedList的优缺点对比

数据结构与算法学习(第一天)_第14张图片

单向循环链表

数据结构与算法学习(第一天)_第15张图片

双向循环链表

数据结构与算法学习(第一天)_第16张图片

双向循环链表可解决约瑟夫问题

数据结构与算法学习(第一天)_第17张图片

静态链表

静态链表,了解一下即可

数据结构与算法学习(第一天)_第18张图片

ArrayList的优化思路

ArrayList的优化思路:存储首元素的位置

数据结构与算法学习(第一天)_第19张图片

栈的接口设计

数据结构与算法学习(第一天)_第20张图片

栈的应用-浏览器的前进和后退

数据结构与算法学习(第一天)_第21张图片

leetcode练习

数据结构与算法学习(第一天)_第22张图片

提交的答案

class Solution {
    public boolean isValid(String s) {
        if(s.isEmpty())
            return true;

        Stack<Character> stack = new Stack<Character>();
        for(char c: s.toCharArray()){
            if(c == '('){
                stack.push(')');
            }
            else if(c == '{'){
                stack.push('}');
            }
            else if(c == '['){
                stack.push(']');
            }
            else{
                if(stack.empty())
                    return false;
                if(c != stack.pop())
                    return false;
            }
        }
        if(!stack.empty())
            return false;
        return true;
    }
}

你可能感兴趣的:(数据结构与算法,学习,leetcode,java,数据结构,算法)