力扣刷题笔记

文章目录

  • 前言
  • 学习路线
  • 时间/空间复杂度
  • 数组
    • 知识点
    • 力扣27题-移除元素
    • 力扣59题-螺旋矩阵
    • 力扣209题-长度最小子数组
    • 力扣977题-有序数组平方排序
  • 链表
    • 知识点
    • 力扣19题-删除链表的倒数第N个节点
    • 力扣24题-两两交换链表值
    • 力扣25题-K个一组翻转链表
    • 力扣141题-环形链表
    • 142题-环形链表二
  • 总结


前言

本博客仅做学习笔记,如有侵权,联系后即刻更改

科普:


学习路线

参考文章

时间/空间复杂度

参考文章

时间复杂度

时间复杂度考虑最坏时间复杂度

  • T(n) = O(f(n))
    f(n) 是算法代码执行的总步数,也叫操作数
  • O(logn)
    对于对数复杂度来说,不管是以 2、3 为底,通通记作 O(logn)
    在这里插入图片描述
  • 常见时间复杂度
    力扣刷题笔记_第1张图片

空间复杂度

在衡量代码的空间复杂度的时候,只关心运行过程中临时占用的内存空间

  • n 作为数据集大小,f(n) 指的是规模 n 所占存储空间的函数
    在这里插入图片描述

数组

力扣刷题笔记_第2张图片

知识点

for的增强型循环

  • 增强for循环遍历数组时使用的普通for循环,而遍历集合时使用的Iterator迭代器
  • 在使用增强型for循环不支持遍历时删除元素
  • 使用增强型for循环时,对遍历的集合需要做null判断,不然可能引发空指针异常。

快慢指针

  • 使用速度不同的指针(可用在链表、数组、序列等上面),来解决一些问题
  • 快指针 fast 指向当前要和 val 对比的元素,慢指针 slow 指向将被赋值的位置

滑动窗口

  • 一般就用在数组或者字符串上
  • 滑动:窗口可以按照一定的方向移动。
  • 窗口:窗口大小可以固定,也可以不固定,此时可以向外或者向内,扩容或者缩小窗口直至满足条件

模拟题

  • 模拟题本身不涉及算法,就是单纯根据题目所描述的模拟整个过程从而得到最后的结果

力扣27题-移除元素

移除元素

  • 是快慢指针的经典题目

暴力双层循环

class Solution {
    public int removeElement(int[] nums, int val) {
        int num = nums.length;
        for(int i=0; i<num; i++){
            if(nums[i] == val){
                for(int j=i; j<num-1; j++){
                    nums[j] = nums[j+1];
                }
                num--;
                i --;
            }
        }
        return num;
    }
}

快慢指针

class Solution {
    public int removeElement(int[] nums, int val) {
        int slow = 0;
        int fast = 0;
        for(; fast<nums.length; fast++){
            if(nums[fast] != val){
                nums[slow] = nums[fast];
                slow++;
            }
        }
        return slow;
    }
}

力扣59题-螺旋矩阵

  • 题目解析
    这是一道模拟题,难度中等,面试出现频率极高

  • 时空复杂度分析
    矩阵大小为 n²,需要全部遍历且填充,所以时间复杂度为 O(n²)
    此外额外维护了一个大小为 n² 的结果矩阵,所以空间复杂度为 O(n²)

class Solution {
    public int[][] generateMatrix(int n) {
        int w[][]= new int [n][n];
        int s=0,x=n-1,z=0,r=n-1;
        int sum=1,i;
        while(sum <= n*n){
            for(i=z; i<=r; i++)
            w[s][i] = sum++;
            s++; 
            for(i=s; i<=x; i++)
            w[i][r] = sum++;
            r--;
            for(i=r; i>=z; i--)
            w[x][i] = sum++;
            x--;
            for(i=x; i>=s; i--)
            w[i][z] = sum++;
            z++;
        }
        return w;
    }
}

力扣209题-长度最小子数组

滑动窗口

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int right=0, left=0, sum=0, num=Integer.MAX_VALUE;
        for(; right<nums.length;){
            sum += nums[right++];
            while(sum >= target){
                num = Math.min(num, right-left);
                sum -= nums[left++];
            }
        }
        return num == Integer.MAX_VALUE ? 0 : num;
    }
}

力扣977题-有序数组平方排序

双指针法来解决,left 指向下标 0,right 指向下标 n - 1

class Solution {
    public int[] sortedSquares(int[] nums) {
       int right = nums.length-1, left = 0;
       int array[] = new int [nums.length];
       int pos = nums.length-1;

       while(left <= right){
           nums[left] = Math.abs(nums[left]);
           nums[right] = Math.abs(nums[right]);
           if(nums[left] > nums[right])
               array[pos--] = (int)Math.pow(nums[left++], 2);
            else {
                array[pos--] = (int)Math.pow(nums[right--], 2);
            }
       } 
       return array;
    }
}

链表

力扣刷题笔记_第3张图片

知识点

单链表

链表中的每个节点只包含一个指针域

  • 单链表的第一个节点的存储位置叫做头指针
  • 最后一个节点的后继指针为空,一般用 NULL 或者 “^” 表示。
    在这里插入图片描述

双向链表

相比起单链表来说

  • 多了一个前驱指针 prev,指向前驱节点

头指针

链表的必备元素且无论链表是否为空,不能为空

后继指针

下个节点地址的指针

力扣19题-删除链表的倒数第N个节点

快慢指针

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode a = head;
        ListNode b = head;
        for(int i =0; i<n; i++){
            a = a.next;
        }
        // 删除头节点
        if(a == null)   return head.next;
        while(a.next != null){
            a = a.next;
            b = b.next;
        }
        b.next = b.next.next;
        return head;
    }
}

力扣24题-两两交换链表值

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode swapPairs(ListNode head) {
        ListNode fakeNode = new ListNode(0);
        fakeNode.next = head;
        ListNode pre = fakeNode;
        
        while(pre.next != null && pre.next.next != null){
            // 存储相邻两节点的后继节点
            ListNode temp = head.next.next;
            pre.next = head.next;
            head.next.next = head;
            head.next = temp;
            pre = head;
            head =  head.next; 
        }
        return fakeNode.next;
    }
}

力扣25题-K个一组翻转链表

每次循环K个节点,翻转后链接回去

class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode hair = new ListNode(0);
        hair.next = head;
        ListNode pre = hair;

        while (head != null) {
            ListNode tail = pre;
            // 查看剩余部分长度是否大于等于 k
            for (int i = 0; i < k; ++i) {
                tail = tail.next;
                if (tail == null) {
                    return hair.next;
                }
            }
            ListNode nex = tail.next;
            ListNode[] reverse = myReverse(head, tail);
            head = reverse[0];
            tail = reverse[1];
            // 把子链表重新接回原链表
            pre.next = head;
            tail.next = nex;
            pre = tail;
            head = tail.next;
        }

        return hair.next;
    }

    public ListNode[] myReverse(ListNode head, ListNode tail) {
        ListNode prev = tail.next;
        ListNode p = head;
        while (prev != tail) {
            ListNode nex = p.next;
            p.next = prev;
            prev = p;
            p = nex;
        }
        return new ListNode[]{tail, head};
    }
}

力扣141题-环形链表

快慢指针,如果快指针反过来追上了慢指针,则存在环

public class Solution {
    public boolean hasCycle(ListNode head) {
        ListNode s = head, f = head;
        while(f != null && f.next != null){ 
            s = s.next;
            f = f.next.next;
            if(s == f) return true;
        }
        return false;
    }
}

142题-环形链表二

ab = cb,求出相遇节点后,设一个节点从head开始走,和slow相遇的节点即环的入口
力扣刷题笔记_第4张图片

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;

        while(fast != null && fast.next != null){
            slow = slow.next;
            fast = fast.next.next;
            if(slow == fast){
                ListNode flag = head;
                while(flag != slow){
                    flag = flag.next;
                    slow = slow.next;
                }
                return flag;
            }
        }
        return null;
    }
}

总结

小小励志

有些事你现在不做,一辈子都不会做了。
如果你想做一件事,全世界都会为你让路。
《搭车去柏林》

你可能感兴趣的:(力扣刷题,算法)