LeetCode热题100(四)

LeetCode热题100(四)

189. 轮转数组

题目详情

https://leetcode.cn/problems/rotate-array/

给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

示例 1:

复制代码
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]

示例 2:

复制代码
输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释: 
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]

解答过程

一开始是想交换数组元素值,但是思考半天没思考出来,后来发现其实clone新数组会很简单

java 复制代码
public void rotate(int[] nums, int k) {
    int[] clone = nums.clone();
    for (int i = 0; i < nums.length; i++) {
        int index = (i + k) % nums.length;
        nums[index] = clone[i];
    }
}

238. 除了自身以外数组的乘积

题目详情

https://leetcode.cn/problems/product-of-array-except-self/

给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除了 nums[i] 之外其余各元素的乘积 。

题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。

请 **不要使用除法,**且在 O(n) 时间复杂度内完成此题。

示例 1:

复制代码
输入: nums = [1,2,3,4]
输出: [24,12,8,6]

示例 2:

复制代码
输入: nums = [-1,1,0,-3,3]
输出: [0,0,9,0,0]

解答过程

看到题目的第一想法是算出总和,然后去算除自身以外的乘积,后来才注意到不允许除法,看了答案才豁然开朗

java 复制代码
public int[] productExceptSelf(int[] nums) {
    int[] left = new int[nums.length];
    Arrays.fill(left, 1);
    for (int i = 1; i < nums.length; i++) {
        left[i] = nums[i - 1] * left[i - 1];
    }

    int[] right = new int[nums.length];
    Arrays.fill(right, 1);
    for (int i = nums.length - 2; i >= 0; i--) {
        right[i] = nums[i + 1] * right[i + 1];
    }

    int[] answer = new int[nums.length];
    for (int i = 0; i < nums.length; i++) {
        answer[i] = left[i] * right[i];
    }
    return answer;
}

73. 矩阵置零

题目详情

https://leetcode.cn/problems/set-matrix-zeroes/

给定一个 *m* x *n* 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法**。**

示例 1:

复制代码
输入:matrix = [[1,1,1],[1,0,1],[1,1,1]]
输出:[[1,0,1],[0,0,0],[1,0,1]]

示例 2:

复制代码
输入:matrix = [[0,1,2,0],[3,4,5,2],[1,3,1,5]]
输出:[[0,0,0,0],[0,4,5,0],[0,3,1,0]]

解答过程

第一想法是两次遍历 第一次记录所有含0的行号和列号 第二次根据记录修改值 但是再数据过多的时候超时

java 复制代码
public void setZeroes(int[][] matrix) {
    ArrayList<Integer> row = new ArrayList<>();
    ArrayList<Integer> column = new ArrayList<>();
    for (int i = 0; i < matrix.length; i++) {
        for (int j = 0; j < matrix[i].length; j++) {
            if (matrix[i][j] == 0) {
                row.add(i);
                column.add(j);
            }
        }
    }
    for (int i = 0; i < matrix.length; i++) {
        for (int j = 0; j < matrix[i].length; j++) {
            if (row.contains(i) || column.contains(j)) {
                matrix[i][j] = 0;
            }
        }
    }
}

看了官方题解发现确实应该将ArrayList换成boolean[]

  • boolean[] row/col是**数组索引访问**,时间复杂度O(1)
  • ArrayList.contains()是**线性遍历查找**,时间复杂度O(k)
java 复制代码
public void setZeroes(int[][] matrix) {
    boolean[] row = new boolean[matrix.length];
    boolean[] column = new boolean[matrix[0].length];
    for (int i = 0; i < matrix.length; i++) {
        for (int j = 0; j < matrix[i].length; j++) {
            if (matrix[i][j] == 0) {
                row[i] = true;
                column[j] = true;
            }
        }
    }
    for (int i = 0; i < matrix.length; i++) {
        for (int j = 0; j < matrix[i].length; j++) {
            if (row[i] || column[j]) {
                matrix[i][j] = 0;
            }
        }
    }
}

54. 螺旋矩阵

题目详情

https://leetcode.cn/problems/spiral-matrix/

给你一个 mn 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。

示例 1:

复制代码
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]

示例 2:

复制代码
输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]

解答过程

自己没想出解题方式,看了官方解题思路,才解出来,核心思路是碰到越界或已访问的就转向

java 复制代码
public List<Integer> spiralOrder(int[][] matrix) {
    ArrayList<Integer> list = new ArrayList<>();
    int rowSize = matrix.length;
    int columnSize = matrix[0].length;
    if (columnSize == 0) {
        return list;
    }

    int total = rowSize * columnSize;
    boolean[][] visited = new boolean[rowSize][columnSize];

    int row = 0;
    int column = 0;

    // 右、下、左、上
    int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
    int direction = 0;

    while (total > 0) {
        System.out.println(matrix[row][column] + " " + Arrays.toString(directions[direction]));
        list.add(matrix[row][column]);
        visited[row][column] = true;
        int nextRow = row + directions[direction][0];
        int nextColumn = column + directions[direction][1];
        if (nextColumn >= columnSize || nextColumn < 0 || nextRow >= rowSize || nextRow < 0 || visited[nextRow][nextColumn]) {
            direction = (direction + 1) % directions.length;
        }
        row += directions[direction][0];
        column += directions[direction][1];
        total--;
    }
    return list;
}

48. 旋转图像

题目详情

https://leetcode.cn/problems/rotate-image/

给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。

你必须在**原地** 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。

示例 1:

复制代码
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[[7,4,1],[8,5,2],[9,6,3]]

示例 2:

复制代码
输入:matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]
输出:[[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]

解答过程

直接看图可能并不是很直观,看最后的输出结果更明显[i][j]会变更为[rowSize - 1 - j][i]处的数字

java 复制代码
public void rotate(int[][] matrix) {
    int rowSize = matrix.length;
    int columnSize = matrix[0].length;
    int[][] clone = new int[rowSize][columnSize];
    for (int i = 0; i < rowSize; i++) {
        clone[i] = matrix[i].clone();
    }
    for (int i = 0; i < rowSize; i++) {
        for (int j = 0; j < columnSize; j++) {
            matrix[i][j] = clone[rowSize - 1 - j][i];
        }
    }
}

240. 搜索二维矩阵 II

题目详情

https://leetcode.cn/problems/search-a-2d-matrix-ii/

编写一个高效的算法来搜索 *m* x *n* 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:

  • 每行的元素从左到右升序排列。
  • 每列的元素从上到下升序排列。

示例 1:

复制代码
输入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 5
输出:true

示例 2:

复制代码
输入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 20
输出:false

解答过程

再明知target不可能存在的时候要放弃循环

java 复制代码
public boolean searchMatrix(int[][] matrix, int target) {
    for (int i = 0; i < matrix.length; i++) {
        if (matrix[i][0] > target) {
            break;
        }
        for (int j = 0; j < matrix[i].length; j++) {
            if (matrix[i][j] == target) {
                return true;
            }
            if (matrix[i][j] > target) {
                break;
            }
        }
    }
    return false;
}

142. 环形链表 II

题目详情

https://leetcode.cn/problems/linked-list-cycle-ii/

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始 )。如果 pos-1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

示例 1:

复制代码
输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

复制代码
输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

复制代码
输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。

解答过程

利用hashset去判断节点是否遍及过

java 复制代码
public ListNode detectCycle(ListNode head) {
    HashSet<ListNode> nodes = new HashSet<>();
    while (head != null) {
        if (nodes.contains(head)) {
            return head;
        }
        nodes.add(head);
        head = head.next;
    }
    return head;
}

2. 两数相加

题目详情

https://leetcode.cn/problems/add-two-numbers/

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例 1:

复制代码
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.

示例 2:

复制代码
输入:l1 = [0], l2 = [0]
输出:[0]

示例 3:

复制代码
输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]

解题过程

不断便利链表,计算和,并记录是否超过10,逐个进行处理

java 复制代码
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
    ListNode ln = new ListNode(-1);
    ListNode l = ln;
    int decade = 0;
    while (l1 != null || l2 != null || decade != 0) {
        int sum = 0;
        if (l1 != null) {
            sum += l1.val;
            l1 = l1.next;
        }
        if (l2 != null) {
            sum += l2.val;
            l2 = l2.next;
        }
        sum += decade;
        if (sum >= 10) {
            decade = 1;
            sum %= 10;
        } else {
            decade = 0;
        }
        ln.next = new ListNode(sum);
        ln = ln.next;
    }
    return l.next;
}

19. 删除链表的倒数第 N 个结点

题目详情

https://leetcode.cn/problems/remove-nth-node-from-end-of-list/

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

示例 1:

复制代码
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]

示例 2:

复制代码
输入:head = [1], n = 1
输出:[]

示例 3:

复制代码
输入:head = [1,2], n = 1
输出:[1]

解答过程

第一思路是遍历一遍记录节点,执行移除操作,随后重新拼接链表

java 复制代码
public ListNode removeNthFromEnd(ListNode head, int n) {
    ArrayList<ListNode> nodes = new ArrayList<>();
    while (head != null) {
        nodes.add(head);
        head = head.next;
    }
    nodes.remove(nodes.size() - n);
    ListNode ns = new ListNode(-1);
    ListNode ln = ns;
    for (ListNode node : nodes) {
        ns.next = node;
        ns = ns.next;
        ns.next = null;
    }
    return ln.next;
}

24. 两两交换链表中的节点

题目详情

https://leetcode.cn/problems/swap-nodes-in-pairs/

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

示例 1:

复制代码
输入:head = [1,2,3,4]
输出:[2,1,4,3]

示例 2:

复制代码
输入:head = []
输出:[]

示例 3:

复制代码
输入:head = [1]
输出:[1]

解答过程

java 复制代码
public ListNode swapPairs(ListNode head) {
    int c = 0;
    ListNode node1 = null;
    ListNode node2 = null;
    ListNode ln = new ListNode(-1);
    ListNode l = ln;
    while (head != null) {
        c++;
        System.out.println(head.val + " " + c);
        if (c % 2 == 1) {
            node1 = head;
        } else {
            node2 = head;
        }
        if (c % 2 == 0) {
            ListNode temp = node2.next;
            ln.next = node2;
            node2.next = node1;
            node1.next = temp;
            ln = ln.next.next;
            head = node1;
            node1 = null;
            node2 = null;
        }
        head = head.next;
    }
    if (node1 != null) {
        ln.next = node1;
    }
    return l.next;
}

看了官方的思路确实更好,递归

java 复制代码
public ListNode swapPairs(ListNode head) {
    System.out.println(head);
    if (head == null || head.next == null) {
        return head;
    }
    ListNode newHead = head.next;
    head.next = swapPairs(newHead.next);
    newHead.next = head;
    return newHead;
}
相关推荐
相信神话20212 小时前
第零章:新手的第一课:正确认知游戏开发
大数据·数据库·算法·2d游戏编程·godot4·2d游戏开发
汀沿河2 小时前
2 模型预训练、微调、强化学习的格式
人工智能·算法·机器学习
颜酱2 小时前
最小生成树(MST)核心原理 + Kruskal & Prim 算法
javascript·后端·算法
啊哦呃咦唔鱼2 小时前
LeetCode hot100-3 无重复字符的最长子串
算法·leetcode·职场和发展
phltxy3 小时前
算法刷题|模拟思想高频题全解(Java版)
java·开发语言·算法
宵时待雨3 小时前
C++笔记归纳10:继承
开发语言·数据结构·c++·笔记·算法
田梓燊3 小时前
最长的连续序列到底怎么写
算法·哈希算法·散列表
smchaopiao3 小时前
C++20概念(Concepts)入门指南
开发语言·c++·算法
一叶落4383 小时前
LeetCode 21. 合并两个有序链表(C语言详解 | 链表经典题)
c语言·数据结构·c++·算法·leetcode·链表