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

之前数据结构其实学得不错,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变大时,方法一显然比方法二时间复杂度大得多,递归这种方法能不用最好就不用。
斐波那契数列这个例子就可以证明算法的重要性

数据结构

线性表

在这里插入图片描述

数组

在这里插入图片描述

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

动态数组

假如不用java官方的动态数组,自己设计的话,接口怎么设计?
设计如下:
在这里插入图片描述

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

在这里插入图片描述

泛型肯定也是要用的技术

在这里插入图片描述

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

链表(Linked List)

动态数组有个明显的缺点,可能会造成内存空间的大量浪费,链表则可以做到用到多少申请多少。
在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

提交的答案

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的结点对象

在这里插入图片描述

反转链表需要一个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;
    }
}

在这里插入图片描述

提交的答案

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的时间复杂度分析

在这里插入图片描述

双向链表

在这里插入图片描述

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

ArrayList和LinkedList的优缺点对比

在这里插入图片描述

单向循环链表

在这里插入图片描述

双向循环链表

在这里插入图片描述

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

在这里插入图片描述

静态链表

静态链表,了解一下即可

在这里插入图片描述

ArrayList的优化思路

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

在这里插入图片描述

栈的接口设计

在这里插入图片描述

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

在这里插入图片描述

leetcode练习

在这里插入图片描述

提交的答案

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;
    }
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

幸数得五

谢谢您的打赏勒

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值