算法

作者: 细雨蒙情 | 来源:发表于2018-06-09 18:57 被阅读13次

一、常见算法

1 斐波那契数列

  • 递归实现
public static int fib(int n) {
        if(n <= 0) return 0;
        if(n == 1) return 1;
        return fib(n-1) + fib(n-2);
    }
  • 递推实现
public static int fib2(int n) {
        int first = 0;
        int second = 1;
        int sum = 0;
        if(n <= 0) return first;
        if(n ==1 ) return second;
        for(int i = 2; i <= n; i++) {
            sum = first + second;
            first = second;
            second = sum;
        }
        return sum;
    }

2、用两个栈实现一个队列。

队列的声明如下,请实现它的两个函数appendTail 和deleteHead,分别完成在队列尾部插入结点和在队列头部删除结点的功能。

public class Test {  
    public static class MList<T> {  
        // 插入栈,只用于插入的数据  
        private Stack<T> stack1 = new Stack<>();  
        // 弹出栈,只用于弹出数据  
        private Stack<T> stack2 = new Stack<>();  
  
        public MList() {  
        }  
          
        // 添加操作,成在队列尾部插入结点  
        public void appendTail(T t) {  
            stack1.add(t);  
        }  
  
        // 删除操作,在队列头部删除结点  
        public T deleteHead() {  
  
            // 先判断弹出栈是否为空,如果为空就将插入栈的所有数据弹出栈,  
            // 并且将弹出的数据压入弹出栈中  
            if (stack2.isEmpty()) {  
                while (!stack1.isEmpty()) {  
                    stack2.add(stack1.pop());  
                }  
            }  
  
            // 如果弹出栈中还没有数据就抛出异常  
            if (stack2.isEmpty()) {  
                throw new RuntimeException("No more element.");  
            }  
  
            // 返回弹出栈的栈顶元素,对应的就是队首元素。  
            return stack2.pop();  
        }  
    }  
}  

二、 链表相关

  • 1、链表反转
  private static Node reverseHead(Node head) {
        if (head == null) {
            return head;
        }

        Node pre = head;
        Node cur = head.nextNode;
        Node next = null;
        while(cur != null){
            next = cur.nextNode;
            cur.nextNode = pre;

            pre = cur;
            cur = next;
        }
//将原本头节点的next指针置为null
        head.nextNode = null;
        return pre;
    }
  • 2、 链表节点删除,O(1)时间复杂度
public class Test {  
    /** 
     * 链表结点 
     */  
    public static class ListNode {  
        int value; // 保存链表的值  
        ListNode next; // 下一个结点  
    }  
  
    /** 
     * 给定单向链表的头指针和一个结点指针,定义一个函数在0(1)时间删除该结点, 
     * 【注意1:这个方法和文本上的不一样,书上的没有返回值,这个因为JAVA引用传递的原因, 
     * 如果删除的结点是头结点,如果不采用返回值的方式,那么头结点永远删除不了】 
     * 【注意2:输入的待删除结点必须是待链表中的结点,否则会引起错误,这个条件由用户进行保证】 
     * 
     * @param head        链表表的头 
     * @param toBeDeleted 待删除的结点 
     * @return 删除后的头结点 
     */  
    public static ListNode deleteNode(ListNode head, ListNode toBeDeleted) {  
  
        // 如果输入参数有空值就返回表头结点  
        if (head == null || toBeDeleted == null) {  
            return head;  
        }  
  
        // 如果删除的是头结点,直接返回头结点的下一个结点  
        if (head == toBeDeleted) {  
            return head.next;  
        }  
  
        // 下面的情况链表至少有两个结点  
  
        // 在多个节点的情况下,如果删除的是最后一个元素  
        if (toBeDeleted.next == null) {  
            // 找待删除元素的前驱  
            ListNode tmp = head;  
            while (tmp.next != toBeDeleted) {  
                tmp = tmp.next;  
            }  
            // 删除待结点  
            tmp.next = null;  
  
        }  
        // 在多个节点的情况下,如果删除的是某个中间结点  
        else {  
            // 将下一个结点的值输入当前待删除的结点  
            toBeDeleted.value = toBeDeleted.next.value;  
            // 待删除的结点的下一个指向原先待删除引号的下下个结点,即将待删除的下一个结点删除  
            toBeDeleted.next = toBeDeleted.next.next;  
        }  
  
        // 返回删除节点后的链表头结点  
        return head;  
    }  
}  

3 有序链表合并
https://github.com/LRH1993/android_interview/blob/master/algorithm/For-offer/14.md
4 链表第一个公共子节点
https://www.cnblogs.com/edisonchou/p/4822675.html

  • 5、链表中倒数第k个结点
public class Test {
    public static class ListNode {
        int value;
        ListNode next;
    }

    /**
     * 输入一个键表,输出该链表中倒数第k 个结点.为了符合大多数人的习惯,
     * 本题从1开始计数,即链表的尾结点是倒数第1个结点.例如一个链表有6个结点,
     * 从头结点开始它们的值依次是1、2、3、4、5 6。这个链表的倒数第3个结点是值为4的结点.
     *
     * @param head 链表的头结点
     * @param k    倒数第k个结点
     * @return 倒数第k个结点
     */
    public static ListNode findKthToTail(ListNode head, int k) {

        // 输入的链表不能为空,并且k大于0
        if (k < 1 || head == null) {
            return null;
        }

        // 指向头结点
        ListNode pointer = head;

        // 倒数第k个结点与倒数第一个结点相隔k-1个位置
        // pointer先走k-1个位置
        for (int i = 1; i < k; i++) {
            // 说明还有结点
            if (pointer.next != null) {
                pointer = pointer.next;
            }
            // 已经没有节点了,但是i还没有到达k-1说明k太大,链表中没有那么多的元素
            else {
                // 返回结果
                return null;
            }

        }

        // pointer还没有走到链表的末尾,那么pointer和head一起走,
        // 当pointer走到最后一个结点即,pointer.next=null时,head就是倒数第k个结点
        while (pointer.next != null) {
            head = head.next;
            pointer = pointer.next;
        }

        // 返回结果
        return head;
    }
}

三、二叉树相关

  • 1、从上往下打印出二叉树的每个结点,同一层的结点按照从左向右的顺序打印。
    思路:
    这道题实质是考查树的遍历算法。从上到下打印二叉树的规律:每一次打印一个结点的时候,如果该结点有子结点, 则把该结点的子结点放到一个队列的末尾。接下来到队列的头部取出最早进入队列的结点,重复前面的打印操作,直至队列中所有的结点都被打印出来为止。
public class Test {
    /**
     * 二叉树的树结点
     */
    public static class BinaryTreeNode {
        int value;
        BinaryTreeNode left;
        BinaryTreeNode right;
    }

    /**
     * 从上往下打印出二叉树的每个结点,向一层的结点按照从左往右的顺序打印。
     * 例如下的二叉树,
     *       8
     *    /    \
     *   6     10
     *  /  \   / \
     * 5   7  9  11
     * 则依次打印出8、6、10、5、3 、9、11.
     *
     * @param root 树的结点
     */
    public static void printFromToBottom(BinaryTreeNode root) {

        // 当结点非空时才进行操作
        if (root != null) {
            // 用于存放还未遍历的元素
            Queue<BinaryTreeNode> list = new LinkedList<>();
            // 将根结点入队
            list.add(root);
            // 用于记录当前处理的结点
            BinaryTreeNode curNode;

            // 队列非空则进行处理
            while (!list.isEmpty()) {
                // 删除队首元素
                curNode = list.remove();
                // 输出队首元素的值
                System.out.print(curNode.value + " ");
                // 如果左子结点不为空,则左子结点入队
                if (curNode.left != null) {
                    list.add(curNode.left);
                }
                // 如果右子结点不为空,则左子结点入队
                if (curNode.right != null) {
                    list.add(curNode.right);
                }
            }
        }
    }
}

相关文章

  • 匈牙利算法

    算法思想 算法流程 算法步骤 算法实现 python 算法应用

  • web开发需要知道的几个算法

    算法分类 快速排序算法 深度优先算法 广度优先算法 堆排序算法 归并排序算法

  • 机器学习算法

    机器学习的算法分监督算法和无监督 算法。监督算法包括回归算法,神经网络,SVM;无监督算法包括聚类算法,降维算法。...

  • 字符串匹配

    BF 算法和 RK 算法BM 算法和 KMP 算法

  • 垃圾回收算法有几种类型? 他们对应的优缺点又是什么?

    常见的垃圾回收算法有: 标记-清除算法、复制算法、标记-整理算法、分代收集算法 标记-清除算法 标记—清除算法包括...

  • 头条-手撕代码

    [toc] 图算法 以及最短路径算法 树算法 手写LRU 排序算法 链表算法

  • 关于一些算法

    我们平常说的算法按照使用方向加密算法,排序算法,搜索算法,优化算法,音视频处理算法,图片处理算法 1.加密解密算法...

  • 给我巨大影响的技术书籍

    算法《算法概论》《算法设计与分析基础》 Anany Levitin《算法引论》Udi Manber《算法导论》《什...

  • 缓存相关

    cache淘汰算法:LIRS 算法 缓存那些事 Redis缓存淘汰算法,LRU算法,LRU算法讲解

  • LZW压缩算法

    参考链接:超级简单的数据压缩算法—LZW算法压缩算法——lzw算法实现LZW算法 LZW 压缩算法正确图解

网友评论

      本文标题:算法

      本文链接:https://www.haomeiwen.com/subject/wpvgrftx.html