1、数组、链表与跳表

1 数据结构

1.1 数组(Array)

  • 数组:Array,是有序的元素序列,数组是在内存中开辟一段连续的空间,并在此空间存放元素。就像是一排出租屋,有100个房间,从001到100每个房间都有固定编号,通过编号就可以快速找到租房子的人。

特点:

  • 查找元素快:通过索引,可以快速访问指定位置的元素

在这里插入图片描述

  • 增删元素慢
  • 指定索引位置增加元素:需要创建一个新数组,将指定新元素存储在指定索引位置,再把原数组元素根据索引,复制到新数组对应索引的位置。如下图
  • 指定索引位置删除元素: 需要创建一个新数组,把原数组元素根据索引,复制到新数组对应索引的位置,原数组中指定索引位置元素不复制到新数组中

在这里插入图片描述

1.2 链表(Linked List)

1.2.1 增加元素

在这里插入图片描述

1.2.2 删除元素 即为增加的逆操作

1.3.3 链表代码实现

class LinkedList { 
    Node head; // 表头
  
    /* 表结点*/
    class Node { 
        int data; 
        Node next; 
        
        Node(int d) { data = d; } 
    } 
}

1.3 跳表(Skip List)

为了优化链表缺陷(lookup查找)时间复杂度为O(n),就有了跳表
实质就是空间换时间,例如添加一个尾指针同时向前查找
跳表的实现:
增加索引:每一集索引跳前一级索引的倍数:2-4-8-16
在这里插入图片描述
增加多级索引:

1.3.1 时间复杂度的分析

每一集索引跳前一级索引的倍数:2-4-8-16,对应结点个数(假设要查的元素在最后一位)为n/2-4-6-8
第k级索引的结点个数就是n/(2k)
假设索引的深度为h,最高级的索引只有两个结点(一步就找到)得到n/(2h) = 2
所以h = log2(n) - 1
时间复杂度为O(logn)

1.3.2 空间复杂度的分析

在这里插入图片描述

1.4 重点

在这里插入图片描述

  1. 是三者之间增加删除的时间复杂度
  2. 两种思想:
    1. 空间换时间
    2. 升维

2 算法题详解

2.1 Array

1)爬楼梯问题

/*

  • [70] 爬楼梯

  • 思路:列出规律

  • 1:1

  • 2:2

  • 3:3

  • 4:5

  • 5:8

  • 可以看出是一个斐波拉契数列:F(n) = F(n-1) + F(n-2)

  • 实现:
    例如数字8是由 前两项相加得到的 3+5,而3和5也分别由他们的前两项相加得到
    实现方法
    定义三个变量,通过循环实现F(3) = F(2) + F(1)改变三个变量的值
    三个为一个循环
    f3 = f1 + f2
    f1 = f2
    f2 = f3

    public int climbStairs(int n) {
        int f1 = 1;
        int f2 = 2;
        int f3 = 3;
        if (n < 3) return n;
        for (int i = 3; i < n + 1; i++) { // ,前两次为1,2,从第三阶开始,得到3才能构成斐波拉契数列
            f3 = f1 + f2; // 先实现第三层
            f1 = f2;      // 替换之前的f1,f2相当于都往后移动一格
            f2 = f3;

        }
        return f3;
    }

  1. 使用数组,数组lookup的时间复杂度为0(1),

设置长度为n(以数组下标为准,n-1即对应n阶层)的可变数组,方法和上面相同
存入数组

 
// @lc code=start
class Solution {
    public int climbStairs(int n) {
        if (n < 3) return n;
        int result = 0;
        int[] array = new int[n];
        array[0] = 1;
        array[1] = 2;
        array[2] = 3;
        for (int i = 2; i < n; i++) {
            array[i] = array[i-1] + array[i-2];
            result = array[i];
        }
        return result;
    }
}

2)加一

  • [66] 加一
  • 需要考虑两种情况:
  • 1.末位为9
  • 2.末位为非9
  • 末位为非9数字很简单,+1即可
  • 末位为9,需要考虑进位 以及 之前元素是否为9,
  • 解题方法:递归
import sun.security.util.Length;

// @lc code=start
class Solution {
    int count = 0; // 记录递归的次数
    public int[] plusOne(int[] digits) {
        int len = digits.length - count++; // 当前列表长度
        if (digits[len-1] != 9) digits[len-1] += 1;
        else {
            while (len-1 > 0) {
                digits[len-1] = 0;
                return plusOne(digits);
            }
            // 如果递归到数组中第一个元素仍为9,那么就只有一种情况,需要开辟新的数组例如[1,0,0]
            digits = new int[digits.length + 1]; 
            digits[0] = 1;
            return digits;
        }
        return digits;
    }
}
// @lc code=end
发布了90 篇原创文章 · 获赞 4 · 访问量 1439

猜你喜欢

转载自blog.csdn.net/weixin_44145258/article/details/103482086