《代码随想录》刷题笔记——数组篇【java实现】

简介: 《代码随想录》刷题笔记——数组篇【java实现】

*二分查找

题目链接

https://leetcode.cn/problems/binary-search/

左闭右闭区间实现

  • 时间复杂度:O(log n)
  • 空间复杂度:O(1)
/**
 * 左闭右闭写法
 *
 * @param nums
 * @param target
 * @return
 */
public static int search1(int[] nums, int target) {
    if (nums == null || nums.length == 0) {
        return -1;
    }
    int left = 0;
    int right = nums.length - 1;
    // 要是没有等号的话,在{5}里面找5就会出问题了
    while (left <= right) {
        int center = (left + right) / 2;
        if (target == nums[center]) {
            return center;
        } else if (target > nums[center]) {
            left = center + 1;
        } else {
            right = center - 1;
        }
    }
    return -1;
}

左闭右开区间实现

  • 时间复杂度:O(log n)
  • 空间复杂度:O(1)
/**
 * 左闭右开写法
 *
 * @param nums
 * @param target
 * @return
 */
public static int search2(int[] nums, int target) {
    if (nums == null || nums.length == 0) {
        return -1;
    }
    int left = 0;
    // 区别点
    int right = nums.length;
    // 区别点
    while (left < right) {
        int center = (left + right) / 2;
        if (target == nums[center]) {
            return center;
        } else if (target > nums[center]) {
            left = center + 1;
        } else {
            // 区别点
            // 虽然已经知道center位置的元素不是要找的元素,但是因为是左闭右开,因此right还是指向center
            // 后面无论怎么循环,都不会再使用到center这个为止,因为center = (left + right) / 2永远小于right
            right = center;
        }
    }
    return -1;
}

*移除元素

题目链接

https://leetcode.cn/problems/remove-element/

暴力求解

  • 时间复杂度:O(n^2)
  • 空间复杂度:O(1)
public static int removeElement(int[] nums, int val) {
    int sameNum = 0;
    int i = 0;
    while (i < nums.length - sameNum) {
        if (val == nums[i]) {
            // 将后面的元素前移过来
            for (int j = i; j < nums.length - 1 - sameNum; j++) {
                nums[j] = nums[j + 1];
            }
            sameNum++;
        }
        if (val == nums[i]) {
            // 前移过来的数值和val一样,将i--
            i--;
        }
        i++;
    }
    return nums.length - sameNum;
}

双指针

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

【思想】

通过一个快指针和慢指针在一个for循环下完成两个for循环的工作,将快指针的值赋给慢指针


slow:新数组存储值的索引,因为每次存储完新数组的值,都会将slow++,因此最后直接返回slow即可,需要返回slow+1


fast:用来去前面探索那些不是val的值,然后将这个值赋给slow对应的位置

/**
 * 双指针
 *
 * @param nums
 * @param val
 * @return
 */
public static int removeElement1(int[] nums, int val) {
    int slow = 0;
    for (int fast = 0; fast < nums.length; fast++) {
        if (nums[fast] != val) {
            // 如果快指针找的数值不是val,就需要将其存储到新数组中
            // 同时slow++,以便存储下一个新数组的值
            nums[slow++] = nums[fast];
        }
    }
    return slow;
}

相向双指针法

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

上面的实现方法并没有改变元素的相对位置,相向双指针方法改变了元素相对位置,但是确保移动最少元素

/**
 * 想向双指针
 *
 * @param nums
 * @param val
 * @return
 */
public static int removeElement(int[] nums, int val) {
    int slow = 0, fast = nums.length - 1;
    while (slow <= fast) {
        // slow赋值为第一个等于val的索引
        while (slow <= fast) {
            if (nums[slow] != val) {
                slow++;
            } else {
                break;
            }
        }
        // fast赋值为最后一个等于val的索引
        while (fast >= slow) {
            if (nums[fast] == val) {
                fast--;
            } else {
                break;
            }
        }
        if (slow < fast) {
            nums[slow++] = nums[fast--];
        }
    }
    // slow最后一定指向的是 新数组末尾元素的下一个元素
    return slow;
}

*有序数组的平方

题目链接

https://leetcode.cn/problems/squares-of-a-sorted-array/

暴力求解

  1. 先对数组的每个元素求平方
  1. 对数组升序排序

时间复杂度:O(n)+排序算法的时间复杂度

双指针

【思路】

数组本身就是非递减顺序的,只不过负数在平方之后可能会变大,因此只需要用两端来比较就能知道那个数字的平方更大

  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

public static int[] sortedSquares(int[] nums) {
    int left = 0, right = nums.length - 1;
    // 用于存储排序之后的结果
    int[] result = new int[nums.length];
    for (int i = nums.length - 1; i >= 0; i--) {
        int leftValue = nums[left];
        int rightValue = nums[right];
        if (leftValue * leftValue >= rightValue * rightValue) {
            result[i] = leftValue * leftValue;
            left++;
        } else {
            result[i] = rightValue * rightValue;
            right--;
        }
        System.out.println(Arrays.toString(result));
    }
    return result;
}

*长度最小的子数组

题目链接

https://leetcode.cn/problems/minimum-size-subarray-sum/

暴力求解

  • 时间复杂度:O(n^2)
  • 空间复杂度:O(1)

注意,子数组是原数组中连续的几个元素的集合

public int minSubArrayLen(int target, int[] nums) {
    // 最小子数组长度
    int minLen = nums.length + 1;
    for (int i = 0; i < nums.length; i++) {
        int sum = 0;
        for (int j = i; j < nums.length; j++) {
            sum += nums[j];
            if (sum >= target) {
                // 已经>=target,可以暂停了
                if ((j - i + 1) < minLen) {
                    minLen = j - i + 1;
                    break;
                }
            }
        }
    }
    return minLen == nums.length + 1 ? 0 : minLen;
}

部分案例已经超出时间限制

滑动窗口

  • 时间复杂度:O(n):不能以为for里放一个while就是O(n^2), 主要是看每一个元素被操作的次数,每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被操作两次,所以时间复杂度是 2 × n 也就是O(n)
  • 空间复杂度:O(1)
/**
 * 滑动窗口
 *
 * @param target
 * @param nums
 * @return
 */
public int minSubArrayLen1(int target, int[] nums) {
    // 最小子数组长度
    int minLen = nums.length + 1;
    int i = 0;
    int sum = 0;
    for (int j = 0; j < nums.length; j++) {
        // j++,窗口终止位置后移一位,sum添加相应的元素
        sum += nums[j];
        while (sum >= target) {
            // 窗口内的元素总和已经超过target,尝试将窗口的起始位置后移,即i++
            if ((j - i + 1) < minLen) {
                minLen = j - i + 1;
            }
            // sum移除窗口起始位置的元素值
            sum -= nums[i++];
        }
    }
    return minLen == nums.length + 1 ? 0 : minLen;
}

螺旋矩阵

【思想】

这道题主要是考代码能力,注意每次循环都是左开右闭就行

【我写的程序】

public static int[][] generateMatrix1(int n) {
    int[][] result = new int[n][n];
    int curNum = 1;
    int target = n * n;
    int initN = n;
    // 圈数
    int cirCleNum = 0;
    while (curNum <= target) {
        if (curNum == target) {
            result[cirCleNum][cirCleNum] = curNum;
            System.out.println("---------------------填中心---------------------");
            for (int i = 0; i < result.length; i++) {
                System.out.println(Arrays.toString(result[i]));
            }
            break;
        }
        // 填上边
        for (int i = 0; i < n - 1; i++) {
            result[cirCleNum][i + cirCleNum] = curNum++;
        }
        System.out.println("---------------------填上边---------------------");
        for (int i = 0; i < result.length; i++) {
            System.out.println(Arrays.toString(result[i]));
        }
        // 填右边
        for (int i = 0; i < n - 1; i++) {
            result[i + cirCleNum][initN - 1 - cirCleNum] = curNum++;
        }
        System.out.println("---------------------填右边---------------------");
        for (int i = 0; i < result.length; i++) {
            System.out.println(Arrays.toString(result[i]));
        }
        // 填下边
        for (int i = n - 1; i > 0; i--) {
            result[initN - 1 - cirCleNum][i + cirCleNum] = curNum++;
        }
        System.out.println("---------------------填下边---------------------");
        for (int i = 0; i < result.length; i++) {
            System.out.println(Arrays.toString(result[i]));
        }
        // 填左边
        for (int i = n - 1; i > 0; i--) {
            result[i + cirCleNum][cirCleNum] = curNum++;
        }
        System.out.println("---------------------填左边---------------------");
        for (int i = 0; i < result.length; i++) {
            System.out.println(Arrays.toString(result[i]));
        }
        System.out.println("======================================================================");
        cirCleNum += 1;
        n -= 2;
    }
    return result;
}

【别人的代码】

public int[][] generateMatrix(int n) {
    int loop = 0;  // 控制循环次数
    int[][] res = new int[n][n];
    int start = 0;  // 每次循环的开始点(start, start)
    int count = 1;  // 定义填充数字
    int i, j;
    while (loop++ < n / 2) { // 判断边界后,loop从1开始
        // 模拟上侧从左到右
        for (j = start; j < n - loop; j++) {
            res[start][j] = count++;
        }
        // 模拟右侧从上到下
        for (i = start; i < n - loop; i++) {
            res[i][j] = count++;
        }
        // 模拟下侧从右到左
        for (; j >= loop; j--) {
            res[i][j] = count++;
        }
        // 模拟左侧从下到上
        for (; i >= loop; i--) {
            res[i][j] = count++;
        }
        start++;
    }
    if (n % 2 == 1) {
        res[start][start] = count;
    }
    return res;
}


目录
相关文章
|
17天前
|
设计模式 Java
Java设计模式:组合模式的介绍及代码演示
组合模式是一种结构型设计模式,用于将多个对象组织成树形结构,并统一处理所有对象。例如,统计公司总人数时,可先统计各部门人数再求和。该模式包括一个通用接口、表示节点的类及其实现类。通过树形结构和节点的通用方法,组合模式使程序更易扩展和维护。
Java设计模式:组合模式的介绍及代码演示
|
3天前
|
存储 安全 Java
Java数组(Arrays)详解
Java 中的数组是一种用于存储固定数量同类型数据的高效数据结构,支持连续内存存储和随机访问。数组可以声明并初始化,通过索引访问和修改元素,获取长度,使用循环遍历,支持多维形式,并可通过 `Arrays` 类的方法进行复制和排序。数组具有固定大小和类型安全的特点,但需注意越界等问题。灵活运用数组能显著提升编程效率。
|
6天前
|
Java
java小工具util系列4:基础工具代码(Msg、PageResult、Response、常量、枚举)
java小工具util系列4:基础工具代码(Msg、PageResult、Response、常量、枚举)
20 5
|
8天前
|
Java API 开发者
探索Java中的Lambda表达式:简洁与强大的代码实践
本文深入探讨Java中Lambda表达式的定义、用法及优势,通过实例展示其如何简化代码、提升可读性,并强调在使用中需注意的兼容性和效率问题。Lambda作为Java 8的亮点功能,不仅优化了集合操作,还促进了函数式编程范式的应用,为开发者提供了更灵活的编码方式。
|
4天前
|
Java 开发者
探索Java中的Lambda表达式:简化你的代码之旅##
【8月更文挑战第62天】 Java 8的发布为开发者带来了诸多新特性,其中最引人注目的无疑是Lambda表达式。这一特性不仅让代码变得更加简洁,还极大地提升了开发的效率。本文将通过实际示例,展示如何利用Lambda表达式来优化我们的代码结构,同时探讨其背后的工作原理和性能考量。 ##
|
7天前
|
Java API 开发者
探索Java中的Lambda表达式:简化代码,提升效率
【9月更文挑战第27天】在Java 8中引入的Lambda表达式为编程带来了革命性的变化。通过简洁的语法和强大的功能,它不仅简化了代码编写过程,还显著提升了程序的执行效率。本文将深入探讨Lambda表达式的本质、用法和优势,并结合实例演示其在实际开发中的应用。无论你是Java新手还是资深开发者,都能从中获得启发,优化你的代码设计。
|
8天前
|
Java Linux Python
Linux环境下 代码java调用python出错
Linux环境下 代码java调用python出错
24 3
|
8天前
|
存储 Java 索引
使用java代码实现左右括号查找
使用java代码实现左右括号查找
|
16天前
|
存储 Java 数据处理
Java 数组的高级用法
在 Java 中,数组不仅可以存储同类型的数据,还支持多种高级用法,如多维数组(常用于矩阵)、动态创建数组、克隆数组、使用 `java.util.Arrays` 进行排序和搜索、与集合相互转换、增强 for 循环遍历、匿名数组传递以及利用 `Arrays.equals()` 比较数组内容。这些技巧能提升代码的灵活性和可读性,适用于更复杂的数据处理场景。
|
8天前
|
JSON Java Maven
关于使用Java-JWT的笔记
这篇文章介绍了使用Java-JWT库来生成和验证JSON Web Tokens (JWT) 的方法。文中解释了JWT的组成,包括头部、载荷和签名,并提供了如何使用java-jwt库生成和验证token的示例代码。此外,还提供了Maven依赖和一些关于token的标准声明和自定义声明的解释。
关于使用Java-JWT的笔记
下一篇
无影云桌面