数据结构与算法学习记录分享

129 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

例举题目来自leetcode

数组、链表、跳表

数组 Array

  • 数组-时间复杂度
  • prepend O(1) 向头部或尾部添加
    正常情况下数组的prepend的操作的时间复杂度是O(n) 但是 可以进行特殊的优化到O(1)。采用的方式是申请稍大的一些内存空间,然后在数组的最开始预留一部分空间,然后prepend的操作则是把头下标前移一个位置即可。
  • append O(1) 任意位置添加
  • lookup O(1) 访问任意位置
  • insert O(n) 插入
  • delete O(n) 删除

链表 Linked List

  • 普通链表-时间复杂度

  • prepend O(1) 向头部或尾部添加

  • append O(1) 任意位置添加

  • lookup O(n) 访问任意位置

  • insert O(1) 插入

  • delete O(1) 删除

跳表 Skip List

  • 链表元素有序的时候
  • 跳表的特点 注意:只能用于元素有序的情况。 所以,跳表(skip list)对标的是平衡树(AVL Tree)和二分查找, 是一种 插入/删除/搜索 都是 O(log n) 的数据结构。1989 年出现。 它最大的优势是原理简单、容易实现、方便扩展、效率更高。因此 在一些热门的项目里用来替代平衡树,如 Redis、LevelDB 等。
  • 在跳表中查询任意数据的时间复杂度就是 O(logn)
  • 空间复杂度是 O(n)

工程中的应用

  • LRU Cache - Linked list
  • Redis - Skip List

习题

  • 移动零 思路 快慢指针
  1. 定义指针 i j 遍历整个数组
  2. 如果发现0 j 指针 记录 0 的位置 在下次的执行时交换 不为0的值 与 为0的值的位置
class Solution{
    public void moveZeroes(int[] nums){
        for (int i = 0, j = 0; i < nums.length; i++) {
            if (nums[i] != 0) {
               if (i != j) {
                   nums[j] = nums[i];
                   nums[i] = 0;
               }
               j++;
            }
        } 
    }
}

class Solution {
    public void moveZeroes(int[] nums) {
       for (int i = 0, j = 0; i < nums.length; i++ ) {
           if (nums[i] != 0) {    
              int temp = nums[i]; 
              nums[i] = 0;
              nums[j++] = temp;
           }
       }
    }
}
  • 盛水最多容器 思路一
  1. 双层for 循环 时间复杂度 O(n^2)
class Solution{
    public int maxArea(int[] height){
        int maxArea = 0;
        for (int i = 0; i < height.length - 1; i++) {
            for (int j = 1; j < height.length; j++) {
                int area = (j - i) * Math.min(height[i],height[j]);
                maxArea = Math.max(maxArea,area) 
            }
        }
        return maxArea;
    }
}

2.左右指针夹逼 时间复杂度O(n)

class Solution{
    public int maxArea(int[] height){
        int max = 0;
        for (int i = 0, j = height.length - 1; i < j; ) {
            int heights = height[i] < height[j]? height[i++]:height[j--];
            int area = (j - i + 1) * heights;
            max = Math.max(area,max);  
        }
        return max;
    }
}
  • 爬楼梯 -- 斐波那契数列
public Solution{
    public int climbStairs(int n){
        if (n < 3){
            return n;
        }
        int first = 1, second = 2, third = 3;
        for (int i = 3; i < n+1; i++) {
           third = first + second;
           first = second;
           second = third;
        }
        return third;
    }
}
  • 三数之和 a+b+c = 0
class Solution{
    public List<List<Integer>> threeSum ( int[] nums ) {
        if ( nums.length < 3 ){
            return new ArrayList<>();
        }
        Arrays.sort(nums);
        Set<List<Integer>> set = new HashSet<>();
        for ( int i = 0; i < nums.length - 2; i++; ) {
             int j = i + 1, k = nums.length - 1;
             while ( j < k ) {
                 int sum = nums[i] + nums[j] + nums[k];
                 if ( sum == 0 ) set.add( Arrays.asList( nums[i], nums[j++], nums[k--] ) );
                 else if ( sum > 0 ) k--;
                 else if ( sum < 0 ) j++;
             } 
        }
        return new ArrayList<>( set );
    }
}

class Solution {
    public List<List<Integer>> threeSum ( int[] nums ) {
        List<List<Integer>> res = new ArrayList<>();
        if ( nums.length < 3 ) return res;
        Arrays.sort( nums );
        for ( int i = 0; i < nums.length - 2; i++ ){
            if(nums[i] > 0) break;
            if(i > 0 && nums[i] == nums[i - 1]) continue;
              int j = i + 1, k = nums.length - 1;
             while ( j < k ) {
                 int sum = nums[i] + nums[j] + nums[k];
                 if ( sum > 0 ) {
                     while ( j < k && nums[k] == nums[--k] );
                 }else if( sum < 0 ){
                     while ( j < k && nums[j] == nums[++j] );
                 }else {
                     res.add(new ArrayList<>(Arrays.asList(nums[i], nums[j], nums[k])));
                     while ( j < k && nums[k] == nums[--k] );
                     while ( j < k && nums[j] == nums[++j] );
                 }
             }
        }
        return res;
    }
}
var threeSum = function ( nums ) {
    let res = [];
    if ( nums.length < 3 ) return res;
    nums.sort( (a,b) => a - b );
    for ( let i = 0; i < nums.length - 2; i++ ){
          if(nums[i] > 0) break;
          if(i > 0 && nums[i] == nums[i - 1]) continue;
          let j = i + 1, k = nums.length - 1;
          while ( j < k ) {
              let sum = nums[i] + nums[j] + nums[k];
              if ( sum > 0 ) {
                  while ( j < k && nums[k] == nums[--k] );
              } else if ( sum < 0 ) {
                  while ( j < k && nums[j] == nums[++j] );
              } else {
                  res.push( [nums[i], nums[j], nums[k]] );
                  while ( j < k && nums[k] == nums[--k] );
                  while ( j < k && nums[j] == nums[++j] );
              }
          }   
    }
    return res;
}