算法与数据结构刷题笔记-Java

这篇博客主要介绍了Java中算法和数据结构的应用,包括LRU缓存机制、环形链表、二叉树的中序遍历、N叉树的层序遍历、二叉树的最大深度等。同时涉及了递归、分治、回溯、深度优先搜索等算法,以及多线程和有限阻塞队列等知识点。
摘要由CSDN通过智能技术生成

第一章 、常见运算

//取模运算:余数,可以用作循环
5%2 = 1
5/2 = 2
i++ //输出后再加
++i //加完再输出  

146. LRU 缓存机制

  •  
  • class LRUCache { 
        private HashMap<Integer, Node> map;
        private DoubleList cache;
        // 最大容量
        private int cap;
    ​
        public LRUCache(int capacity) {
            this.cap = capacity;
            map = new HashMap<>();
            cache = new DoubleList();
        }
    ​
        public int get(int key) {
            if (!map.containsKey(key)) return -1;
            int val = map.get(key).val;
            // 利用 put 方法把该数据提前
            put(key, val);
            return val;
        }
    ​
        public void put(int key, int val) {
            // 先把新节点 x 做出来
            Node x = new Node(key, val);
            if (map.containsKey(key)) {
                // 删除旧的节点,新的插到头部
                cache.remove(map.get(key));
                cache.addFirst(x);
                // 更新 map 中对应的数据
                map.put(key, x);
            } else {
                //满了则删除链表最后一个数据
                if (cap == cache.size()) {
                    Node last = cache.removeLast();
                    map.remove(last.key);
                }
                // 直接添加到头部
                cache.addFirst(x);
                map.put(key, x);
            }
        }
    ​
        static class DoubleList {
            //确保链表不为空,头结点为first.next
            private Node first = new Node(0, 0);
            private Node end = new Node(0, 0);
            private int size;
    ​
            public DoubleList() {
                first.next = end;
                end.prev = first;
                size = 0;
            }
    ​
            // 在链表头部添加节点 x,时间 O(1)
            public void addFirst(Node x) {
                Node temp = first.next;
                first.next = x;//第二个才是插入的头结点
                x.next = temp;
                temp.prev = x;
                x.prev = first;
                size++;
            }
            // 删除链表中的 x 节点(x 一定存在)
            // 由于是双链表且给的是目标 Node 节点,时间 O(1)
            public void remove(Node x) {
                x.next.prev = x.prev;
                x.prev.next = x.next;
                size--;
            }
            // 删除链表中最后一个节点,并返回该节点,时间 O(1)
            public Node removeLast() {
                Node last = end.prev;
                remove(last);
                return last;
            }
    ​
            // 返回链表长度,时间 O(1)
            public int size() {
                return size;
            }
        }
    ​
        static class Node {
            public int key, val;
            public Node next, prev;
    ​
            public Node(int k, int v) {
                this.key = k;
                this.val = v;
            }
        }
    }

142. 环形链表 II

    •  
    •  
public class Solution {
    public ListNode detectCycle(ListNode head) {
        //快慢指针
        //每次移动两步,有环则一定会在环的 某一个位置 超越慢指针
        ListNode fast = head, slow = head;
        while(true){
            if(fast == null || fast.next == null) return null;
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow) break;
        }
        // 假如fast == head --> 有环
        fast = head;
        while(fast != slow){
           fast = fast.next; 
           slow = slow.next;
        }
        return fast;
    }
}

面试题 02.07. 链表相交

    • public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        //双指针:a和b以相同的速度走过相同的路程,如果最后一段路程相同则他们必然在共同路程的入口相遇;
        ListNode a = headA;
        ListNode b = headB;
        while(a != b){
          a = a == null ? headB : a.next;
          b = b == null ? headA : b.next;
        }
        return a;
      }

      206. 反转链表

      •  
      class Solution {
          public ListNode reverseList(ListNode head) {
              //双指针实现
              ListNode per = null;
              ListNode cur = head;
              ListNode temp = null;
              while(cur != null){
                  temp = cur.next;
                  //改变指向,局部反转
                  cur.next = per;
                  //指针向前移动
                  per = cur;
                  cur = temp;
              }
              return per;
          }
      }
      

      141. 环形链表

      •  
      public boolean hasCycle(ListNode head) {
        //快慢指针
        ListNode f = head, s = head;
        while(true){
          if(f == null || f.next == null) return false;
          f = f.next.next;
          s = s.next;
          if(f == s) return true;
        }
      }
      

      21. 合并两个有序链表

        •  
      public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
              //迭代法
              ListNode head = new ListNode(-1);
              //维护一个指针,一直指向链表的最后一个位置
              ListNode per = head;
              while(l1 != null && l2 != null){
                  if(l1.val >= l2.val){
                      per.next = l2;
                      l2 = l2.next;
                  }else{
                      per.next = l1;
                      l1 = l1.next;
                  }
                  //指针后移一位
                  per = per.next;
              }
              //链表末尾指向不为空的链表
              per.next = l1 == null ? l2 : l1;
              return head.next;
      }
      
      •  
      public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
              //递归解法,较小的节点指向其余待合并元素
              if(l1 == null) return l2;
              if(l2 == null) return l1;
      
              if(l1.val > l2.val){
                 l2.next = mergeTwoLists(l1, l2.next);
                 return l2;
              }else{
                 l1.next =  mergeTwoLists(l1.next, l2);
                 return l1;
              }
      }
      

      二、树、二叉树、二叉搜索树

      1、 解题模板

      •  
      /* 基本的二叉树节点 */
      class TreeNode {
          int val;
          TreeNode left, right;
      }
      void traverse(TreeNode root) {
          traverse(root.left);
          traverse(root.right);
      }
      
      •  
      /* 基本的 N 叉树节点 */
      class TreeNode {
          int val;
          TreeNode[] children;
      }
      void traverse(TreeNode root) {
          for (TreeNode child : root.children)
              traverse(child);
      }
      

      2、力扣刷题

      94. 二叉树的中序遍历

      • class Solution {
            public List<Integer> inorderTraversal(TreeNode root) {
               List<Integer> res = new ArrayList();
               order(root, res);
               return res;
            }
        
            private void order(TreeNode root, List<Integer> res){
                //中序遍历 做根右
                if(null == root) return;
                order(root.left, res);
                res.add(root.val);
                order(root.right, res);
            }
        }
        

      590. N 叉树的后序遍历

      • class Solution {
            public List<Integer> postorder(Node root) {
               List<Integer> res = new ArrayList();
               inOrder(root, res);
               return res;
            }
        		
            private void inOrder(Node node, List<Integer> res){
                if(null == node) return;
              	//遍历孩子节点
                for(Node n : node.children){
                    inOrder(n, res);
                }
                res.add(node.val);
            }
        }
        

      429. N 叉树的层序遍历

      • class Solution {
            public List<List<Integer>> levelOrder(Node root) {
                List<List<Integer>> res = new ArrayList();
                if(root == null) return res;
                inOrder(root, res, 0);
                return res;
            }
            
            private void inOrder(Node root,List<List<Integer>> res, int level){
                if(root == null) return;
                //遍历当前层
                if(res.size() < level + 1){
                    res.add(new ArrayList()); //防止下标越界
                }
                res.get(level).add(root.val);       
                for(Node n : root.children){
                    inOrder(n, res, level + 1);//注意不能是level++
                }      
            }
        }
        

      226. 翻转二叉树

      • class Solution {
            public TreeNode invertTree(TreeNode root) {
              	//递归终止条件  
              	if(null == root) return root;
              	//当前层逻辑:位置交换  
              	TreeNode temp = root.left;
                root.left = root.right;
                root.right = temp;
              	//下探一层
                invertTree(root.left);
                invertTree(root.right);
                return root;
            }
        }
        

      98. 验证二叉搜索树

        •  
      class Solution {
          long per = Long.MIN_VALUE;//注意
          public boolean isValidBST(TreeNode root) {
              //根据中序遍历的特点(左,根,右)--》前一个节点小于后一个节点
              if(root == null) return true;
              //左节点
              if(!isValidBST(root.left)){
                  return false;
              }
              //根节点处理,左要小于根
              if(per >= root.val){
                  return false;
              }
              //记录前节点
              per = root.val;
              //右节点
              return isValidBST(root.right);
          }
      }
      

      104. 二叉树的最大深度

        •  
      class Solution {
          //深度优先搜索
          public int maxDepth(TreeNode root) {
              if(root == null) return 0;
              return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
          }
      }
      

      三、栈、队列

      1、解题模板

      2、力扣刷题

      四、哈希表、映射、集合

      1、解题模板

      2、力扣刷题

      五、堆、二叉堆、图

      1、解题模板

      2、力扣刷题

      第三章 常用算法

      一、递归

      二、分治、回溯

      三、深度优先和广度优先搜索

      1、解题模板

        •  
        void dfs(TreeNode root) {
            if (root == null) {
                return;
            }
            dfs(root.left);
            dfs(root.right);
        }
        
        •  
      void bfs(TreeNode root) {
          Queue<TreeNode> queue = new ArrayDeque<>();
          queue.add(root);
          while (!queue.isEmpty()) {
              TreeNode node = queue.poll(); // Java 的 pop 写作 poll()
              if (node.left != null) {
                  queue.add(node.left);
              }
              if (node.right != null) {
                  queue.add(node.right);
              }
          }
      }
      
      // 二叉树的层序遍历
      void bfs(TreeNode root) {
          Queue<TreeNode> queue = new ArrayDeque<>();
          queue.add(root);
          while (!queue.isEmpty()) {
            //在每一层遍历开始前,先记录队列中的结点数量 nn(这一层的结点数量),然后一口气处理完这一层的结点
              int n = queue.size();
              for (int i = 0; i < n; i++) { 
                  // 变量 i 无实际意义,只是为了循环 n 次
                  TreeNode node = queue.poll();
                  if (node.left != null) {
                      queue.add(node.left);
                  }
                  if (node.right != null) {
                      queue.add(node.right);
                  }
              }
          }
      }
      

      2、力扣刷题

      102. 二叉树的层序遍历

      • class Solution {
            public List<List<Integer>> levelOrder(TreeNode root) {
                List<List<Integer>> res = new ArrayList();
                return inOrder(root, 0, res);
            }
        
            private List<List<Integer>> inOrder(TreeNode root, int level, List<List<Integer>> res){
                if (null == root) return res;
        
                if(res.size() <= level){
                    res.add(new ArrayList());
                }
                
                res.get(level).add(root.val);
                inOrder(root.left, level + 1, res);
                inOrder(root.right, level +  1, res);
                return res;
            }
        }
        
      •  
      • public List<List<Integer>> levelOrder(TreeNode root) {
            List<List<Integer>> res = new ArrayList<>();
        
            Queue<TreeNode> queue = new ArrayDeque<>();
            if (root != null) {
                queue.add(root);
            }
            while (!queue.isEmpty()) {
                int n = queue.size();//记录一层的节点数量,然后一次性遍历完成
                List<Integer> level = new ArrayList<>();
                for (int i = 0; i < n; i++) { 
                    TreeNode node = queue.poll();
                    level.add(node.val);
                    if (node.left != null) {
                        queue.add(node.left);
                    }
                    if (node.right != null) {
                        queue.add(node.right);
                    }
                }
                res.add(level);
            }
        
            return res;
        }
        

      四、贪心算法

      五、二分查找

      六、动态规划

      七、排序算法

      1、解题模板

        •  
      private static void mpsort(int[] a) {
              for (int i = 0; i < a.length; i++) {
                  for (int j = 0; j < a.length - i - 1; j++) {
                      //内层循环,升序(如果前一个值比后一个值大,则交换)
                      if (a[j] > a[j + 1]) {
                          swap(a, j, j + 1);
                      }
                  }
              }
      }
      private static void swap(int[] a, int j, int i) {
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
      }
      
        •  
        public static void main(String[] args) {
                int arr[] = {7, 5, 3, 2, 4};
                //插入排序
                for (int i = 1; i < arr.length; i++) {
                    //外层循环,从第二个开始比较
                    for (int j = i; j > 0; j--) {
                        //内存循环,与前面排好序的数据比较,如果后面的数据小于前面的则交换
                        if (arr[j] < arr[j - 1]) {
                            int temp = arr[j - 1];
                            arr[j - 1] = arr[j];
                            arr[j] = temp;
                        } else {
                            //如果不小于,说明插入完毕,退出内层循环
                            break;
                        }
                    }
                }
            }
        
          •  
        /**
           * 归并排序
           * 分治思想
           */
        private static void mergeSort(int[] arr) {
          int[] temp = new int[arr.length];
          subSort(arr, temp, 0,arr.length -1);
        }
        
        private static void subSort(int[] arr, int[] temp, int left, int right) {
          if (left < right){
            int mid = (left + right) >> 1;
            //左边排序
            subSort(arr, temp, left, mid);
            //右边排序
            subSort(arr, temp, mid + 1, right);
            //合并
            merge(arr, temp, left, mid, right);
          }
        
        }
        
        /**
          * 合并两个有序数组
          */
        private static void merge(int[] arr, int[] temp, int left, int mid, int right) {
          //左序列指针
          int i = left;
          //右序列指针
          int j = mid + 1;
          int k = 0;
        	
          while (i <= mid && j <= right){
            temp[k++] = arr[i] <= arr[j] ? arr[i++] : arr[j++];
          }
          //把左边填入,只会有一个越界
          while (i <= mid){
            temp[k++] = arr[i++];
          }
          //把右边填入
          while (j <= right){
            temp[k++] = arr[j++];
          }
          k = 0;
          //将temp中的元素全部拷贝到原数组中
          while(left <= right){
            arr[left++] = temp[k++];
          }
        }
        

        2、力扣刷题

        八、字符串算法

        第五章、其他相关知识

        一、多线程

        1、常用思路

        •  
        •  
        •  
        •  

        2、力扣刷题

        1114. 按序打印

            •  
            •  
            •  
        class Foo {
            private boolean firstFinish = false;
            private boolean secondFinish = false;
            Object lock = new Object();
          
            public Foo() {       
            }
        
            public void first(Runnable printFirst) throws InterruptedException {
                synchronized(lock){
                        printFirst.run();
                        firstFinish = true;
                        //通知所有在等待lock的线程
                        lock.notifyAll(); 
                }      
            }
        
            public void second(Runnable printSecond) throws InterruptedException {   
                   synchronized(lock){
                       //当1还未执行结束,则自旋等待,防止出现中途跳出
                       while(!firstFinish){
                           lock.wait();
                       }
                     while()
                        printSecond.run();
                        secondFinish = true;
                        lock.notifyAll(); 
                    } 
            }
        
            public void third(Runnable printThird) throws InterruptedException {  
                   synchronized(lock){
                       //当2还未执行结束则自旋等待
                       while(!secondFinish){
                           lock.wait();
                       }
                       printThird.run(); 
                    } 
            }
        }
        
          •  
          •  
        class Foo {
          	//保证可见性及禁止指令重排序
          	volatile int count=1;
            public Foo() {    
            }
            
            public void first(Runnable printFirst) throws InterruptedException {
                printFirst.run();
                count++;
            }
        
            public void second(Runnable printSecond) throws InterruptedException {
              //自旋,volatile更新数据后会通知到其他线程获取最新的值 
              while (count!=2);
                printSecond.run();
                count++;
            }
        
            public void third(Runnable printThird) throws InterruptedException {
              //自旋,volatile更新数据后会通知到其他线程获取最新的值    
              while (count!=3);
                printThird.run();
            }
        }
        
        •  
        class Foo {
            int num;
            Lock lock;
            //精确的通知和唤醒线程
            Condition condition1, condition2, condition3;
        
            public Foo() {
                num = 1;
                lock = new ReentrantLock();
                condition1 = lock.newCondition();
                condition2 = lock.newCondition();
                condition3 = lock.newCondition();
            }
        
            public void first(Runnable printFirst) throws InterruptedException {
                lock.lock();
                try {
                  	//自旋等待
                    while (num != 1) {
                        condition1.await();
                    }
                    printFirst.run();
                    num = 2;
                    condition2.signal();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        
            public void second(Runnable printSecond) throws InterruptedException {
                lock.lock();
                try {
                    while (num != 2) {
                        condition2.await();
                    }
                    printSecond.run();
                    num = 3;
                    condition3.signal();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        
            public void third(Runnable printThird) throws InterruptedException {
                lock.lock();
                try {
                    while (num != 3) {
                        condition3.await();
                    }
                    printThird.run();
                    num = 1;
                    condition1.signal();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }
        
          •  
        lass Foo {
            CountDownLatch a;
            CountDownLatch b;
        
            public Foo() {
                //等待一个线程执行完
                a = new CountDownLatch(1);
                b = new CountDownLatch(1);
            }
        
            public void first(Runnable printFirst) throws InterruptedException {
                printFirst.run();
                a.countDown();//执行完-1
            }
        
            public void second(Runnable printSecond) throws InterruptedException {
                a.await();
                printSecond.run();
                b.countDown();
            }
        
            public void third(Runnable printThird) throws InterruptedException {
                b.await();
                printThird.run();
            }
        }
        
          •  
          •  
        class Foo {
            private Semaphore sa;
            private Semaphore sb;
            public Foo() {
                sa = new Semaphore(0);//等待first执行完后再+许可
                sb = new Semaphore(0);  
            }
        
            public void first(Runnable printFirst) throws InterruptedException {
                printFirst.run();
                sa.release();//给second加许可,释放一个sa的信号量
            }
        
            public void second(Runnable printSecond) throws InterruptedException {
                sa.acquire();
                printSecond.run();
                sb.release();//给third加许可
            }
        
            public void third(Runnable printThird) throws InterruptedException {
                sb.acquire();
                printThird.run();
            }
        }
        
        • class Foo {
              BlockingQueue<String> blockingQueue12, blockingQueue23;
          
              public Foo() {
                  //同步队列,没有容量,进去一个元素,必须等待取出来以后,才能再往里面放一个元素
                  blockingQueue12 = new SynchronousQueue<>();
                  blockingQueue23 = new SynchronousQueue<>();
              }
          
              public void first(Runnable printFirst) throws InterruptedException {
                  printFirst.run();
                  blockingQueue12.put("stop");
              }
          
              public void second(Runnable printSecond) throws InterruptedException {
                  blockingQueue12.take();
                  printSecond.run();
                  blockingQueue23.put("stop");
              }
          
              public void third(Runnable printThird) throws InterruptedException {
                  blockingQueue23.take();
                  printThird.run();
              }
          }
          

        1115. 交替打印FooBar

        •  
        class FooBar {
            private int n;
            public FooBar(int n) {
                this.n = n;
            }
            Semaphore foo = new Semaphore(1);
            Semaphore bar = new Semaphore(0);
        
            public void foo(Runnable printFoo) throws InterruptedException {
                for (int i = 0; i < n; i++) {
                    foo.acquire();
                    printFoo.run();
                    bar.release();
                }
            }
        
            public void bar(Runnable printBar) throws InterruptedException {
                for (int i = 0; i < n; i++) {
                    bar.acquire();
                    printBar.run();
                    foo.release();
                }
            }
        }
        
        •  
        class FooBar {
            private int n;
            public FooBar(int n) {
                this.n = n;
            }
        
            Lock lock = new ReentrantLock(true);
            volatile boolean permitFoo = true;
        
            public void foo(Runnable printFoo) throws InterruptedException {
                for (int i = 0; i < n; ) {
                    lock.lock();
                    try {
                      if(permitFoo) {
                          printFoo.run();
                            i++;
                            permitFoo = false;
                      }
                    }finally {
                      lock.unlock();
                    }
                }
            }
        
            public void bar(Runnable printBar) throws InterruptedException {
                for (int i = 0; i < n; ) {
                    lock.lock();
                    try {
                      if(!permitFoo) {
                          printBar.run();
                          i++;
                          permitFoo = true;
                      }
                    }finally {
                      lock.unlock();
                    }
                }
            }
         }
        
        •  
        class FooBar {
            private int n;
        
            public FooBar(int n) {
                this.n = n;
            }
        
            volatile boolean permitFoo = true;
        
            public void foo(Runnable printFoo) throws InterruptedException {
                for (int i = 0; i < n; ) {
                    if (permitFoo) {
                        printFoo.run();
                        i++;
                        permitFoo = false;//下一次一定是要等待其他线程完成修改
                    }
                }
            }
        
            public void bar(Runnable printBar) throws InterruptedException {
                for (int i = 0; i < n; ) {
                    if (!permitFoo) {
                        printBar.run();
                        i++;
                        permitFoo = true;
                    }
                }
            }
        }
        
          •  
          •  
          •  
        class FooBar {
            private int n;
        
            public FooBar(int n) {
                this.n = n;
            }
        
            CyclicBarrier cb = new CyclicBarrier(2);
            volatile boolean fin = true;
        
            public void foo(Runnable printFoo) throws InterruptedException {
                for (int i = 0; i < n; i++) {
                    while (!fin) ;//自旋等待,必须要加锁否则下一次任然可能是自己抢占了时间片
                    printFoo.run();
                    fin = false;
                    try {
                        cb.await();//阻塞自己,等待其他线程到达屏障点-->到达后进入下一次循环;
                    } catch (BrokenBarrierException e) {
                    }
                }
            }
        
            public void bar(Runnable printBar) throws InterruptedException {
                for (int i = 0; i < n; i++) {
                    try {
                        cb.await();//阻塞自己,等待其他线程到达屏障点-->到达后执行打印逻辑
                    } catch (BrokenBarrierException e) {
                    }
                    printBar.run();
                    fin = true;//类似于唤醒在自旋的线程
                }
            }
        }
        
        •  
        public class FooBar {
            private int n;
            private BlockingQueue<Integer> bar = new LinkedBlockingQueue<>(1);
            private BlockingQueue<Integer> foo = new LinkedBlockingQueue<>(1);
            public FooBar(int n) {
                this.n = n;
            }
            public void foo(Runnable printFoo) throws InterruptedException {
                for (int i = 0; i < n; i++) {
                    foo.put(i);//在take前都只能阻塞
                    printFoo.run();
                    bar.put(i);
                }
            }
        
            public void bar(Runnable printBar) throws InterruptedException {
                for (int i = 0; i < n; i++) {
                    bar.take();
                    printBar.run();
                    foo.take();//执行完释放,类似于通知
                }
            }
        }
        

        1188. 设计有限阻塞队列

        •  
        class BoundedBlockingQueue {
            //通过链表实现,可以从头结点添加,尾结点删除
            private LinkedList<Integer> list;
            private int capacity;
            private volatile int size;
        
            Object lock = new Object();
        
            public BoundedBlockingQueue(int capacity) {
                this.list = new LinkedList();
                this.capacity = capacity;
                this.size = 0;
            }
            
            public void enqueue(int element) throws InterruptedException {
                synchronized(lock){
                    while(size + 1 > capacity) lock.wait();//自旋等待
                    size++;
                    list.addFirst(element);
                    lock.notify();
                }
            }
            
            public int dequeue() throws InterruptedException {
                synchronized(lock){
                   while(size <= 0) lock.wait();//自旋等待 
                   int res = list.removeLast();
                   size--;
                   lock.notify();
                   return res;
                }
            }
            
            public int size() {
                return size;
            }
        }
        

        二、布隆过滤器

        三、LRU缓存

2、力扣刷题

 

  • 遍历

    /* 基本的单链表节点 */
    class ListNode {
        int val;
        ListNode next;
    }
    ​
    void traverse(ListNode head) {
        for (ListNode p = head; p != null; p = p.next) {
            // 迭代访问 p.val
        }
    }
    ​
    void traverse(ListNode head) {
        // 递归访问 head.val
        traverse(head.next);
    }

     

1、解题模板

  • 原始数组

    //1、 数据类型 [] 数组名=new 数据类型[ length];
    int[] ary = new int[4];//初始化值为0
    //2、初始化
    int[] ary2 = {0, 1, 2};
    //数组扩容,拷贝
    int[] newInts = Arrays.copyOf(ary2, 5);//表面上对数组长度进行扩容,实际新开辟一个空间
    System.out.println(Arrays.toString(newInts));//[0, 1, 0, 0, 0]
    //数组复制
    System.arraycopy(ary2, 1, ary, 1, 2);//把ary2中的内容从下标1开始复制到ary中,复制长度2
    System.out.println(Arrays.toString(ary));//[0, 1, 2, 0]
  • ArrayList

    public boolean add(E e) {
      ensureCapacityInternal(size + 1);  // Increments modCount!!
      elementData[size++] = e;//学习写法:添加到size位置后,size++
      return true;
    }
  • 跳表

    • 升维:增加多级索引Olog(n);随着增加删除索引索引可能需要重建,空间复杂度O(n)

  • 链表

    //双向链表
    class Node {
        public int key, val;
        public Node next, prev;
        public Node(int k, int v) {
            this.key = k;
            this.val = v;
        }
    }

     

一、数组、链表、跳表

 

第二章、常用数据结构与算法

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值