每日刷题记录 (二十二)

x33g5p2x  于2022-07-14 转载在 其他  
字(4.1k)|赞(0)|评价(0)|浏览(445)

第一题: 109. 有序链表转换二叉搜索树

LeetCode: 109. 有序链表转换二叉搜索树
描述:
给定一个单链表的头节点 head ,其中的元素 按升序排序 ,将其转换为高度平衡的二叉搜索树。

本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差不超过 1。

解题思路:

  1. 这里也是使用二分法, 每次去找中间的节点
  2. 然后中间节点的左半分为左子树, 右半分为右子树
  3. 递归的去链接起来
  4. 注意每次需要把左子树最后一个节点的next置空

代码实现:

  1. class Solution {
  2. public TreeNode sortedListToBST(ListNode head) {
  3. if(head == null) return null;
  4. if(head.next == null) return new TreeNode(head.val);
  5. ListNode fast = head;
  6. ListNode slow = head;
  7. ListNode pre = null;
  8. while(fast != null && fast.next != null) {
  9. fast = fast.next.next;
  10. pre = slow;
  11. slow = slow.next;
  12. }
  13. pre.next = null;
  14. TreeNode root = new TreeNode(slow.val);
  15. root.left = sortedListToBST(head);
  16. root.right = sortedListToBST(slow.next);
  17. return root;
  18. }
  19. }

第二题: 112. 路径总和

LeetCode: 112. 路径总和

描述:
给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false

叶子节点 是指没有子节点的节点。

解题思路:

  1. 递归的进入 如果当前节点是叶子节点, 且targetSum为0, 就返回true, 否则就是false
  2. 遍历到一个节点的时候, 就让targetSum减去该节点值.
  3. 然后递归的进入左右子树.寻找是否有满足要求的叶子节点.
  4. 如果递归到root为空, 说明就没有满足条件的, 返回false;

代码实现:

  1. class Solution {
  2. public boolean hasPathSum(TreeNode root, int targetSum) {
  3. if(root == null) return false;
  4. if(root.left == null && root.right == null) {
  5. if(root.val == targetSum) {
  6. return true;
  7. }else{
  8. return false;
  9. }
  10. }
  11. targetSum -= root.val;
  12. return hasPathSum(root.left, targetSum) || hasPathSum(root.right,targetSum);
  13. }
  14. }

第三题: 179. 最大数

LeetCode: 179. 最大数

描述:
给定一组非负整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。

注意:输出结果可能非常大,所以你需要返回一个字符串而不是整数

解题思路:

  1. 这里将所有的数都转成字符串 加入到优先级队列中.
  2. 这里堆顶放的是组合起来更大的. (o2+o1).compare(o1+o2)
  3. 入堆完之后,再每次都出堆顶元素, 然后用字符串拼接起来.
  4. 如果最后的结果字符串, 首字符是0, 那么直接返回 "0"

代码实现:

  1. class Solution {
  2. public String largestNumber(int[] nums) {
  3. PriorityQueue<String> pq = new PriorityQueue<>((o1,o2) -> ((o2+o1).compareTo(o1+o2)));
  4. for(int num : nums) {
  5. pq.offer(num+"");
  6. }
  7. StringBuilder res = new StringBuilder();
  8. while(!pq.isEmpty()) {
  9. res.append(pq.poll());
  10. }
  11. if(res.charAt(0) == '0') return "0";
  12. return res.toString();
  13. }
  14. }

第四题: 190. 颠倒二进制位

LeetCode: 190. 颠倒二进制位

描述:
颠倒给定的 32 位无符号整数的二进制位。

提示:

  • 请注意,在某些语言(如 Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因为无论整数是有符号的还是无符号的,其内部的二进制表示形式都是相同的。
  • 在 Java 中,编译器使用二进制补码记法来表示有符号整数。因此,在 示例 2 中,输入表示有符号整数 -3,输出表示有符号整数 -1073741825。

解题思路:

  1. 这里直接使用位运算
  2. 求得每一位是否是1, 如果是1就让颠倒位置为1. 为0就让颠倒位置为0
  3. 注意这里的运算配合使用 res |= (n & 1) << (31-i)

代码实现:

  1. public class Solution {
  2. // you need treat n as an unsigned value
  3. public int reverseBits(int n) {
  4. int res = 0;
  5. for(int i = 0; i < 32; i++) {
  6. res |= (n & 1) << (31-i);
  7. n>>=1;
  8. }
  9. return res;
  10. }
  11. }

第五题: 334. 递增的三元子序列

LeetCode: 334. 递增的三元子序列

描述:

给你一个整数数组 nums ,判断这个数组中是否存在长度为 3 的递增子序列。

如果存在这样的三元组下标 (i, j, k) 且满足 i < j < k ,使得 nums[i] < nums[j] < nums[k] ,返回 true ;否则,返回 false

解题思路:

  1. 首先, 如果数组长度小于3, 直接为false
  2. 初始化 first = nums[0], second = Integer.MAX_VALUE
  3. 遍历当前数组
  4. 如果当前数组元素>second, 表示存在第三大的元素, 返回true
  5. 如果当前数组元素 > first, 表示有第二大的元素, 让second = 该元素
  6. 如果是其他情况, 移动first的位置.

代码实现:

  1. class Solution {
  2. public boolean increasingTriplet(int[] nums) {
  3. if(nums.length < 3) return false;
  4. int first = nums[0];
  5. int second = Integer.MAX_VALUE;
  6. for(int num : nums) {
  7. if(num > second) {
  8. return true;
  9. }else if(num > first) {
  10. second = num;
  11. }else{
  12. first = num;
  13. }
  14. }
  15. return false;
  16. }
  17. }

第六题: 350. 两个数组的交集 II

LeetCode: 350. 两个数组的交集 II

描述:
给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。

解题思路:

  1. 首先将两个数组排序.
  2. 定义两个指针, 分别指向两个指针的初始下标.
  3. 如果两个指针下的元素相等, 那么就把这个结果添加到结果集中.
  4. 如果第一个数组的元素大于第二个数组的元素, 那么就让第二个数组找更大的, 让该下标++
  5. 如果第一个数组的元素小于第二个数组的元素, 那么就让第一个数组找更大的, 让该下标++;

代码实现:

  1. class Solution {
  2. public int[] intersect(int[] nums1, int[] nums2) {
  3. List<Integer> list = new ArrayList<>();
  4. Arrays.sort(nums1);
  5. Arrays.sort(nums2);
  6. int i1 = 0;
  7. int i2 = 0;
  8. while(i1 < nums1.length && i2 < nums2.length) {
  9. if(nums1[i1] == nums2[i2]){
  10. list.add(nums1[i1]);
  11. i1++;
  12. i2++;
  13. }else if(nums1[i1] > nums2[i2]){
  14. i2++;
  15. }else{
  16. i1++;
  17. }
  18. }
  19. int[] res = new int[list.size()];
  20. for(int i = 0; i < list.size(); i++) {
  21. res[i] = list.get(i);
  22. }
  23. return res;
  24. }
  25. }

第七题: 395. 至少有 K 个重复字符的最长子串

LeetCode: 395. 至少有 K 个重复字符的最长子串

描述:
给你一个字符串 s 和一个整数 k ,请你找出 s 中的最长子串, 要求该子串中的每一字符出现次数都不少于 k 。返回这一子串的长度。

解题思路:

  1. 记录当前字符串中每个字符出现的次数.
  2. 再次遍历, 如果当前的字符串中有一个字符出现的次数小于k
  3. 那么就分治的方法,去查看左边是否满足, 满足的最大值. 再去查看右边是否满足, 满足的最大值.
  4. 最终记录左右两边的最大值.

代码实现:

  1. class Solution {
  2. public int longestSubstring(String s, int k) {
  3. int[] arr = new int[26];
  4. if(s.length() < k) return 0;
  5. for(char ch : s.toCharArray()) {
  6. arr[ch-'a']++;
  7. }
  8. for(int i = 0; i < s.length(); i++) {
  9. if(arr[s.charAt(i)-'a'] < k) {
  10. int left = longestSubstring(s.substring(0,i),k);
  11. int right = longestSubstring(s.substring(i+1,s.length()),k);
  12. return Math.max(left,right);
  13. }
  14. }
  15. return s.length();
  16. }
  17. }

相关文章