算法学习笔记总结记录(二)

126 阅读2分钟

「这是我参与2022首次更文挑战的第29天,活动详情查看:2022首次更文挑战

3、说一下时间复杂度:1 < O(logn) <O(n) <O(nlogn) <O(n^2) <O(n^k) <O(2^n)

4、斐波那契数列使用的递归的复杂度是O(2^n),因为它可以看作一个颗二叉树,二叉树的高度是 n - 1,由我们的基础知识可以知道,一个高度为k的二叉树最多可以由 2^k - 1个叶子节点,也就是递归过程函数调用的次数,所以时间复杂度为 O(2^n),而空间复杂度就是树的高度 S(n) 在这里插入图片描述

二、链表题

链表题主要方法就是两个指针和递归和循环,我们先从这三个角度去思考。

  • 003-从尾到头打印链表

    办法:递归。不多提醒,你可以直接做出来。时间复杂度O(n)

    public static void method(ListNode p) {
    		if(p == null) {
    			return ;
    		}
    		method(p.next);
    		System.out.println(p.val);
    	}
    
  • 014-链表中倒数第k个结点

    经典的两个指针,一个先动,另外一个等待k。当然java没有指针,他是new两个对象等于原链表,时间复杂度O(n)

    	public static ListNode method(ListNode p,int k) {
    		ListNode p1 = p;
    		ListNode p2 = p;
    		int i = 0;
    		while(p1 != null && i <= k) {
    			p1 = p1.next;
    			i++;
    		}
    		while(p1 != null && p2 != null) {
    			p1 = p1.next;
    			p2 = p2.next;
    		}
    		return p2.next;
    	}
    
  • 015-反转链表

    三个办法,递归,利用栈,循环(这个稍微比较难写),但是复杂度都是O(n)

    // 递归办法1	-- 我给出递归主要是因为我发现我不是很习惯递归返回一个值,下面这个递归是没有返回值的
    	// 我貌似比较喜欢全局变量,也没有错
    	public static ListNode res = new ListNode(0);
    	
    	public static ListNode ReverseList(ListNode listNode) {
    		ListNode a = res;
    		digui(listNode);
    		return a.next;
        }
    	
    	public static void digui(ListNode listNode) {
    		if(listNode != null) {
    			digui(listNode.next);
    			res.next = new ListNode(listNode.val);
    			res = res.next;
            }
        }
    
    	// 递归办法2 --有返回值的
    	public static ListNode res;
    	
    	public static ListNode ReverseList(ListNode listNode) {
    		ListNode a = digui(listNode);
    		return res.next;
        }
    	
    	public static ListNode digui(ListNode listNode) {
    		if(listNode != null) {
    			ListNode res = digui(listNode.next);  // 这一步,你似乎不习惯递归返回值
    			res.next = new ListNode(listNode.val);
    			return res.next; // 因为一定要把这个东西返回,不然没有意义
            }else {
            	ListNode temp = new ListNode(0); // 因为只会进入这里一次
            	res = temp;
            	return temp;
            }
        }
    

    循环算法,我放一张图:

    这个就是中间状态,pre,next,head已经就位。但是正如我文章开头总结的一样,如果考虑最开始的pre=null思考怎么写代码,实在难以理解,无法下手。可以直接从下图的状态开始写,这个时候,我们要做的就是让head指向pre,pre移动到head的位置,next和head都移动到3的位置上。

在这里插入图片描述

public static ListNode method(ListNode p) {
	ListNode pre = null;
	ListNode head = p;
	ListNode next = null;
	while(head != null) {
		next = head.next;
		head.next = pre;
		pre = head;
		head = next;
	}
	return pre;
}