LeetCode腾讯精选练习(50 题)

一、数组相关题目

1、LeetCode54:螺旋矩阵

给定一个包含mxn个元素的矩阵(m 行,n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素

示例1:

输入:
[
 [ 1, 2, 3 ],
 [ 4, 5, 6 ],
 [ 7, 8, 9 ]
]
输出: [1,2,3,6,9,8,7,4,5]

示例2:

输入:
[
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9,10,11,12]
]
输出: [1,2,3,4,8,12,11,10,9,5,6,7]

题解:

    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> result = new ArrayList<>();
        if (matrix.length == 0 || matrix[0].length == 0) return result;
        int left = 0, right = matrix[0].length - 1, up = 0, down = matrix.length - 1;
        while (true) {
            //上
            for (int i = left; i <= right; ++i) {
                result.add(matrix[up][i]);
            }
            up++;
            if (up > down) break;
            //右
            for (int i = up; i <= down; ++i) {
                result.add(matrix[i][right]);
            }
            right--;
            if (left > right) break;
            //下
            for (int i = right; i >= left; --i) {
                result.add(matrix[down][i]);
            }
            down--;
            if (up > down) break;
            //左
            for (int i = down; i >= up; --i) {
                result.add(matrix[i][left]);
            }
            left++;
            if (left > right) break;
        }
        return result;
    }

2、LeetCode59:螺旋矩阵 II

给定一个正整数n,生成一个包含1到 n 2 n^2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵

示例:

输入: 3
输出:
[
 [ 1, 2, 3 ],
 [ 8, 9, 4 ],
 [ 7, 6, 5 ]
]

题解:

    public int[][] generateMatrix(int n) {
        int left = 0, right = n - 1, up = 0, down = n - 1;
        int[][] result = new int[n][n];
        int start = 1, end = n * n;
        while (start <= end) {
            for (int i = left; i <= right; ++i) {
                result[up][i] = start++;
            }
            up++;
            for (int i = up; i <= down; ++i) {
                result[i][right] = start++;
            }
            right--;
            for (int i = right; i >= left; --i) {
                result[down][i] = start++;
            }
            down--;
            for (int i = down; i >= up; --i) {
                result[i][left] = start++;
            }
            left++;
        }
        return result;
    }

3、LeetCode238:除自身以外数组的乘积

给定长度为n的整数数组nums,其中n>1,返回输出数组output,其中output[i]等于nums中除nums[i]之外其余各元素的乘积

示例:

输入: [1,2,3,4]
输出: [24,12,8,6]

题解:

    public int[] productExceptSelf(int[] nums) {
        int[] result = new int[nums.length];
        int k = 1;
        for (int i = 0; i < nums.length; ++i) {
            result[i] = k;
            k *= nums[i];//此时数组存储的是除去当前元素左边的元素乘积
        }
        k = 1;
        for (int i = nums.length - 1; i >= 0; --i) {
            result[i] *= k;//k为该数右边的乘积
            k *= nums[i];//此时数组等于左边的*该数右边的
        }
        return result;
    }

二、链表相关题目

1、LeetCode160:相交链表

编写一个程序,找到两个单链表相交的起始节点

扫描二维码关注公众号,回复: 8875871 查看本文章

如下面的两个链表:

在这里插入图片描述
在节点c1开始相交

示例1:

在这里插入图片描述

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Reference of the node with value = 8
输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点

示例2:

在这里插入图片描述

输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Reference of the node with value = 2
输入解释:相交节点的值为 2 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点

示例3:

在这里插入图片描述

输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
输入解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
解释:这两个链表不相交,因此返回 null

解析:

设定两个指针分别指向两个链表头部,一起向前走直到其中一个到达末端,另一个与末端距离则是两链表的长度差。再通过长链表指针先走的方式消除长度差,最终两链表即可同时走到相交点

换个方式消除长度差: 拼接两链表

设长-短链表为C,短-长链表为D (分别代表长链表在前和短链表在前的拼接链表),则当C走到长短链表交接处时,D走在长链表中,且与长链表头距离为长度差:

当ha==hb时跳出,返回即可

题解:

    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode ha = headA, hb = headB;
        while (ha != hb) {
            ha = ha == null ? headB : ha.next;
            hb = hb == null ? headA : hb.next;
        }
        return ha;
    }

2、LeetCode61:旋转链表

给定一个链表,旋转链表,将链表每个节点向右移动k个位置,其中k是非负数

示例1:

输入: 1->2->3->4->5->NULL, k = 2
输出: 4->5->1->2->3->NULL
解释:
向右旋转 1 步: 5->1->2->3->4->NULL
向右旋转 2 步: 4->5->1->2->3->NULL

示例2:

输入: 0->1->2->NULL, k = 4
输出: 2->0->1->NULL
解释:
向右旋转 1 步: 2->0->1->NULL
向右旋转 2 步: 1->2->0->NULL
向右旋转 3 步: 0->1->2->NULL
向右旋转 4 步: 2->0->1->NULL

解析:

循环旋转本质上是将尾部向前数第K个元素作为头,原来的头接到原来的尾上

题解:

    public ListNode rotateRight(ListNode head, int k) {
        if (head == null || k == 0) return head;
        ListNode cursor = head, tail = null;//头指针和尾指针
        int length = 1;
        while (cursor.next != null) {//循环得到总长度
            cursor = cursor.next;
            length++;
        }
        int loop = length - (k % length);//得到循环的次数
        tail = cursor;//指向尾节点
        tail.next = head;//改成循环链表
        cursor = head;//指向头节点
        for (int i = 0; i < loop; ++i) {
            cursor = cursor.next;
            tail = tail.next;
        }
        tail.next = null;//改成单链表
        return cursor;//返回当前头
    }

3、LeetCode23:合并K个排序链表

合并k个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度

示例:

输入:
[
  1->4->5,
  1->3->4,
  2->6
]
输出: 1->1->2->3->4->4->5->6

题解:

    public ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0) return null;
        PriorityQueue<ListNode> queue = new PriorityQueue<>(lists.length, new Comparator<ListNode>() {
            @Override
            public int compare(ListNode node1, ListNode node2) {
                //升序
                return node1.val - node2.val;
                //if (node1.val < node2.val) return -1;
                //else if (node1.val == node2.val) return 0;
                //else return 1;
            }
        });
        ListNode dummy = new ListNode(0);
        ListNode tmp = dummy;
        for (ListNode listNode : lists) {
            if (listNode != null) queue.add(listNode);
        }
        while (!queue.isEmpty()) {
            tmp.next = queue.poll();
            tmp = tmp.next;
            if (tmp.next != null) queue.add(tmp.next);
        }
        return dummy.next;
    }

三、双指针相关题目

1、LeetCode16:最接近的三数之和

给定一个包括n个整数的数组nums和 一个目标值target。找出nums中的三个整数,使得它们的和与target最接近。返回这三个数的和。假定每组输入只存在唯一答案

例如,给定数组 nums = [-1,2,1,-4], 和 target = 1
与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2)

解析:

https://leetcode-cn.com/problems/3sum-closest/solution/hua-jie-suan-fa-16-zui-jie-jin-de-san-shu-zhi-he-b/

题解:

    public int threeSumClosest(int[] nums, int target) {
        Arrays.sort(nums);
        int result = nums[0] + nums[1] + nums[2];
        for (int i = 0; i < nums.length; ++i) {
            int start = i + 1, end = nums.length - 1;
            while (start < end) {
                int sum = nums[i] + nums[start] + nums[end];
                if (Math.abs(target - sum) < Math.abs(target - result))
                    result = sum;
                if (sum > target)
                    end--;
                else if (sum < target)
                    start++;
                else return target;
            }
        }
        return result;
    }

四、优先队列

1、LeetCode215:数组中的第K个最大元素

在未排序的数组中找到第k个最大的元素。请注意,你需要找的是数组排序后的第k个最大的元素,而不是第k个不同的元素

示例1:

输入: [3,2,1,5,6,4] 和 k = 2
输出: 5

示例2:

输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4

题解:

    public int findKthLargest(int[] nums, int k) {
        PriorityQueue<Integer> queue = new PriorityQueue<>(k, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1 - o2;
            }
        });
        for (int num : nums) {
            queue.add(num);
            if (queue.size() > k) {
                queue.poll();
            }
        }
        return queue.peek();
    }

五、二叉树

1、LeetCode230:二叉搜索树中第K小的元素

给定一个二叉搜索树,编写一个函数kthSmallest来查找其中第k个最小的元素

示例1:

输入: root = [3,1,4,null,2], k = 1
   3
  / \
 1   4
  \
   2
输出: 1

示例2:

输入: root = [5,3,6,2,4,null,null,1], k = 3
       5
      / \
     3   6
    / \
   2   4
  /
 1
输出: 3

解析:

二叉搜索树的中序遍历后元素升序排列

题解:

    public int kthSmallest(TreeNode root, int k) {
        List<Integer> list = new ArrayList<>();
        inorder(root, list);
        return list.get(k - 1);
    }

    private void inorder(TreeNode node, List<Integer> list) {
        if (node != null) {
            inorder(node.left, list);
            list.add(node.val);
            inorder(node.right, list);
        }
    }

2、LeetCode124:二叉树中的最大路径和

给定一个非空二叉树,返回其最大路径和

本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点

示例1:

输入: [1,2,3]
       1
      / \
     2   3
输出: 6

示例2:

输入: [-10,9,20,null,null,15,7]
   -10
   / \
  9  20
    /  \
   15   7
输出: 42

题解:

    Integer max = Integer.MIN_VALUE;

    public int maxPathSum(TreeNode root) {
        helper(root);
        return max;
    }

    private int helper(TreeNode node) {
        if (node == null) return 0;
        int left = helper(node.left);
        int right = helper(node.right);
        max = Math.max(max, node.val + left + right);
        return Math.max(0, node.val + Math.max(left, right));
    }

六、位运算相关题目

1、LeetCode136:只出现一次的数字

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素

示例1:

输入: [2,2,1]
输出: 1

示例2:

输入: [4,1,2,1,2]
输出: 4

解析:

如果对0和二进制位做异或运算,得到的仍然是这个二进制位
a ^ 0 = a
如果对相同的二进制位做异或运算,返回的结果是0
a ^ a = 0
异或满足交换律和结合律
a ^ b ^ a = (a ^ a) ^ b = 0 ^ b = b
所以只需要将所有的数进行异或操作,得到那个唯一的数字

题解:

    public int singleNumber(int[] nums) {
        int result = nums[0];
        if (nums.length > 1) {
            for (int i = 1; i < nums.length; ++i) {
                result ^= nums[i];
            }
        }
        return result;
    }
发布了177 篇原创文章 · 获赞 407 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/qq_40378034/article/details/103519344